mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +00:00
Implement native function pointer check, addr conversion and register, update documents (#185)
Modified WASM runtime API: - wasm_runtime_module_malloc() - wasm_runtime_lookup_function() Introduced runtime API - wasm_runtime_register_natives()
This commit is contained in:
parent
2e36149e32
commit
0d3f304191
119
README.md
119
README.md
|
@ -1,17 +1,17 @@
|
|||
WebAssembly Micro Runtime
|
||||
=========================
|
||||
[Building WAMR VM core](./doc/build_wamr.md) | [Embedding WAMR VM core](./doc/embed_wamr.md) | [Building WASM applications](./doc/build_wasm_app.md) | [Samples and demos](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-and-demos)
|
||||
|
||||
**A [Bytecode Alliance][BA] project**
|
||||
|
||||
[BA]: https://bytecodealliance.org/
|
||||
|
||||
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with small footprint. It includes a few parts as below:
|
||||
- The "iwasm" VM core, supporting WebAssembly interpreter, ahead of time compilation (AoT) and Just-in-Time compilation (JIT)
|
||||
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with a small footprint. It includes a few parts as below:
|
||||
- The **"iwasm" VM core**, supporting WebAssembly interpreter, ahead of time compilation (AoT) and Just-in-Time compilation (JIT)
|
||||
|
||||
- The application framework and the supporting API's for the WASM applications
|
||||
- The **application framework** and the supporting API's for the WASM applications
|
||||
|
||||
- The dynamic management of the WASM applications
|
||||
- The **dynamic management** of the WASM applications
|
||||
|
||||
|
||||
|
||||
|
@ -20,16 +20,16 @@ iwasm VM core
|
|||
|
||||
### key features
|
||||
|
||||
- Embeddable with the supporting C API's
|
||||
- [Embeddable with the supporting C API's](./doc/embed_wamr.md)
|
||||
- Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage
|
||||
- Near to native speed by AoT
|
||||
- AoT module loader works for both embedded OS and Linux system
|
||||
- Choices of WASM application libc support: the built-in libc subset for embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc
|
||||
- The mechanism for exporting native API's to WASM applications
|
||||
- Unique AoT support for embedded systems which have no system loaders
|
||||
- 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
|
||||
- [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md)
|
||||
|
||||
### Supported architectures and platforms
|
||||
|
||||
The iwasm supports following architectures:
|
||||
The iwasm supports the following architectures:
|
||||
|
||||
- X86-64, X86-32
|
||||
- ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested)
|
||||
|
@ -38,13 +38,7 @@ The iwasm supports following architectures:
|
|||
|
||||
Following platforms are supported:
|
||||
|
||||
- [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), [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)
|
||||
|
||||
Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform.
|
||||
|
||||
|
@ -55,107 +49,51 @@ Execute following commands to build **wamrc** compiler:
|
|||
```shell
|
||||
cd wamr-compiler
|
||||
./build_llvm.sh
|
||||
mkdir build
|
||||
cd build
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
ln -s ./wamrc /usr/bin/wamrc
|
||||
```
|
||||
|
||||
After build is completed, create a symbolic link **/usr/bin/wamrc** to the generated wamrc.
|
||||
|
||||
### 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)**.
|
||||
|
||||
### Embed WAMR VM core
|
||||
|
||||
WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. For the details, see [embed WAMR VM core](./doc/embed_wamr.md).
|
||||
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)**.
|
||||
|
||||
|
||||
|
||||
Application framework
|
||||
===================================
|
||||
|
||||
By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some efforts.
|
||||
By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some effort.
|
||||
|
||||
The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, which are based on the event driven programming model. Here are the supporting API sets by the [WAMR application library](./doc/wamr_api.md) :
|
||||
The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, that are based on the event driven programming model. Here are the supporting API sets by the [WAMR application framework library](./doc/wamr_api.md) :
|
||||
|
||||
- Timer
|
||||
- Micro service (Request/Response) and Pub/Sub inter-app communication
|
||||
- Sensor
|
||||
- Connectivity and data transmission
|
||||
- 2D graphic UI (based on littlevgl)
|
||||
- Timer, Inter-app communication (request/response and pub/sub), Sensor, Connectivity and data transmission, 2D graphic UI
|
||||
|
||||
Every subfolder under [WAMR application framework](./core/app-framework) folder is a compilation configurable component. The developers can copy the template folder to create new components to the application framework. If a component needs to export native functions to the WASM application, refer to the [export_native_api.md](./doc/export_native_api.md) .
|
||||
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 from 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.
|
||||
|
||||
|
||||
|
||||
<img src="./doc/pics/wamr-arch.JPG" width="80%">
|
||||
|
||||
The tool [host_tool](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from cloud.
|
||||
The WAMR application manager supports remote application management 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.
|
||||
|
||||
The tool [host_tool](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from the host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from the cloud.
|
||||
|
||||
Browse the folder [core/app-mgr](./core/app-mgr) for the details.
|
||||
|
||||
WAMR SDK
|
||||
==========
|
||||
|
||||
The **wamr-sdk** tools build the WAMR to both **runtime SDK** for embedding by your native codes and **APP SDK** for developing the WASM applications. A SDK profile presents a configuration of build parameters for the selection of CPU arch, software platforms, execution mode, libc and application framework components.
|
||||
Usually there are two tasks for integrating the WAMR into a particular project:
|
||||
|
||||
**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK.
|
||||
- Select what WAMR components (vmcore, libc, app-mgr, app-framework components) to be integrated, and get the associated source files added into the project building configuration
|
||||
- Generate the APP SDK for developing the WASM apps on the selected libc and framework components
|
||||
|
||||
### Menu configuration for building SDK
|
||||
|
||||
Menu configuration is supported for easy integration of runtime components and application libraries for the target architecture and platform.
|
||||
|
||||
```
|
||||
cd wamr-sdk
|
||||
./build_sdk.sh -i -n [profile name]
|
||||
```
|
||||
|
||||
<img src="./doc/pics/wamr_menu_config.png" alt="wamr build menu configuration" style="zoom:80%;" />
|
||||
|
||||
After the menu configuration is finished, the building process is automatically started. When the building gets successful, the SDK package is generated under folder $wamr-sdk/out/{profile}, and the header files of configured components were copied into the SDK package.
|
||||
|
||||
The directory structure of a SDK package with profile name "simple":
|
||||
|
||||
```
|
||||
simple/
|
||||
├── app-sdk
|
||||
│ ├── libc-builtin-sysroot
|
||||
│ │ ├── include
|
||||
│ │ └── share
|
||||
│ └── wamr-app-framework
|
||||
│ ├── include
|
||||
│ │ ├── bi-inc
|
||||
│ │ └── wa-inc
|
||||
│ ├── lib
|
||||
│ └── share
|
||||
└── runtime-sdk
|
||||
├── include
|
||||
│ └── bi-inc
|
||||
└── lib
|
||||
```
|
||||
The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. It supports menu configuration for selecting WAMR components and builds the WAMR to a SDK package that includes **runtime SDK** and **APP SDK**. The runtime SDK is used for building the native application and the APP SDK should be shipped to WASM application developers.
|
||||
|
||||
|
||||
|
||||
### Use Runtime SDK
|
||||
|
||||
The folder "**runtime-sdk**" contains all the header files and library files for integration with project native code.
|
||||
|
||||
### Build WASM applications with APP-SDK
|
||||
|
||||
The folder “**app-sdk**” contains all the header files and WASM library for developing the WASM application. For C/C++ based WASM applications, the developers can use conventional cross-compilation procedure to build the WASM application. Refer to [build WASM applications](./doc/build_wasm_app.md) for the details.
|
||||
|
||||
|
||||
|
||||
|
||||
Samples and demos
|
||||
Samples
|
||||
=================
|
||||
|
||||
The WAMR samples integrate the iwasm VM core, application manager and selected application framework components. The samples are located in folder [samples](./samples):
|
||||
|
@ -164,9 +102,6 @@ The WAMR samples integrate the iwasm VM core, application manager and selected a
|
|||
- **[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.
|
||||
|
||||
|
||||
The graphic user interface demo photo:
|
||||
|
||||
![WAMR samples diagram](./doc/pics/vgl_demo.png "WAMR samples diagram")
|
||||
|
||||
|
||||
Releases and acknowledgments
|
||||
|
@ -182,7 +117,7 @@ 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.
|
||||
Please submit issues for any new feature request or your plan for contributing new features.
|
||||
|
||||
|
||||
License
|
||||
|
|
125
core/app-framework/README.md
Normal file
125
core/app-framework/README.md
Normal file
|
@ -0,0 +1,125 @@
|
|||
Application framework
|
||||
=======
|
||||
|
||||
## Directory structure
|
||||
|
||||
|
||||
|
||||
This folder "app-native-shared" is for the source files shared by both WASM APP and native runtime
|
||||
|
||||
- The c files in this directory are compiled into both the WASM APP and runtime.
|
||||
- The header files for distributing to SDK are placed in the "bi-inc" folder.
|
||||
|
||||
|
||||
|
||||
This folder "template" contains a pre-defined directory structure for a framework component. The developers can copy the template folder to create new components to the application framework.
|
||||
|
||||
|
||||
|
||||
Every other subfolder is framework component. Each component contains two library parts: **app and native**.
|
||||
|
||||
- The "base" component provide timer API and inter-app communication support. It must be enabled if other components are selected.
|
||||
- Under the "app" folder of a component, the subfolder "wa_inc" holds all header files that should be included by the WASM applications
|
||||
|
||||
|
||||
|
||||
## Application framework basic model
|
||||
|
||||
The app framework is built on top of two fundamental operations:
|
||||
|
||||
- [Native calls into WASM function](../../doc/embed_wamr.md)
|
||||
|
||||
- [WASM app calls into native API](../../doc/export_native_api.md)
|
||||
|
||||
Asynchronized programming model is supported for WASM applications
|
||||
|
||||
- Every WASM app has its own sandbox and thread
|
||||
|
||||
- Queue and messaging
|
||||
|
||||
<img src="../../doc/pics/app_framework.PNG" style="zoom:67%;" />
|
||||
|
||||
|
||||
|
||||
## Customized building of app framework
|
||||
|
||||
A component can be compilation configurable to the runtime. The wamr SDK tool "build_sdk.sh" supports menu config to select app components for building a customized runtime.
|
||||
|
||||
A number of CMAKE variables are defined to control build of framework and components. You can create a cmake file for defining these variables and include it in the CMakeList.txt for your software, or pass it in "-x" argument when run the [build_sdk.sh](../../wamr-sdk/build_sdk.sh) for building the runtime SDK.
|
||||
|
||||
```cmake
|
||||
set (WAMR_BUILD_APP_FRAMEWORK 1)
|
||||
set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE)
|
||||
```
|
||||
|
||||
Variables:
|
||||
|
||||
- **WAMR_BUILD_APP_FRAMEWORK**: enable the application framework
|
||||
- **WAMR_BUILD_APP_LIST**: the selected components to be built into the final runtime
|
||||
|
||||
|
||||
|
||||
The configuration file can be generated through the wamr-sdk menu config:
|
||||
|
||||
```bash
|
||||
cd wamr-sdk
|
||||
./build_sdk -n [profile] -i
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Create new components
|
||||
|
||||
Generally you should follow following steps to create a new component:
|
||||
|
||||
- Copy the “template” for creating a new folder
|
||||
|
||||
- Implement the app part
|
||||
|
||||
- If your component exports native function to WASM, ensure your created a header file under app for declaring the function prototype.
|
||||
- If you component provides header files for the WASM applications to include, ensure it is placed under subfolder "wa_inc".
|
||||
|
||||
- Implement the native part
|
||||
|
||||
- If your native function is exported to WASM, you need to create an inl file for the registration. It can be any file name, assuming the file name is "my_component.inl" here:
|
||||
|
||||
```c
|
||||
//use right signature for your functions
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_2, "(i)i"),
|
||||
```
|
||||
|
||||
- Ensure "wasm_lib.cmake" is provided as it will be included by the WAMR SDK building script
|
||||
|
||||
- Add a definition in "wasm_lib.cmake" for your component, e.g.
|
||||
|
||||
```cmake
|
||||
add_definitions (-DAPP_FRAMEWORK_MY_COMPONENT)
|
||||
```
|
||||
|
||||
- Modify the file [app_ext_lib_export.c](./app_ext_lib_export.c) to register native APIs exported for the new introduced component. Skip it if not exporting native functions.
|
||||
|
||||
```
|
||||
#include "lib_export.h"
|
||||
|
||||
...
|
||||
#ifdef APP_FRAMEWORK_MY_COMPONENT // this definition is created in wasm_lib.cmake
|
||||
#include "my_component_native_api.h"
|
||||
#endif
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
...
|
||||
#ifdef APP_FRAMEWORK_MY_COMPONENT
|
||||
#include "my_component.inl"
|
||||
#endif
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Sensor component working flow
|
||||
|
||||
|
||||
|
||||
![](../../doc/pics/sensor_callflow.PNG)
|
||||
|
|
@ -26,8 +26,8 @@
|
|||
#define addr_native_to_app(ptr) \
|
||||
wasm_runtime_addr_native_to_app(module_inst, ptr)
|
||||
|
||||
#define module_malloc(size) \
|
||||
wasm_runtime_module_malloc(module_inst, size)
|
||||
#define module_malloc(size, p_native_addr) \
|
||||
wasm_runtime_module_malloc(module_inst, size, p_native_addr)
|
||||
|
||||
#define module_free(offset) \
|
||||
wasm_runtime_module_free(module_inst, offset)
|
||||
|
|
39
core/app-framework/app_ext_lib_export.c
Normal file
39
core/app-framework/app_ext_lib_export.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "lib_export.h"
|
||||
|
||||
#ifdef APP_FRAMEWORK_SENSOR
|
||||
#include "sensor_native_api.h"
|
||||
#endif
|
||||
|
||||
#ifdef APP_FRAMEWORK_CONNECTION
|
||||
#include "connection_native_api.h"
|
||||
#endif
|
||||
|
||||
#ifdef APP_FRAMEWORK_WGL
|
||||
#include "gui_native_api.h"
|
||||
#endif
|
||||
|
||||
/* More header file here */
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#ifdef APP_FRAMEWORK_SENSOR
|
||||
#include "runtime_sensor.inl"
|
||||
#endif
|
||||
|
||||
#ifdef APP_FRAMEWORK_CONNECTION
|
||||
#include "connection.inl"
|
||||
#endif
|
||||
|
||||
#ifdef APP_FRAMEWORK_WGL
|
||||
#include "wamr_gui.inl"
|
||||
#endif
|
||||
|
||||
/* More inl file here */
|
||||
};
|
||||
|
||||
int
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis)
|
||||
{
|
||||
*p_ext_lib_apis = extended_native_symbol_defs;
|
||||
return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
|
||||
}
|
||||
|
|
@ -1,8 +1,15 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
|
||||
add_definitions (-DWASM_ENABLE_APP_FRAMEWORK=1)
|
||||
|
||||
set (APP_FRAMEWORK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE )
|
||||
LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${CMAKE_CURRENT_LIST_DIR}/app_ext_lib_export.c)
|
||||
endif()
|
||||
|
||||
# app-native-shared and base are required
|
||||
include (${APP_FRAMEWORK_ROOT_DIR}/app-native-shared/native_interface.cmake)
|
||||
LIST (APPEND WASM_APP_SOURCE_ALL ${NATIVE_INTERFACE_SOURCE})
|
||||
|
@ -31,10 +38,6 @@ function (add_module_native arg)
|
|||
|
||||
LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_CURRENT_SOURCE})
|
||||
set (WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_SOURCE_ALL} PARENT_SCOPE)
|
||||
|
||||
# VARIABLES in function are only used in this scope,
|
||||
# set PARENT_SCOPE to pass to top CMakeLists
|
||||
set (WASM_LIB_BASE_SOURCE ${WASM_LIB_BASE_SOURCE} PARENT_SCOPE)
|
||||
endfunction ()
|
||||
|
||||
function (add_module_app arg)
|
||||
|
@ -83,4 +86,4 @@ else ()
|
|||
endif ()
|
||||
ENDFOREACH (dir)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
EXPORT_WASM_API(wasm_register_resource),
|
||||
EXPORT_WASM_API(wasm_response_send),
|
||||
EXPORT_WASM_API(wasm_post_request),
|
||||
EXPORT_WASM_API(wasm_sub_event),
|
||||
EXPORT_WASM_API(wasm_create_timer),
|
||||
EXPORT_WASM_API(wasm_timer_destroy),
|
||||
EXPORT_WASM_API(wasm_timer_cancel),
|
||||
EXPORT_WASM_API(wasm_timer_restart),
|
||||
EXPORT_WASM_API(wasm_get_sys_tick_ms),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_register_resource, "($)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_response_send, "(*~)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_post_request, "(*~)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_sub_event, "($)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_create_timer, "(iii)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_timer_destroy, "(i)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_timer_cancel, "(i)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_timer_restart, "(ii)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_get_sys_tick_ms, "()i"),
|
||||
|
|
|
@ -14,19 +14,13 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
bool
|
||||
wasm_response_send(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size);
|
||||
wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size);
|
||||
void
|
||||
wasm_register_resource(wasm_exec_env_t exec_env,
|
||||
int32 url_offset);
|
||||
wasm_register_resource(wasm_exec_env_t exec_env, char *url);
|
||||
void
|
||||
wasm_post_request(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size);
|
||||
wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size);
|
||||
void
|
||||
wasm_sub_event(wasm_exec_env_t exec_env,
|
||||
int32 url_offset);
|
||||
|
||||
|
||||
wasm_sub_event(wasm_exec_env_t exec_env, char *url);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -11,17 +11,8 @@
|
|||
extern void module_request_handler(request_t *request, void *user_data);
|
||||
|
||||
bool
|
||||
wasm_response_send(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size)
|
||||
wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
if (!validate_app_addr(buffer_offset, size))
|
||||
return false;
|
||||
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
response_t response[1];
|
||||
|
||||
|
@ -37,15 +28,9 @@ wasm_response_send(wasm_exec_env_t exec_env,
|
|||
}
|
||||
|
||||
void
|
||||
wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset)
|
||||
wasm_register_resource(wasm_exec_env_t exec_env, char *url)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *url = NULL;
|
||||
|
||||
if (!validate_app_str_addr(url_offset))
|
||||
return;
|
||||
|
||||
url = addr_app_to_native(url_offset);
|
||||
|
||||
if (url != NULL) {
|
||||
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App,
|
||||
|
@ -56,16 +41,9 @@ wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset)
|
|||
}
|
||||
|
||||
void
|
||||
wasm_post_request(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size)
|
||||
wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
if (!validate_app_addr(buffer_offset, size))
|
||||
return;
|
||||
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
request_t req[1];
|
||||
|
@ -91,15 +69,9 @@ wasm_post_request(wasm_exec_env_t exec_env,
|
|||
}
|
||||
|
||||
void
|
||||
wasm_sub_event(wasm_exec_env_t exec_env, int32 url_offset)
|
||||
wasm_sub_event(wasm_exec_env_t exec_env, char *url)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *url = NULL;
|
||||
|
||||
if (!validate_app_str_addr(url_offset))
|
||||
return;
|
||||
|
||||
url = addr_app_to_native(url_offset);
|
||||
|
||||
if (url != NULL) {
|
||||
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
EXPORT_WASM_API(wasm_open_connection),
|
||||
EXPORT_WASM_API(wasm_close_connection),
|
||||
EXPORT_WASM_API(wasm_send_on_connection),
|
||||
EXPORT_WASM_API(wasm_config_connection),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_open_connection, "($*~)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_close_connection, "(i)"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_send_on_connection, "(i*~)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_config_connection, "(i*~)i"),
|
||||
|
|
|
@ -20,16 +20,16 @@ extern "C" {
|
|||
|
||||
uint32
|
||||
wasm_open_connection(wasm_exec_env_t exec_env,
|
||||
int32 name_offset, int32 args_offset, uint32 len);
|
||||
char *name, char *args_buf, uint32 len);
|
||||
void
|
||||
wasm_close_connection(wasm_exec_env_t exec_env,
|
||||
uint32 handle);
|
||||
int
|
||||
wasm_send_on_connection(wasm_exec_env_t exec_env,
|
||||
uint32 handle, int32 data_offset, uint32 len);
|
||||
uint32 handle, char *data, uint32 len);
|
||||
bool
|
||||
wasm_config_connection(wasm_exec_env_t exec_env,
|
||||
uint32 handle, int32 cfg_offset, uint32 len);
|
||||
uint32 handle, char *cfg_buf, uint32 len);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,17 +16,10 @@
|
|||
|
||||
uint32
|
||||
wasm_open_connection(wasm_exec_env_t exec_env,
|
||||
int32 name_offset, int32 args_offset, uint32 len)
|
||||
char *name, char *args_buf, uint32 len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
attr_container_t *args;
|
||||
char *name, *args_buf;
|
||||
|
||||
if (!validate_app_str_addr(name_offset) ||
|
||||
!validate_app_addr(args_offset, len) ||
|
||||
!(name = addr_app_to_native(name_offset)) ||
|
||||
!(args_buf = addr_app_to_native(args_offset)))
|
||||
return -1;
|
||||
|
||||
args = (attr_container_t *)args_buf;
|
||||
|
||||
|
@ -45,15 +38,8 @@ wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle)
|
|||
|
||||
int
|
||||
wasm_send_on_connection(wasm_exec_env_t exec_env,
|
||||
uint32 handle, int32 data_offset, uint32 len)
|
||||
uint32 handle, char *data, uint32 len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *data;
|
||||
|
||||
if (!validate_app_addr(data_offset, len) ||
|
||||
!(data = addr_app_to_native(data_offset)))
|
||||
return -1;
|
||||
|
||||
if (connection_impl._send != NULL)
|
||||
return connection_impl._send(handle, data, len);
|
||||
|
||||
|
@ -62,16 +48,10 @@ wasm_send_on_connection(wasm_exec_env_t exec_env,
|
|||
|
||||
bool
|
||||
wasm_config_connection(wasm_exec_env_t exec_env,
|
||||
uint32 handle, int32 cfg_offset, uint32 len)
|
||||
uint32 handle, char *cfg_buf, uint32 len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *cfg_buf;
|
||||
attr_container_t *cfg;
|
||||
|
||||
if (!validate_app_addr(cfg_offset, len) ||
|
||||
!(cfg_buf = addr_app_to_native(cfg_offset)))
|
||||
return false;
|
||||
|
||||
cfg = (attr_container_t *)cfg_buf;
|
||||
|
||||
if (connection_impl._config != NULL)
|
||||
|
|
|
@ -5,6 +5,9 @@ set (WASM_LIB_CONN_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|||
|
||||
include_directories(${WASM_LIB_CONN_DIR})
|
||||
|
||||
add_definitions (-DAPP_FRAMEWORK_CONNECTION)
|
||||
|
||||
|
||||
include (${CMAKE_CURRENT_LIST_DIR}/${WAMR_BUILD_PLATFORM}/connection_mgr.cmake)
|
||||
|
||||
file (GLOB source_all
|
||||
|
|
|
@ -135,15 +135,9 @@ wasm_sensor_config(wasm_exec_env_t exec_env,
|
|||
|
||||
uint32
|
||||
wasm_sensor_open(wasm_exec_env_t exec_env,
|
||||
int32 name_offset, int instance)
|
||||
char *name, int instance)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *name = NULL;
|
||||
|
||||
if (!validate_app_str_addr(name_offset))
|
||||
return -1;
|
||||
|
||||
name = addr_app_to_native(name_offset);
|
||||
|
||||
if (name != NULL) {
|
||||
sensor_client_t *c;
|
||||
|
@ -192,17 +186,8 @@ wasm_sensor_open(wasm_exec_env_t exec_env,
|
|||
|
||||
bool
|
||||
wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env,
|
||||
uint32 sensor, int32 buffer_offset,
|
||||
int len)
|
||||
uint32 sensor, char *buffer, int len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
if (!validate_app_addr(buffer_offset, len))
|
||||
return false;
|
||||
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
attr_container_t *cfg = (attr_container_t *)buffer;
|
||||
sensor_obj_t s = find_sys_sensor_id(sensor);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
EXPORT_WASM_API(wasm_sensor_open),
|
||||
EXPORT_WASM_API(wasm_sensor_config),
|
||||
EXPORT_WASM_API(wasm_sensor_config_with_attr_container),
|
||||
EXPORT_WASM_API(wasm_sensor_close),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_sensor_open, "($i)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_sensor_config, "(iiii)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_sensor_config_with_attr_container, "(i*~)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_sensor_close, "(i)i"),
|
||||
|
|
|
@ -19,12 +19,11 @@ wasm_sensor_config(wasm_exec_env_t exec_env,
|
|||
int bit_cfg, int delay);
|
||||
uint32
|
||||
wasm_sensor_open(wasm_exec_env_t exec_env,
|
||||
int32 name_offset, int instance);
|
||||
char *name, int instance);
|
||||
|
||||
bool
|
||||
wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env,
|
||||
uint32 sensor, int32 buffer_offset,
|
||||
int len);
|
||||
uint32 sensor, char *buffer, int len);
|
||||
|
||||
bool
|
||||
wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
set (WASM_LIB_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
add_definitions (-DAPP_FRAMEWORK_SENSOR)
|
||||
|
||||
include_directories(${WASM_LIB_SENSOR_DIR})
|
||||
|
||||
|
||||
|
|
|
@ -20,23 +20,23 @@ extern "C" {
|
|||
|
||||
void
|
||||
wasm_obj_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc);
|
||||
int32 func_id, uint32 *argv, uint32 argc);
|
||||
|
||||
void
|
||||
wasm_btn_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc);
|
||||
int32 func_id, uint32 *argv, uint32 argc);
|
||||
|
||||
void
|
||||
wasm_label_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc);
|
||||
int32 func_id, uint32 *argv, uint32 argc);
|
||||
|
||||
void
|
||||
wasm_cb_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc);
|
||||
int32 func_id, uint32 *argv, uint32 argc);
|
||||
|
||||
void
|
||||
wasm_list_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc);
|
||||
int32 func_id, uint32 *argv, uint32 argc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -4,25 +4,25 @@
|
|||
*/
|
||||
|
||||
/* button */
|
||||
EXPORT_WASM_API(wasm_btn_native_call),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_btn_native_call, "(i*i)"),
|
||||
|
||||
/* obj */
|
||||
EXPORT_WASM_API(wasm_obj_native_call),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_obj_native_call, "(i*i)"),
|
||||
|
||||
/* label */
|
||||
EXPORT_WASM_API(wasm_label_native_call),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_label_native_call, "(i*i)"),
|
||||
|
||||
/* cont */
|
||||
//EXPORT_WASM_API(wasm_cont_native_call),
|
||||
//EXPORT_WASM_API_WITH_SIG(wasm_cont_native_call, "(i*i)"),
|
||||
|
||||
/* page */
|
||||
//EXPORT_WASM_API(wasm_page_native_call),
|
||||
//EXPORT_WASM_API_WITH_SIG(wasm_page_native_call, "(i*i)"),
|
||||
|
||||
/* list */
|
||||
EXPORT_WASM_API(wasm_list_native_call),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_list_native_call, "(i*i)"),
|
||||
|
||||
/* drop down list */
|
||||
//EXPORT_WASM_API(wasm_ddlist_native_call),
|
||||
//EXPORT_WASM_API_WITH_SIG(wasm_ddlist_native_call, "(i*i)"),
|
||||
|
||||
/* check box */
|
||||
EXPORT_WASM_API(wasm_cb_native_call),
|
||||
EXPORT_WASM_API_WITH_SIG(wasm_cb_native_call, "(i*i)"),
|
||||
|
|
|
@ -6,6 +6,7 @@ set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|||
set (DEPS_DIR ${WASM_LIB_GUI_DIR}/../../../deps)
|
||||
|
||||
add_definitions(-DLV_CONF_INCLUDE_SIMPLE)
|
||||
add_definitions (-DAPP_FRAMEWORK_WGL)
|
||||
|
||||
include_directories(${WASM_LIB_GUI_DIR}
|
||||
${DEPS_DIR}
|
||||
|
|
|
@ -126,7 +126,7 @@ static WGLNativeFuncDef btn_native_func_defs[] = {
|
|||
/*************** Native Interface to Wasm App ***********/
|
||||
void
|
||||
wasm_btn_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
int32 func_id, uint32 *argv, uint32 argc)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
@ -135,6 +135,6 @@ wasm_btn_native_call(wasm_exec_env_t exec_env,
|
|||
btn_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argv,
|
||||
argc);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static WGLNativeFuncDef cb_native_func_defs[] = {
|
|||
/*************** Native Interface to Wasm App ***********/
|
||||
void
|
||||
wasm_cb_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
int32 func_id, uint32 *argv, uint32 argc)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
@ -82,6 +82,6 @@ wasm_cb_native_call(wasm_exec_env_t exec_env,
|
|||
cb_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argv,
|
||||
argc);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ static WGLNativeFuncDef label_native_func_defs[] = {
|
|||
/*************** Native Interface to Wasm App ***********/
|
||||
void
|
||||
wasm_label_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
int32 func_id, uint32 *argv, uint32 argc)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
@ -73,6 +73,6 @@ wasm_label_native_call(wasm_exec_env_t exec_env,
|
|||
label_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argv,
|
||||
argc);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ static WGLNativeFuncDef list_native_func_defs[] = {
|
|||
/*************** Native Interface to Wasm App ***********/
|
||||
void
|
||||
wasm_list_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
int32 func_id, uint32 *argv, uint32 argc)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
@ -58,6 +58,6 @@ wasm_list_native_call(wasm_exec_env_t exec_env,
|
|||
list_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argv,
|
||||
argc);
|
||||
}
|
||||
|
|
|
@ -109,17 +109,11 @@ void wgl_native_func_call(wasm_module_inst_t module_inst,
|
|||
WGLNativeFuncDef *funcs,
|
||||
uint32 size,
|
||||
int32 func_id,
|
||||
uint32 argv_offset,
|
||||
uint32 *argv,
|
||||
uint32 argc)
|
||||
{
|
||||
WGLNativeFuncDef *func_def = funcs;
|
||||
WGLNativeFuncDef *func_def_end = func_def + size;
|
||||
uint32 *argv;
|
||||
|
||||
if (!validate_app_addr(argv_offset, argc * sizeof(uint32)))
|
||||
return;
|
||||
|
||||
argv = addr_app_to_native(argv_offset);
|
||||
|
||||
while (func_def < func_def_end) {
|
||||
if (func_def->func_id == func_id) {
|
||||
|
|
|
@ -74,7 +74,7 @@ void wgl_native_func_call(wasm_module_inst_t module_inst,
|
|||
WGLNativeFuncDef *funcs,
|
||||
uint32 size,
|
||||
int32 func_id,
|
||||
uint32 argv_offset,
|
||||
uint32 *argv,
|
||||
uint32 argc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -378,7 +378,7 @@ static WGLNativeFuncDef obj_native_func_defs[] = {
|
|||
/*************** Native Interface to Wasm App ***********/
|
||||
void
|
||||
wasm_obj_native_call(wasm_exec_env_t exec_env,
|
||||
int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
int32 func_id, uint32 *argv, uint32 argc)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
@ -387,6 +387,6 @@ wasm_obj_native_call(wasm_exec_env_t exec_env,
|
|||
obj_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argv,
|
||||
argc);
|
||||
}
|
||||
|
|
10
core/app-mgr/README.md
Normal file
10
core/app-mgr/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
WASM application management
|
||||
=======
|
||||
|
||||
## structure
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<img src="../../doc/pics/wamr-arch.JPG" width="80%">
|
|
@ -735,42 +735,13 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode)
|
||||
destroy_import_funcs(AOTImportFunc *import_funcs,
|
||||
bool is_jit_mode)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_free(import_funcs);
|
||||
}
|
||||
|
||||
static void*
|
||||
resolve_sym(const char *module_name, const char *field_name)
|
||||
{
|
||||
void *sym;
|
||||
|
||||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
if ((sym = wasm_native_lookup_libc_builtin_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if ((sym = wasm_native_lookup_libc_wasi_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BASE_LIB != 0
|
||||
if ((sym = wasm_native_lookup_base_lib_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
if ((sym = wasm_native_lookup_extension_lib_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_import_funcs(const uint8 **p_buf, const uint8 *buf_end,
|
||||
AOTModule *module,
|
||||
|
@ -804,13 +775,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end,
|
|||
"invalid function type index.");
|
||||
return false;
|
||||
}
|
||||
import_funcs[i].func_type = module->func_types[import_funcs[i].func_type_index];
|
||||
read_string(buf, buf_end, import_funcs[i].module_name);
|
||||
read_string(buf, buf_end, import_funcs[i].func_name);
|
||||
|
||||
module_name = import_funcs[i].module_name;
|
||||
field_name = import_funcs[i].func_name;
|
||||
if (!(import_funcs[i].func_ptr_linked =
|
||||
resolve_sym(module_name, field_name))) {
|
||||
wasm_native_resolve_symbol(module_name, field_name,
|
||||
import_funcs[i].func_type,
|
||||
&import_funcs[i].signature))) {
|
||||
LOG_WARNING("warning: fail to link import function (%s, %s)\n",
|
||||
module_name, field_name);
|
||||
}
|
||||
|
@ -2053,46 +2027,61 @@ aot_unload(AOTModule *module)
|
|||
#if WASM_ENABLE_JIT != 0
|
||||
if (module->comp_data)
|
||||
aot_destroy_comp_data(module->comp_data);
|
||||
|
||||
if (module->comp_ctx)
|
||||
aot_destroy_comp_context(module->comp_ctx);
|
||||
|
||||
if (module->wasm_module)
|
||||
wasm_loader_unload(module->wasm_module);
|
||||
#endif
|
||||
|
||||
if (module->mem_init_data_list)
|
||||
destroy_mem_init_data_list(module->mem_init_data_list,
|
||||
module->mem_init_data_count,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->table_init_data_list)
|
||||
destroy_table_init_data_list(module->table_init_data_list,
|
||||
module->table_init_data_count,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->func_types)
|
||||
destroy_func_types(module->func_types,
|
||||
module->func_type_count,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->import_globals)
|
||||
destroy_import_globals(module->import_globals,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->globals)
|
||||
destroy_globals(module->globals,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->import_funcs)
|
||||
destroy_import_funcs(module->import_funcs,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->export_funcs)
|
||||
destroy_export_funcs(module->export_funcs,
|
||||
module->is_jit_mode);
|
||||
|
||||
if (module->func_type_indexes)
|
||||
wasm_free(module->func_type_indexes);
|
||||
|
||||
if (module->func_ptrs)
|
||||
wasm_free(module->func_ptrs);
|
||||
|
||||
if (module->const_str_set)
|
||||
bh_hash_map_destroy(module->const_str_set);
|
||||
|
||||
if (module->code)
|
||||
bh_munmap(module->code, module->code_size);
|
||||
|
||||
if (module->data_sections)
|
||||
destroy_object_data_sections(module->data_sections,
|
||||
module->data_section_count);
|
||||
|
||||
wasm_free(module);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ typedef struct {
|
|||
REG_SYM(aot_set_exception_with_id), \
|
||||
REG_SYM(aot_get_exception), \
|
||||
REG_SYM(aot_is_wasm_type_equal), \
|
||||
REG_SYM(aot_invoke_native), \
|
||||
REG_SYM(wasm_runtime_enlarge_memory), \
|
||||
REG_SYM(wasm_runtime_set_exception), \
|
||||
REG_SYM(fmin), \
|
||||
|
|
|
@ -28,7 +28,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
/* Initialize import global data */
|
||||
for (i = 0; i < module->import_global_count; i++, import_global++) {
|
||||
bh_assert(import_global->data_offset ==
|
||||
p - (uint8*)module_inst->global_data.ptr);
|
||||
(uint32)(p - (uint8*)module_inst->global_data.ptr));
|
||||
memcpy(p, &import_global->global_data_linked, import_global->size);
|
||||
p += import_global->size;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
/* Initialize defined global data */
|
||||
for (i = 0; i < module->global_count; i++, global++) {
|
||||
bh_assert(global->data_offset ==
|
||||
p - (uint8*)module_inst->global_data.ptr);
|
||||
(uint32)(p - (uint8*)module_inst->global_data.ptr));
|
||||
init_expr = &global->init_expr;
|
||||
switch (init_expr->init_expr_type) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
|
@ -53,7 +53,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
p += global->size;
|
||||
}
|
||||
|
||||
bh_assert(module_inst->global_data_size == p - (uint8*)module_inst->global_data.ptr);
|
||||
bh_assert(module_inst->global_data_size ==
|
||||
(uint32)(p - (uint8*)module_inst->global_data.ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -420,65 +421,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst)
|
|||
wasm_free(module_inst);
|
||||
}
|
||||
|
||||
static bool
|
||||
check_type(uint8 type, const char *p)
|
||||
{
|
||||
const char *str = "i32";
|
||||
|
||||
if (strlen(p) < 3)
|
||||
return false;
|
||||
|
||||
switch (type) {
|
||||
case VALUE_TYPE_I32:
|
||||
str = "i32";
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
str = "i64";
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
str = "f32";
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
str = "f64";
|
||||
break;
|
||||
}
|
||||
if (strncmp(p, str, 3))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_function_type(const WASMType *type,
|
||||
const char *signature)
|
||||
{
|
||||
uint32 i;
|
||||
const char *p = signature;
|
||||
|
||||
if (!p || *p++ != '(')
|
||||
return false;
|
||||
|
||||
for (i = 0; i < type->param_count; i++) {
|
||||
if (!check_type(type->types[i], p))
|
||||
return false;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
if (*p++ != ')')
|
||||
return false;
|
||||
|
||||
if (type->result_count) {
|
||||
if (!check_type(type->types[type->param_count], p))
|
||||
return false;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AOTFunctionInstance*
|
||||
aot_lookup_function(const AOTModuleInstance *module_inst,
|
||||
const char *name, const char *signature)
|
||||
|
@ -486,13 +428,10 @@ aot_lookup_function(const AOTModuleInstance *module_inst,
|
|||
uint32 i;
|
||||
AOTModule *module = (AOTModule*)module_inst->aot_module.ptr;
|
||||
|
||||
for (i = 0; i < module->export_func_count; i++) {
|
||||
if (!strcmp(module->export_funcs[i].func_name, name)
|
||||
&& check_function_type(module->export_funcs[i].func_type,
|
||||
signature))
|
||||
for (i = 0; i < module->export_func_count; i++)
|
||||
if (!strcmp(module->export_funcs[i].func_name, name))
|
||||
return &module->export_funcs[i];
|
||||
}
|
||||
|
||||
(void)signature;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -517,8 +456,8 @@ aot_call_function(WASMExecEnv *exec_env,
|
|||
{
|
||||
AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst;
|
||||
AOTFuncType *func_type = function->func_type;
|
||||
bool ret = wasm_runtime_invoke_native(function->func_ptr, func_type,
|
||||
exec_env, argv, argc, argv);
|
||||
bool ret = wasm_runtime_invoke_native(exec_env, function->func_ptr,
|
||||
func_type, NULL, argv, argc, argv);
|
||||
return ret && !aot_get_exception(module_inst) ? true : false;
|
||||
}
|
||||
|
||||
|
@ -612,11 +551,14 @@ aot_clear_exception(AOTModuleInstance *module_inst)
|
|||
}
|
||||
|
||||
int32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size)
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr)
|
||||
{
|
||||
uint8 *addr =
|
||||
mem_allocator_malloc(module_inst->heap_handle.ptr, size);
|
||||
|
||||
if (p_native_addr)
|
||||
*p_native_addr = addr;
|
||||
if (!addr) {
|
||||
aot_set_exception(module_inst, "out of memory");
|
||||
return 0;
|
||||
|
@ -641,10 +583,11 @@ int32
|
|||
aot_module_dup_data(AOTModuleInstance *module_inst,
|
||||
const char *src, uint32 size)
|
||||
{
|
||||
int32 buffer_offset = aot_module_malloc(module_inst, size);
|
||||
char *buffer;
|
||||
int32 buffer_offset = aot_module_malloc(module_inst, size,
|
||||
(void**)&buffer);
|
||||
|
||||
if (buffer_offset != 0) {
|
||||
char *buffer;
|
||||
buffer = aot_addr_app_to_native(module_inst, buffer_offset);
|
||||
memcpy(buffer, src, size);
|
||||
}
|
||||
|
@ -858,3 +801,35 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
|||
|
||||
return wasm_type_equal(type1, type2);
|
||||
}
|
||||
|
||||
void
|
||||
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
AOTModuleInstance *module_inst = (AOTModuleInstance*)
|
||||
wasm_runtime_get_module_inst(exec_env);
|
||||
AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
|
||||
uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
|
||||
uint32 func_type_idx = func_type_indexes[func_idx];
|
||||
AOTFuncType *func_type = aot_module->func_types[func_type_idx];
|
||||
void **func_ptrs = (void**)module_inst->func_ptrs.ptr;
|
||||
void *func_ptr = func_ptrs[func_idx];
|
||||
AOTImportFunc *import_func;
|
||||
const char *signature = NULL;
|
||||
char buf[128];
|
||||
|
||||
if (func_idx < aot_module->import_func_count) {
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
if (!func_ptr) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
import_func->module_name, import_func->func_name);
|
||||
aot_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
signature = import_func->signature;
|
||||
}
|
||||
wasm_runtime_invoke_native(exec_env, func_ptr,
|
||||
func_type, signature, frame_lp, argc, argv_ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ typedef struct AOTModule {
|
|||
/* is jit mode or not */
|
||||
bool is_jit_mode;
|
||||
|
||||
#if WASM_ENABLE_JIT
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
WASMModule *wasm_module;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTCompData *comp_data;
|
||||
|
@ -379,7 +379,8 @@ void
|
|||
aot_clear_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
int32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size);
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
||||
void
|
||||
aot_module_free(AOTModuleInstance *module_inst, int32 ptr);
|
||||
|
@ -431,6 +432,13 @@ bool
|
|||
aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
||||
uint32 type1_idx, uint32 type2_idx);
|
||||
|
||||
/**
|
||||
* Invoke native function from aot code
|
||||
*/
|
||||
void
|
||||
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
|
||||
|
||||
uint32
|
||||
aot_get_plt_table_size();
|
||||
|
||||
|
|
|
@ -20,6 +20,14 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
|||
return NULL;
|
||||
|
||||
memset(exec_env, 0, (uint32)total_size);
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (!(exec_env->argv_buf = wasm_malloc(sizeof(uint32) * 64))) {
|
||||
wasm_free(exec_env);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
exec_env->module_inst = module_inst;
|
||||
exec_env->wasm_stack_size = stack_size;
|
||||
exec_env->wasm_stack.s.top_boundary =
|
||||
|
@ -31,6 +39,9 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
|||
void
|
||||
wasm_exec_env_destroy(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
wasm_free(exec_env->argv_buf);
|
||||
#endif
|
||||
wasm_free(exec_env);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ typedef struct WASMExecEnv {
|
|||
/* The WASM module instance of current thread */
|
||||
struct WASMModuleInstanceCommon *module_inst;
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
uint32 *argv_buf;
|
||||
#endif
|
||||
|
||||
/* Current interpreter frame of current thread */
|
||||
struct WASMInterpFrame *cur_frame;
|
||||
|
||||
|
|
|
@ -4,44 +4,124 @@
|
|||
*/
|
||||
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "bh_log.h"
|
||||
|
||||
|
||||
typedef struct NativeSymbol {
|
||||
const char *symbol;
|
||||
void *func_ptr;
|
||||
} NativeSymbol;
|
||||
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);
|
||||
|
||||
uint32
|
||||
get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
|
||||
uint32
|
||||
get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
|
||||
|
||||
uint32
|
||||
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
|
||||
|
||||
uint32
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
||||
|
||||
static bool
|
||||
sort_symbol_ptr(NativeSymbol *ptr, int len)
|
||||
check_symbol_signature(const WASMType *type, const char *signature)
|
||||
{
|
||||
int i, j;
|
||||
NativeSymbol temp;
|
||||
const char *p = signature, *p_end;
|
||||
char sig_map[] = { 'F', 'f', 'I', 'i' }, sig;
|
||||
uint32 i = 0;
|
||||
|
||||
for (i = 0; i < len - 1; ++i) {
|
||||
for (j = i + 1; j < len; ++j) {
|
||||
if (strcmp((ptr+i)->symbol, (ptr+j)->symbol) > 0) {
|
||||
temp = ptr[i];
|
||||
ptr[i] = ptr[j];
|
||||
ptr[j] = temp;
|
||||
if (!p || strlen(p) < 2)
|
||||
return false;
|
||||
|
||||
p_end = p + strlen(signature);
|
||||
|
||||
if (*p++ != '(')
|
||||
return false;
|
||||
|
||||
if ((uint32)(p_end - p) < 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])
|
||||
/* normal parameter */
|
||||
continue;
|
||||
|
||||
if (type->types[i] != VALUE_TYPE_I32)
|
||||
/* pointer and string must be i32 type */
|
||||
return false;
|
||||
|
||||
if (sig == '*') {
|
||||
/* it is a pointer */
|
||||
if (i + 1 < type->param_count
|
||||
&& type->types[i + 1] == VALUE_TYPE_I32
|
||||
&& *p == '~') {
|
||||
/* pointer length followed */
|
||||
i++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else if (sig == '$') {
|
||||
/* it is a string */
|
||||
}
|
||||
else {
|
||||
/* invalid signature */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p++ != ')')
|
||||
return false;
|
||||
|
||||
if (type->result_count) {
|
||||
if (p >= p_end)
|
||||
return false;
|
||||
if (*p++ != sig_map[type->types[i] - VALUE_TYPE_F64])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
|
||||
{
|
||||
uint32 i, j;
|
||||
NativeSymbol temp;
|
||||
|
||||
for (i = 0; i < n_native_symbols - 1; i++) {
|
||||
for (j = i + 1; j < n_native_symbols; j++) {
|
||||
if (strcmp(native_symbols[i].symbol,
|
||||
native_symbols[j].symbol) > 0) {
|
||||
temp = native_symbols[i];
|
||||
native_symbols[i] = native_symbols[j];
|
||||
native_symbols[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
lookup_symbol(NativeSymbol *ptr, int len, const char *symbol)
|
||||
lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
const char *symbol, const char **p_signature)
|
||||
{
|
||||
int low = 0, mid, ret;
|
||||
int high = len - 1;
|
||||
int high = n_native_symbols - 1;
|
||||
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
ret = strcmp(symbol, ptr[mid].symbol);
|
||||
|
||||
if (ret == 0)
|
||||
return ptr[mid].func_ptr;
|
||||
ret = strcmp(symbol, native_symbols[mid].symbol);
|
||||
if (ret == 0) {
|
||||
*p_signature = native_symbols[mid].signature;
|
||||
return native_symbols[mid].func_ptr;
|
||||
}
|
||||
else if (ret < 0)
|
||||
high = mid - 1;
|
||||
else
|
||||
|
@ -51,75 +131,135 @@ lookup_symbol(NativeSymbol *ptr, int len, const char *symbol)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
const WASMType *func_type, const char **p_signature)
|
||||
{
|
||||
NativeSymbolsNode *node, *node_next;
|
||||
const char *signature = NULL;
|
||||
void *func_ptr = NULL;
|
||||
|
||||
node = g_native_symbols_list;
|
||||
while (node) {
|
||||
node_next = node->next;
|
||||
if (!strcmp(node->module_name, module_name)) {
|
||||
if ((func_ptr = lookup_symbol(node->native_symbols,
|
||||
node->n_native_symbols,
|
||||
field_name, &signature))
|
||||
|| (field_name[0] == '_'
|
||||
&& (func_ptr = lookup_symbol(node->native_symbols,
|
||||
node->n_native_symbols,
|
||||
field_name + 1, &signature))))
|
||||
break;
|
||||
}
|
||||
node = node_next;
|
||||
}
|
||||
|
||||
if (func_ptr) {
|
||||
if (signature && signature[0] != '\0') {
|
||||
/* signature is not empty, check its format */
|
||||
if (!check_symbol_signature(func_type, signature)) {
|
||||
LOG_WARNING("failed to check signature '%s' and resolve "
|
||||
"pointer params for import function (%s %s)\n",
|
||||
signature, module_name, field_name);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
/* Save signature for runtime to do pointer check and
|
||||
address conversion */
|
||||
*p_signature = signature;
|
||||
}
|
||||
else
|
||||
/* signature is empty */
|
||||
*p_signature = NULL;
|
||||
}
|
||||
|
||||
return func_ptr;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
{
|
||||
NativeSymbolsNode *node;
|
||||
|
||||
if (!(node = bh_malloc(sizeof(NativeSymbolsNode))))
|
||||
return false;
|
||||
|
||||
node->module_name = module_name;
|
||||
node->native_symbols = native_symbols;
|
||||
node->n_native_symbols = n_native_symbols;
|
||||
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;
|
||||
}
|
||||
|
||||
sort_symbol_ptr(native_symbols, n_native_symbols);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_init()
|
||||
{
|
||||
NativeSymbol *native_symbols;
|
||||
uint32 n_native_symbols;
|
||||
|
||||
#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))
|
||||
return false;
|
||||
|
||||
n_native_symbols = get_spectest_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("spectest",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("wasi_unstable",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BASE_LIB != 0
|
||||
static bool is_base_lib_sorted = false;
|
||||
static NativeSymbol *base_native_symbol_defs;
|
||||
static int base_native_symbol_len;
|
||||
n_native_symbols = get_base_lib_export_apis(&native_symbols);
|
||||
if (n_native_symbols > 0
|
||||
&& !wasm_native_register_natives("env",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
int
|
||||
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
|
||||
#if WASM_ENABLE_APP_FRAMEWORK != 0
|
||||
n_native_symbols = get_ext_lib_export_apis(&native_symbols);
|
||||
if (n_native_symbols > 0
|
||||
&& !wasm_native_register_natives("env",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
void *
|
||||
wasm_native_lookup_base_lib_func(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (strcmp(module_name, "env"))
|
||||
return NULL;
|
||||
|
||||
if (!is_base_lib_sorted) {
|
||||
base_native_symbol_len = get_base_lib_export_apis(&base_native_symbol_defs);
|
||||
|
||||
if (base_native_symbol_len > 0)
|
||||
sort_symbol_ptr(base_native_symbol_defs, base_native_symbol_len);
|
||||
|
||||
is_base_lib_sorted = true;
|
||||
}
|
||||
|
||||
if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len,
|
||||
func_name))
|
||||
|| (func_name[0] == '_'
|
||||
&& (ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len,
|
||||
func_name + 1))))
|
||||
return ret;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_BASE_LIB */
|
||||
|
||||
static bool is_ext_lib_sorted = false;
|
||||
static NativeSymbol *ext_native_symbol_defs;
|
||||
static int ext_native_symbol_len;
|
||||
|
||||
int
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
||||
|
||||
void *
|
||||
wasm_native_lookup_extension_lib_func(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (strcmp(module_name, "env"))
|
||||
return NULL;
|
||||
|
||||
if (!is_ext_lib_sorted) {
|
||||
ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs);
|
||||
|
||||
if (ext_native_symbol_len > 0)
|
||||
sort_symbol_ptr(ext_native_symbol_defs, ext_native_symbol_len);
|
||||
|
||||
is_ext_lib_sorted = true;
|
||||
}
|
||||
|
||||
if ((ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len,
|
||||
func_name))
|
||||
|| (func_name[0] == '_'
|
||||
&& (ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len,
|
||||
func_name + 1))))
|
||||
return ret;
|
||||
|
||||
return NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_destroy()
|
||||
{
|
||||
NativeSymbolsNode *node, *node_next;
|
||||
|
||||
node = g_native_symbols_list;
|
||||
while (node) {
|
||||
node_next = node->next;
|
||||
bh_free(node);
|
||||
node = node_next;
|
||||
}
|
||||
|
||||
g_native_symbols_list = g_native_symbols_list_end = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,82 +7,66 @@
|
|||
#define _WASM_NATIVE_H
|
||||
|
||||
#include "bh_common.h"
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
#include "../interpreter/wasm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Lookup native function implementation of a given import function
|
||||
* in libc builtin API's
|
||||
*
|
||||
* @param module_name the module name of the import function
|
||||
* @param func_name the function name of the import function
|
||||
*
|
||||
* @return return the native function pointer if success, NULL otherwise
|
||||
*/
|
||||
void *
|
||||
wasm_native_lookup_libc_builtin_func(const char *module_name,
|
||||
const char *func_name);
|
||||
typedef struct NativeSymbol {
|
||||
const char *symbol;
|
||||
void *func_ptr;
|
||||
const char *signature;
|
||||
} NativeSymbol;
|
||||
|
||||
typedef struct NativeSymbolsNode {
|
||||
struct NativeSymbolsNode *next;
|
||||
const char *module_name;
|
||||
NativeSymbol *native_symbols;
|
||||
uint32 n_native_symbols;
|
||||
} NativeSymbolsNode, *NativeSymbolsList;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
/**
|
||||
* Lookup global variable of a given import global
|
||||
* in libc builtin globals
|
||||
* from libc builtin globals
|
||||
*
|
||||
* @param module_name the module name of the import global
|
||||
* @param global_name the global name of the import global
|
||||
* @param global return the global data
|
||||
*
|
||||
* @param return true if success, false otherwise
|
||||
* @param true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
wasm_native_lookup_libc_builtin_global(const char *module_name,
|
||||
const char *global_name,
|
||||
WASMGlobalImport *global);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Lookup native function implementation of a given import function
|
||||
* in libc wasi API's
|
||||
* Resolve native symbol in all libraries, including libc-builtin, libc-wasi,
|
||||
* base lib and extension lib, and user registered natives
|
||||
* function, which can be auto checked by vm before calling native function
|
||||
*
|
||||
* @param module_name the module name of the import function
|
||||
* @param func_name the function name of the import function
|
||||
* @param func_type the function prototype of the import function
|
||||
* @param p_signature output the signature if resolve success
|
||||
*
|
||||
* @return return the native function pointer if success, NULL otherwise
|
||||
* @return the native function pointer if success, NULL otherwise
|
||||
*/
|
||||
void *
|
||||
wasm_native_lookup_libc_wasi_func(const char *module_name,
|
||||
const char *func_name);
|
||||
void*
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
const WASMType *func_type, const char **p_signature);
|
||||
|
||||
/**
|
||||
* Lookup native function implementation of a given import function
|
||||
* in base lib API's
|
||||
*
|
||||
* @param module_name the module name of the import function
|
||||
* @param func_name the function name of the import function
|
||||
*
|
||||
* @return return the native function pointer if success, NULL otherwise
|
||||
*/
|
||||
void *
|
||||
wasm_native_lookup_base_lib_func(const char *module_name,
|
||||
const char *func_name);
|
||||
bool
|
||||
wasm_native_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
/**
|
||||
* Lookup native function implementation of a given import function
|
||||
* in extension lib API's
|
||||
*
|
||||
* @param module_name the module name of the import function
|
||||
* @param func_name the function name of the import function
|
||||
*
|
||||
* @return return the native function pointer if success, NULL otherwise
|
||||
*/
|
||||
void *
|
||||
wasm_native_lookup_extension_lib_func(const char *module_name,
|
||||
const char *func_name);
|
||||
bool
|
||||
wasm_native_init();
|
||||
|
||||
void
|
||||
wasm_native_destroy();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -35,12 +35,18 @@ wasm_runtime_init()
|
|||
if (vm_thread_sys_init() != 0)
|
||||
return false;
|
||||
|
||||
if (wasm_native_init() == false) {
|
||||
wasm_runtime_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_destroy()
|
||||
{
|
||||
wasm_native_destroy();
|
||||
vm_thread_sys_destroy();
|
||||
}
|
||||
|
||||
|
@ -342,15 +348,18 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst)
|
|||
}
|
||||
|
||||
int32
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size)
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
|
||||
void **p_native_addr)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_module_malloc((WASMModuleInstance*)module_inst, size);
|
||||
return wasm_module_malloc((WASMModuleInstance*)module_inst, size,
|
||||
p_native_addr);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_module_malloc((AOTModuleInstance*)module_inst, size);
|
||||
return aot_module_malloc((AOTModuleInstance*)module_inst, size,
|
||||
p_native_addr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -691,20 +700,17 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
total_size = sizeof(size_t) * (uint64)argc;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(offset_argv_offsets = wasm_runtime_module_malloc
|
||||
(module_inst, (uint32)total_size))
|
||||
(module_inst, (uint32)total_size,
|
||||
(void**)&argv_offsets))
|
||||
|| argv_buf_len >= UINT32_MAX
|
||||
|| !(offset_argv_buf = wasm_runtime_module_malloc
|
||||
(module_inst, (uint32)argv_buf_len))) {
|
||||
(module_inst, (uint32)argv_buf_len,
|
||||
(void**)&argv_buf))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Init wasi environment failed: allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
argv_offsets = (size_t*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_argv_offsets);
|
||||
argv_buf = (char*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_argv_buf);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
argv_offsets[i] = argv_buf_offset;
|
||||
bh_strcpy_s(argv_buf + argv_buf_offset,
|
||||
|
@ -718,20 +724,17 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
total_size = sizeof(size_t) * (uint64)argc;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(offset_env_offsets = wasm_runtime_module_malloc
|
||||
(module_inst, (uint32)total_size))
|
||||
(module_inst, (uint32)total_size,
|
||||
(void**)&env_offsets))
|
||||
|| env_buf_len >= UINT32_MAX
|
||||
|| !(offset_env_buf = wasm_runtime_module_malloc
|
||||
(module_inst, (uint32)env_buf_len))) {
|
||||
(module_inst, (uint32)env_buf_len,
|
||||
(void**)&env_buf))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Init wasi environment failed: allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
env_offsets = (size_t*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_env_offsets);
|
||||
env_buf = (char*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_env_buf);
|
||||
|
||||
for (i = 0; i < env_count; i++) {
|
||||
env_offsets[i] = env_buf_offset;
|
||||
bh_strcpy_s(env_buf + env_buf_offset,
|
||||
|
@ -740,23 +743,20 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
}
|
||||
|
||||
if (!(offset_curfds = wasm_runtime_module_malloc
|
||||
(module_inst, sizeof(struct fd_table)))
|
||||
(module_inst, sizeof(struct fd_table), (void**)&curfds))
|
||||
|| !(offset_prestats = wasm_runtime_module_malloc
|
||||
(module_inst, sizeof(struct fd_prestats)))
|
||||
(module_inst, sizeof(struct fd_prestats), (void**)&prestats))
|
||||
|| !(offset_argv_environ = wasm_runtime_module_malloc
|
||||
(module_inst, sizeof(struct argv_environ_values)))) {
|
||||
(module_inst, sizeof(struct argv_environ_values),
|
||||
(void**)&argv_environ))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Init wasi environment failed: allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
curfds = wasi_ctx->curfds = (struct fd_table*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_curfds);
|
||||
prestats = wasi_ctx->prestats = (struct fd_prestats*)
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset_prestats);
|
||||
argv_environ = wasi_ctx->argv_environ =
|
||||
(struct argv_environ_values*)wasm_runtime_addr_app_to_native
|
||||
(module_inst, offset_argv_environ);
|
||||
wasi_ctx->curfds = curfds;
|
||||
wasi_ctx->prestats = prestats;
|
||||
wasi_ctx->argv_environ = argv_environ;
|
||||
|
||||
fd_table_init(curfds);
|
||||
fd_prestats_init(prestats);
|
||||
|
@ -1064,13 +1064,14 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
|
|||
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(argv_buf_offset =
|
||||
wasm_runtime_module_malloc(module_inst, (uint32)total_size))) {
|
||||
wasm_runtime_module_malloc(module_inst, (uint32)total_size,
|
||||
(void**)&argv_buf))) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset);
|
||||
p = argv_buf;
|
||||
argv_offsets = (int32*)(p + total_argv_size);
|
||||
p_end = p + total_size;
|
||||
|
||||
|
@ -1379,6 +1380,15 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
{
|
||||
return wasm_native_register_natives(module_name,
|
||||
native_symbols, n_native_symbols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of wasm_runtime_invoke_native()
|
||||
*/
|
||||
|
@ -1425,13 +1435,16 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
|||
#define MAX_REG_FLOATS 16
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||
WASMExecEnv *exec_env,
|
||||
uint32 *argv, uint32 argc, uint32 *ret)
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
/* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args */
|
||||
uint32 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size;
|
||||
uint32 *argv_src = argv, i, argc1, n_ints = 0, n_fps = 0, n_stacks = 0;
|
||||
uint32 arg_i32, ptr_len;
|
||||
bool ret = false;
|
||||
|
||||
n_ints++; /* exec env */
|
||||
|
||||
|
@ -1508,11 +1521,41 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
for (i = 0; i < func_type->param_count; i++) {
|
||||
switch (func_type->types[i]) {
|
||||
case VALUE_TYPE_I32:
|
||||
{
|
||||
arg_i32 = *argv_src++;
|
||||
|
||||
if (signature) {
|
||||
if (signature[i + 1] == '*') {
|
||||
/* param is a pointer */
|
||||
if (signature[i + 2] == '~')
|
||||
/* pointer with length followed */
|
||||
ptr_len = *argv_src;
|
||||
else
|
||||
/* pointer without length followed */
|
||||
ptr_len = 1;
|
||||
|
||||
if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len))
|
||||
goto fail;
|
||||
|
||||
arg_i32 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
else if (signature[i + 1] == '$') {
|
||||
/* param is a string */
|
||||
if (!wasm_runtime_validate_app_str_addr(module, arg_i32))
|
||||
goto fail;
|
||||
|
||||
arg_i32 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
}
|
||||
|
||||
if (n_ints < MAX_REG_INTS)
|
||||
ints[n_ints++] = *argv_src++;
|
||||
ints[n_ints++] = arg_i32;
|
||||
else
|
||||
stacks[n_stacks++] = *argv_src++;
|
||||
stacks[n_stacks++] = arg_i32;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
if (n_ints < MAX_REG_INTS - 1) {
|
||||
/* 64-bit data must be 8 bytes aligned in arm */
|
||||
|
@ -1565,26 +1608,29 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
else {
|
||||
switch (func_type->types[func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||
argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks));
|
||||
PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks));
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks);
|
||||
*(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||
PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
wasm_free(argv1);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
#endif /* end of defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) */
|
||||
|
||||
|
@ -1609,12 +1655,15 @@ static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
|
|||
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||
WASMExecEnv *exec_env,
|
||||
uint32 *argv, uint32 argc, uint32 *ret)
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0;
|
||||
uint32 arg_i32, ptr_len;
|
||||
uint64 size;
|
||||
bool ret = false;
|
||||
|
||||
#if defined(BUILD_TARGET_X86_32)
|
||||
argc1 = argc + 2;
|
||||
|
@ -1637,20 +1686,49 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
for (i = 0; i < sizeof(WASMExecEnv*) / sizeof(uint32); i++)
|
||||
argv1[j++] = ((uint32*)&exec_env)[i];
|
||||
|
||||
#if defined(BUILD_TARGET_X86_32)
|
||||
word_copy(argv1 + j, argv, argc);
|
||||
j += argc;
|
||||
#else
|
||||
for (i = 0; i < func_type->param_count; i++) {
|
||||
switch (func_type->types[i]) {
|
||||
case VALUE_TYPE_I32:
|
||||
argv1[j++] = *argv++;
|
||||
{
|
||||
arg_i32 = *argv++;
|
||||
|
||||
if (signature) {
|
||||
if (signature[i + 1] == '*') {
|
||||
/* param is a pointer */
|
||||
if (signature[i + 2] == '~')
|
||||
/* pointer with length followed */
|
||||
ptr_len = *argv;
|
||||
else
|
||||
/* pointer without length followed */
|
||||
ptr_len = 1;
|
||||
|
||||
if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len))
|
||||
goto fail;
|
||||
|
||||
arg_i32 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
else if (signature[i + 1] == '$') {
|
||||
/* param is a string */
|
||||
if (!wasm_runtime_validate_app_str_addr(module, arg_i32))
|
||||
goto fail;
|
||||
|
||||
arg_i32 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
}
|
||||
|
||||
argv1[j++] = arg_i32;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
/* 64-bit data must be 8 bytes aligned in arm and mips */
|
||||
#if !defined(BUILD_TARGET_X86_32)
|
||||
/* 64-bit data must be 8 bytes aligned in arm, thumb, mips
|
||||
and xtensa */
|
||||
if (j & 1)
|
||||
j++;
|
||||
#endif
|
||||
argv1[j++] = *argv++;
|
||||
argv1[j++] = *argv++;
|
||||
break;
|
||||
|
@ -1662,7 +1740,6 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif /* end of defined(BUILD_TARGET_X86_32) */
|
||||
|
||||
argc1 = j;
|
||||
if (func_type->result_count == 0) {
|
||||
|
@ -1671,16 +1748,16 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
else {
|
||||
switch (func_type->types[func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
||||
argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1));
|
||||
PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, argc1));
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(float32*)ret = invokeNative_Float32(func_ptr, argv1, argc1);
|
||||
*(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, argc1);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, argc1));
|
||||
PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, argc1));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
|
@ -1688,9 +1765,12 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
wasm_free(argv1);
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* end of defined(BUILD_TARGET_X86_32) \
|
||||
|
@ -1724,12 +1804,15 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
|||
#endif
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||
WASMExecEnv *exec_env,
|
||||
uint32 *argv, uint32 argc, uint32 *ret)
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size;
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size, arg_i64;
|
||||
uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
|
||||
uint32 arg_i32, ptr_len;
|
||||
bool ret = false;
|
||||
#if defined(_WIN32) || defined(_WIN32_)
|
||||
/* important difference in calling conventions */
|
||||
#define n_fps n_ints
|
||||
|
@ -1757,11 +1840,40 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
for (i = 0; i < func_type->param_count; i++) {
|
||||
switch (func_type->types[i]) {
|
||||
case VALUE_TYPE_I32:
|
||||
{
|
||||
arg_i32 = *argv_src++;
|
||||
arg_i64 = arg_i32;
|
||||
if (signature) {
|
||||
if (signature[i + 1] == '*') {
|
||||
/* param is a pointer */
|
||||
if (signature[i + 2] == '~')
|
||||
/* pointer with length followed */
|
||||
ptr_len = *argv_src;
|
||||
else
|
||||
/* pointer without length followed */
|
||||
ptr_len = 1;
|
||||
|
||||
if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len))
|
||||
goto fail;
|
||||
|
||||
arg_i64 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
else if (signature[i + 1] == '$') {
|
||||
/* param is a string */
|
||||
if (!wasm_runtime_validate_app_str_addr(module, arg_i32))
|
||||
goto fail;
|
||||
|
||||
arg_i64 = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
}
|
||||
if (n_ints < MAX_REG_INTS)
|
||||
ints[n_ints++] = *argv_src++;
|
||||
ints[n_ints++] = arg_i64;
|
||||
else
|
||||
stacks[n_stacks++] = *argv_src++;
|
||||
stacks[n_stacks++] = arg_i64;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
if (n_ints < MAX_REG_INTS)
|
||||
ints[n_ints++] = *(uint64*)argv_src;
|
||||
|
@ -1794,16 +1906,16 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
else {
|
||||
switch (func_type->types[func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||
argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks));
|
||||
PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks));
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks);
|
||||
*(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||
PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
|
@ -1811,10 +1923,12 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
|||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
wasm_free(argv1);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "bh_common.h"
|
||||
#include "bh_thread.h"
|
||||
#include "wasm_exec_env.h"
|
||||
#include "wasm_native.h"
|
||||
#include "../interpreter/wasm.h"
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#include "wasmtime_ssp.h"
|
||||
|
@ -172,7 +173,8 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst);
|
|||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size);
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
|
@ -282,9 +284,15 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
|
|||
bool
|
||||
wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||
WASMExecEnv *exec_env,
|
||||
wasm_runtime_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
uint32 *argv, uint32 argc, uint32 *ret);
|
||||
|
||||
|
||||
|
|
|
@ -265,6 +265,7 @@ aot_create_import_funcs(const WASMModule *module)
|
|||
import_funcs[i].func_name = import_func->field_name;
|
||||
import_funcs[i].func_ptr_linked = import_func->func_ptr_linked;
|
||||
import_funcs[i].func_type = import_func->func_type;
|
||||
import_funcs[i].signature = import_func->signature;
|
||||
/* Resolve function type index */
|
||||
for (j = 0; j < module->type_count; j++)
|
||||
if (import_func->func_type == module->types[j]) {
|
||||
|
|
|
@ -83,6 +83,8 @@ typedef struct AOTImportFunc {
|
|||
uint32 func_type_index;
|
||||
/* function pointer after linked */
|
||||
void *func_ptr_linked;
|
||||
/* signature from registered native symbols */
|
||||
const char *signature;
|
||||
} AOTImportFunc;
|
||||
|
||||
/**
|
||||
|
|
|
@ -208,6 +208,7 @@ typedef enum FloatArithmetic {
|
|||
#define F64_ZERO (comp_ctx->llvm_consts.f64_zero)
|
||||
#define I32_ONE (comp_ctx->llvm_consts.i32_one)
|
||||
#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_EIGHT (comp_ctx->llvm_consts.i32_eight)
|
||||
#define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one)
|
||||
|
|
|
@ -82,21 +82,149 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef func_idx, AOTFuncType *aot_func_type,
|
||||
LLVMTypeRef *param_types, LLVMValueRef *param_values,
|
||||
uint32 param_count, uint32 param_cell_num,
|
||||
LLVMTypeRef ret_type, uint8 wasm_ret_type,
|
||||
LLVMValueRef *p_value_ret)
|
||||
{
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
|
||||
LLVMTypeRef ret_ptr_type, elem_ptr_type;
|
||||
LLVMValueRef func, elem_idx, elem_ptr;
|
||||
LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res;
|
||||
char buf[32], *func_name = "aot_invoke_native";
|
||||
uint32 i, cell_num = 0;
|
||||
|
||||
/* prepare function type of aot_invoke_native */
|
||||
func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
|
||||
func_param_types[1] = I32_TYPE; /* func_idx */
|
||||
func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */
|
||||
func_param_types[3] = I32_TYPE; /* argc */
|
||||
func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */
|
||||
if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* prepare function pointer */
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_invoke_native))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
func_name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (param_count > 64) {
|
||||
aot_set_last_error("prepare native arguments failed: "
|
||||
"maximum 64 parameter cell number supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* prepare frame_lp */
|
||||
for (i = 0; i < param_count; i++) {
|
||||
if (!(elem_idx = I32_CONST(cell_num))
|
||||
|| !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
|
||||
aot_set_last_error("llvm add const or pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s%d", "elem", i);
|
||||
if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->argv_buf, &elem_idx, 1, buf))
|
||||
|| !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
|
||||
elem_ptr_type, buf))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMSetAlignment(res, 1);
|
||||
|
||||
cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
|
||||
}
|
||||
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID) {
|
||||
if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
|
||||
ret_ptr_type, "argv_ret"))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* convert to int32 pointer */
|
||||
if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
|
||||
INT32_PTR_TYPE, "argv_ret_ptr"))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
|
||||
}
|
||||
|
||||
func_param_values[0] = func_ctx->exec_env;
|
||||
func_param_values[1] = func_idx;
|
||||
func_param_values[2] = func_ctx->argv_buf;
|
||||
func_param_values[3] = I32_CONST(param_cell_num);
|
||||
func_param_values[4] = value_ret_ptr;
|
||||
|
||||
if (!func_param_values[3]) {
|
||||
aot_set_last_error("llvm create const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call aot_invoke_native() function */
|
||||
if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID)
|
||||
/* get function return value */
|
||||
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 func_idx, uint8 **p_frame_ip)
|
||||
{
|
||||
uint32 import_func_count = comp_ctx->comp_data->import_func_count;
|
||||
AOTImportFunc *import_funcs = comp_ctx->comp_data->import_funcs;
|
||||
uint32 func_count = comp_ctx->func_ctx_count;
|
||||
uint32 func_count = comp_ctx->func_ctx_count, param_cell_num = 0;
|
||||
AOTFuncContext **func_ctxes = comp_ctx->func_ctxes;
|
||||
AOTFuncType *func_type;
|
||||
LLVMTypeRef *param_types = NULL, ret_type, f_type, f_ptr_type;
|
||||
LLVMValueRef *param_values = NULL, value_ret, func, value, cmp;
|
||||
LLVMBasicBlockRef check_func_ptr_succ;
|
||||
LLVMTypeRef *param_types = NULL, ret_type;
|
||||
LLVMValueRef *param_values = NULL, value_ret = NULL, func;
|
||||
LLVMValueRef import_func_idx;
|
||||
int32 i, j = 0, param_count;
|
||||
void *func_ptr;
|
||||
uint64 total_size;
|
||||
uint8 wasm_ret_type;
|
||||
bool ret = false;
|
||||
|
||||
/* Check function index */
|
||||
|
@ -112,6 +240,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
func_type = func_ctxes[func_idx - import_func_count]->
|
||||
aot_func->func_type;
|
||||
|
||||
/* Get param cell number */
|
||||
param_cell_num = wasm_type_param_cell_num(func_type);
|
||||
|
||||
/* Allocate memory for parameters */
|
||||
param_count = (int32)func_type->param_count;
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
|
||||
|
@ -129,8 +260,10 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
POP(param_values[i + j], func_type->types[i]);
|
||||
|
||||
if (func_idx < import_func_count) {
|
||||
/* Get function pointer linked */
|
||||
func_ptr = import_funcs[func_idx].func_ptr_linked;
|
||||
if (!(import_func_idx = I32_CONST(func_idx))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Initialize parameter types of the LLVM function */
|
||||
total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
|
||||
|
@ -146,99 +279,37 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
for (i = 0; i < param_count; i++)
|
||||
param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
|
||||
|
||||
/* Resolve return type of the LLVM function */
|
||||
if (func_type->result_count)
|
||||
ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]);
|
||||
else
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
/* Resolve function prototype */
|
||||
if (!(f_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count + 1, false))
|
||||
|| !(f_ptr_type = LLVMPointerType(f_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
if (!func_ptr) {
|
||||
/* The import function isn't linked, throw exception
|
||||
when calling it. */
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
false, NULL, NULL))
|
||||
goto fail;
|
||||
ret = aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* JIT mode, call the linked function directly */
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)func_ptr))
|
||||
|| !(func = LLVMConstIntToPtr(value, f_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (func_type->result_count) {
|
||||
wasm_ret_type = func_type->types[func_type->param_count];
|
||||
ret_type = TO_LLVM_TYPE(wasm_ret_type);
|
||||
}
|
||||
else {
|
||||
/* Load function pointer */
|
||||
if (!(value = I32_CONST(func_idx))
|
||||
|| !(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->func_ptrs,
|
||||
&value, 1, "func_ptr"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check whether import function is NULL */
|
||||
if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Throw exception if import function is NULL */
|
||||
if (!(check_func_ptr_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_func_ptr_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_func_ptr_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
true, cmp, check_func_ptr_succ)))
|
||||
goto fail;
|
||||
|
||||
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
|
||||
f_ptr_type, "func"))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
wasm_ret_type = VALUE_TYPE_VOID;
|
||||
ret_type = VOID_TYPE;
|
||||
}
|
||||
|
||||
/* call aot_invoke_native() */
|
||||
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type,
|
||||
param_types + 1, param_values + 1,
|
||||
param_count, param_cell_num,
|
||||
ret_type, wasm_ret_type, &value_ret))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, (uint32)param_count + 1,
|
||||
(func_type->result_count > 0
|
||||
? "call" : "")))) {
|
||||
aot_set_last_error("LLVM build call failed.");
|
||||
goto fail;
|
||||
}
|
||||
/* Call the function */
|
||||
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, (uint32)param_count + 1,
|
||||
(func_type->result_count > 0
|
||||
? "call" : "")))) {
|
||||
aot_set_last_error("LLVM build call failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set calling convention for the call with the func's calling convention */
|
||||
LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
|
||||
/* Set calling convention for the call with the func's calling convention */
|
||||
LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
|
||||
}
|
||||
|
||||
if (func_type->result_count > 0)
|
||||
PUSH(value_ret, func_type->types[func_type->param_count]);
|
||||
|
@ -269,10 +340,12 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
f_type, f_ptr_type;
|
||||
LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ;
|
||||
LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ;
|
||||
int32 i, j = 0, param_count;
|
||||
uint64 total_size;
|
||||
bool ret;
|
||||
char *func_name = "aot_is_wasm_type_equal";
|
||||
int32 i, j = 0, param_count;
|
||||
uint32 param_cell_num;
|
||||
uint64 total_size;
|
||||
uint8 wasm_ret_type;
|
||||
bool ret;
|
||||
|
||||
/* Check function type index */
|
||||
if (type_idx >= comp_ctx->comp_data->func_type_count) {
|
||||
|
@ -282,6 +355,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
func_type = comp_ctx->comp_data->func_types[type_idx];
|
||||
|
||||
param_cell_num = wasm_type_param_cell_num(func_type);
|
||||
|
||||
POP_I32(elem_idx);
|
||||
|
||||
table_size_const = I32_CONST(comp_ctx->comp_data->table_size);
|
||||
|
@ -383,9 +458,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
/* Create LLVM function with const function pointer */
|
||||
if (!(func_const =
|
||||
I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
|
||||
|| !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
|
||||
if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
|
||||
|| !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -485,23 +559,13 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
|
||||
|
||||
/* Resolve return type of the LLVM function */
|
||||
if (func_type->result_count)
|
||||
ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]);
|
||||
else
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
/* Resolve function prototype */
|
||||
if (!(f_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count + 1, false))
|
||||
|| !(f_ptr_type = LLVMPointerType(f_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
goto fail;
|
||||
if (func_type->result_count) {
|
||||
wasm_ret_type = func_type->types[func_type->param_count];
|
||||
ret_type = TO_LLVM_TYPE(wasm_ret_type);
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
|
||||
f_ptr_type, "func"))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
else {
|
||||
wasm_ret_type = VALUE_TYPE_VOID;
|
||||
ret_type = VOID_TYPE;
|
||||
}
|
||||
|
||||
/* Allocate memory for parameters */
|
||||
|
@ -520,14 +584,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
for (i = param_count - 1; i >= 0; i--)
|
||||
POP(param_values[i + j], func_type->types[i]);
|
||||
|
||||
/* Call the function */
|
||||
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, (uint32)param_count + 1,
|
||||
(func_type->result_count > 0
|
||||
? "call_indirect" : "")))) {
|
||||
aot_set_last_error("LLVM build call failed.");
|
||||
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type,
|
||||
param_types + 1, param_values + 1,
|
||||
param_count, param_cell_num,
|
||||
ret_type, wasm_ret_type, &value_ret))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (func_type->result_count > 0)
|
||||
PUSH(value_ret, func_type->types[func_type->param_count]);
|
||||
|
|
|
@ -440,8 +440,9 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
AOTFuncContext *func_ctx;
|
||||
AOTFuncType *aot_func_type = comp_data->func_types[func->func_type_index];
|
||||
AOTBlock *aot_block;
|
||||
LLVMTypeRef int8_ptr_type;
|
||||
LLVMTypeRef int8_ptr_type, int32_ptr_type;
|
||||
LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
|
||||
LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
|
||||
char local_name[32];
|
||||
uint64 size;
|
||||
uint32 i, j = 0;
|
||||
|
@ -476,7 +477,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
func_ctx->exec_env = LLVMGetParam(func_ctx->func, j++);
|
||||
|
||||
/* Get aot inst address, the layout of exec_env is:
|
||||
exec_env->next, exec_env->prev, and exec_env->module_inst */
|
||||
exec_env->next, exec_env->prev, exec_env->module_inst, and argv_buf */
|
||||
if (!(aot_inst_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
|
||||
&aot_inst_offset, 1, "aot_inst_addr"))) {
|
||||
|
@ -491,6 +492,32 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* Get argv buffer address */
|
||||
if (!(argv_buf_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
|
||||
&argv_buf_offset, 1, "argv_buf_addr"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Convert to int32 pointer type */
|
||||
if (!(argv_buf_addr = LLVMBuildBitCast(comp_ctx->builder, argv_buf_addr,
|
||||
int32_ptr_type, "argv_buf_ptr"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_ctx->argv_buf = LLVMBuildLoad(comp_ctx->builder,
|
||||
argv_buf_addr, "argv_buf"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < aot_func_type->param_count; i++, j++) {
|
||||
snprintf(local_name, sizeof(local_name), "l%d", i);
|
||||
func_ctx->locals[i] =
|
||||
|
@ -674,6 +701,7 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
|
|||
consts->f64_zero = F64_CONST(0);
|
||||
consts->i32_one = I32_CONST(1);
|
||||
consts->i32_two = I32_CONST(2);
|
||||
consts->i32_three = I32_CONST(3);
|
||||
consts->i32_four = I32_CONST(4);
|
||||
consts->i32_eight = I32_CONST(8);
|
||||
consts->i32_neg_one = I32_CONST((uint32)-1);
|
||||
|
@ -692,6 +720,7 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
|
|||
&& consts->f64_zero
|
||||
&& consts->i32_one
|
||||
&& consts->i32_two
|
||||
&& consts->i32_three
|
||||
&& consts->i32_four
|
||||
&& consts->i32_eight
|
||||
&& consts->i32_neg_one
|
||||
|
|
|
@ -92,6 +92,7 @@ typedef struct AOTFuncContext {
|
|||
LLVMValueRef exec_env;
|
||||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef table_base;
|
||||
LLVMValueRef argv_buf;
|
||||
|
||||
LLVMValueRef mem_data_size;
|
||||
LLVMValueRef mem_base_addr;
|
||||
|
@ -150,6 +151,7 @@ typedef struct AOTLLVMConsts {
|
|||
LLVMValueRef f64_zero;
|
||||
LLVMValueRef i32_one;
|
||||
LLVMValueRef i32_two;
|
||||
LLVMValueRef i32_three;
|
||||
LLVMValueRef i32_four;
|
||||
LLVMValueRef i32_eight;
|
||||
LLVMValueRef i32_neg_one;
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _EXT_LIB_EXPORT_H_
|
||||
#define _EXT_LIB_EXPORT_H_
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis)
|
||||
{
|
||||
*p_ext_lib_apis = extended_native_symbol_defs;
|
||||
return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _EXT_LIB_EXPORT_H_ */
|
||||
|
|
@ -13,10 +13,16 @@ extern "C" {
|
|||
typedef struct NativeSymbol {
|
||||
const char *symbol;
|
||||
void *func_ptr;
|
||||
const char *signature;
|
||||
} NativeSymbol;
|
||||
|
||||
#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol}
|
||||
#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper}
|
||||
#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL}
|
||||
#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL}
|
||||
|
||||
#define EXPORT_WASM_API_WITH_SIG(symbol, signature) \
|
||||
{#symbol, (void*)symbol, signature}
|
||||
#define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \
|
||||
{#symbol, (void*)symbol##_wrapper, signature}
|
||||
|
||||
/**
|
||||
* Get the exported APIs of base lib
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include "lib_export.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -161,8 +162,7 @@ wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst);
|
|||
*
|
||||
* @param module_inst the module instance
|
||||
* @param name the name of the function
|
||||
* @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64"
|
||||
* to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32"
|
||||
* @param signature the signature of the function, ignored currently
|
||||
*
|
||||
* @return the function instance found
|
||||
*/
|
||||
|
@ -293,6 +293,8 @@ wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
|
|||
*
|
||||
* @param module_inst the WASM module instance which contains heap
|
||||
* @param size the size bytes to allocate
|
||||
* @param p_native_addr return native address of the allocated memory
|
||||
* if it is not NULL, and return NULL if memory malloc failed
|
||||
*
|
||||
* @return the allocated memory address, which is a relative offset to the
|
||||
* base address of the module instance's memory space, the value range
|
||||
|
@ -300,7 +302,8 @@ wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
|
|||
* Return non-zero if success, zero if failed.
|
||||
*/
|
||||
int32_t
|
||||
wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size);
|
||||
wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size,
|
||||
void **p_native_addr);
|
||||
|
||||
/**
|
||||
* Free memory to the heap of WASM module instance
|
||||
|
@ -432,6 +435,36 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
|
|||
uint8_t **p_native_start_addr,
|
||||
uint8_t **p_native_end_addr);
|
||||
|
||||
/**
|
||||
* Register native functions with same module name
|
||||
*
|
||||
* @param module_name the module name of the native functions
|
||||
* @param native_symbols specifies an array of NativeSymbol structures which
|
||||
* contain the names, function pointers and signatures
|
||||
* Note: WASM runtime will not allocate memory to clone the data, so
|
||||
* user must ensure the array can be used forever
|
||||
* Meanings of letters in function signature:
|
||||
* 'i': the parameter is i32 type
|
||||
* 'I': the parameter is i64 type
|
||||
* 'f': the parameter is f32 type
|
||||
* 'F': the parameter is f64 type
|
||||
* '*': the parameter is a pointer (i32 in WASM), and runtime will
|
||||
* auto check its boundary before calling the native function.
|
||||
* If it is followed by '~', the checked length of the pointer
|
||||
* is gotten from the following parameter, if not, the checked
|
||||
* length of the pointer is 1.
|
||||
* '~': the parameter is the pointer's length with i32 type, and must
|
||||
* follow after '*'
|
||||
* '$': the parameter is a string (i32 in WASM), and runtime will
|
||||
* auto check its boundary before calling the native function
|
||||
* @param n_native_symbols specifies the number of native symbols in the array
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool wasm_runtime_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32_t n_native_symbols);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -137,6 +137,8 @@ typedef struct WASMFunctionImport {
|
|||
WASMType *func_type;
|
||||
/* function pointer after linked */
|
||||
void *func_ptr_linked;
|
||||
/* signature from registered native symbols */
|
||||
const char *signature;
|
||||
} WASMFunctionImport;
|
||||
|
||||
typedef struct WASMGlobalImport {
|
||||
|
@ -288,8 +290,7 @@ typedef struct WASMModule {
|
|||
auxiliary stack top pointer */
|
||||
uint32 llvm_aux_stack_global_index;
|
||||
|
||||
/* Whether there is possible memory grow, e.g.
|
||||
memory.grow opcode or call enlargeMemory */
|
||||
/* Whether there is possible memory grow, e.g. memory.grow opcode */
|
||||
bool possible_memory_grow;
|
||||
|
||||
StringList const_str_list;
|
||||
|
|
|
@ -726,9 +726,11 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMFunctionImport *func_import = cur_func->u.func_import;
|
||||
unsigned local_cell_num = 2;
|
||||
WASMInterpFrame *frame;
|
||||
uint32 argv_ret[2];
|
||||
char buf[128];
|
||||
bool ret;
|
||||
|
||||
if (!(frame = ALLOC_FRAME(exec_env,
|
||||
|
@ -742,19 +744,16 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
if (!cur_func->u.func_import->func_ptr_linked) {
|
||||
char buf[128];
|
||||
snprintf(buf,
|
||||
sizeof(buf), "fail to call unlinked import function (%s, %s)",
|
||||
cur_func->u.func_import->module_name,
|
||||
cur_func->u.func_import->field_name);
|
||||
wasm_set_exception((WASMModuleInstance*)module_inst, buf);
|
||||
if (!func_import->func_ptr_linked) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
func_import->module_name, func_import->field_name);
|
||||
wasm_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked,
|
||||
cur_func->u.func_import->func_type,
|
||||
exec_env,
|
||||
ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
|
||||
func_import->func_type, func_import->signature,
|
||||
frame->lp, cur_func->param_cell_num, argv_ret);
|
||||
|
||||
if (!ret)
|
||||
|
|
|
@ -556,36 +556,6 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void*
|
||||
resolve_sym(const char *module_name, const char *field_name)
|
||||
{
|
||||
void *sym;
|
||||
|
||||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
if ((sym = wasm_native_lookup_libc_builtin_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if ((sym = wasm_native_lookup_libc_wasi_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BASE_LIB != 0
|
||||
if ((sym = wasm_native_lookup_base_lib_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
if ((sym = wasm_native_lookup_extension_lib_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
|
@ -737,13 +707,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
}
|
||||
import->u.function.func_type = module->types[type_index];
|
||||
|
||||
if (!module->possible_memory_grow
|
||||
&& !strcmp(module_name, "env")
|
||||
&& !(strcmp(field_name, "enlargeMemory")))
|
||||
module->possible_memory_grow = true;
|
||||
|
||||
if (!(import->u.function.func_ptr_linked =
|
||||
resolve_sym(module_name, field_name))) {
|
||||
wasm_native_resolve_symbol(module_name, field_name,
|
||||
import->u.function.func_type,
|
||||
&import->u.function.signature))) {
|
||||
#if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */
|
||||
LOG_WARNING("warning: fail to link import function (%s, %s)\n",
|
||||
module_name, field_name);
|
||||
|
@ -3016,7 +2983,8 @@ handle_next_reachable_block:
|
|||
POP_TYPE(func_type->types[idx]);
|
||||
}
|
||||
|
||||
PUSH_TYPE(func_type->types[func_type->param_count]);
|
||||
if (func_type->result_count > 0)
|
||||
PUSH_TYPE(func_type->types[func_type->param_count]);
|
||||
|
||||
func->has_op_func_call = true;
|
||||
break;
|
||||
|
|
|
@ -849,75 +849,15 @@ wasm_deinstantiate(WASMModuleInstance *module_inst)
|
|||
wasm_free(module_inst);
|
||||
}
|
||||
|
||||
static bool
|
||||
check_type(uint8 type, const char *p)
|
||||
{
|
||||
const char *str = "i32";
|
||||
|
||||
if (strlen(p) < 3)
|
||||
return false;
|
||||
|
||||
switch (type) {
|
||||
case VALUE_TYPE_I32:
|
||||
str = "i32";
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
str = "i64";
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
str = "f32";
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
str = "f64";
|
||||
break;
|
||||
}
|
||||
if (strncmp(p, str, 3))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_function_type(const WASMType *type, const char *signature)
|
||||
{
|
||||
uint32 i;
|
||||
const char *p = signature;
|
||||
|
||||
if (!p || *p++ != '(')
|
||||
return false;
|
||||
|
||||
for (i = 0; i < type->param_count; i++) {
|
||||
if (!check_type(type->types[i], p))
|
||||
return false;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
if (*p++ != ')')
|
||||
return false;
|
||||
|
||||
if (type->result_count) {
|
||||
if (!check_type(type->types[type->param_count], p))
|
||||
return false;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
if (*p != '\0')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WASMFunctionInstance*
|
||||
wasm_lookup_function(const WASMModuleInstance *module_inst,
|
||||
const char *name, const char *signature)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < module_inst->export_func_count; i++)
|
||||
if (!strcmp(module_inst->export_functions[i].name, name)
|
||||
&& check_function_type(
|
||||
module_inst->export_functions[i].function->u.func->func_type,
|
||||
signature))
|
||||
if (!strcmp(module_inst->export_functions[i].name, name))
|
||||
return module_inst->export_functions[i].function;
|
||||
(void)signature;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -972,10 +912,13 @@ wasm_get_exception(WASMModuleInstance *module_inst)
|
|||
}
|
||||
|
||||
int32
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size)
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr)
|
||||
{
|
||||
WASMMemoryInstance *memory = module_inst->default_memory;
|
||||
uint8 *addr = mem_allocator_malloc(memory->heap_handle, size);
|
||||
if (p_native_addr)
|
||||
*p_native_addr = addr;
|
||||
if (!addr) {
|
||||
wasm_set_exception(module_inst, "out of memory");
|
||||
return 0;
|
||||
|
@ -998,9 +941,10 @@ int32
|
|||
wasm_module_dup_data(WASMModuleInstance *module_inst,
|
||||
const char *src, uint32 size)
|
||||
{
|
||||
int32 buffer_offset = wasm_module_malloc(module_inst, size);
|
||||
char *buffer;
|
||||
int32 buffer_offset = wasm_module_malloc(module_inst, size,
|
||||
(void**)&buffer);
|
||||
if (buffer_offset != 0) {
|
||||
char *buffer;
|
||||
buffer = wasm_addr_app_to_native(module_inst, buffer_offset);
|
||||
bh_memcpy_s(buffer, size, src, size);
|
||||
}
|
||||
|
|
|
@ -222,7 +222,8 @@ const char*
|
|||
wasm_get_exception(WASMModuleInstance *module);
|
||||
|
||||
int32
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size);
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
||||
void
|
||||
wasm_module_free(WASMModuleInstance *module_inst, int32 ptr);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -80,6 +80,10 @@ enum {
|
|||
#define WASM_ENABLE_BASE_LIB 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_APP_FRAMEWORK
|
||||
#define WASM_ENABLE_APP_FRAMEWORK 0
|
||||
#endif
|
||||
|
||||
/* WASM log system */
|
||||
#ifndef WASM_ENABLE_LOG
|
||||
#define WASM_ENABLE_LOG 1
|
||||
|
@ -148,8 +152,8 @@ enum {
|
|||
#define APP_THREAD_STACK_SIZE_MIN (16 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
|
||||
#else
|
||||
#define APP_THREAD_STACK_SIZE_DEFAULT (4 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MIN (2 * 1024)
|
||||
#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
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ bh_mprotect(void *addr, uint32 size, int prot)
|
|||
void
|
||||
bh_dcache_flush()
|
||||
{
|
||||
#if defined(CONFIG_CPU_CORTEX_M7)
|
||||
#if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU)
|
||||
uint32 key;
|
||||
key = irq_lock();
|
||||
SCB_CleanDCache();
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
Embed WAMR into software production
|
||||
Embedding WAMR guideline
|
||||
=====================================
|
||||
|
||||
![WAMR embed diagram](./pics/embed.PNG "WAMR embed architecture diagram")
|
||||
|
||||
**Note**: All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files.
|
||||
|
||||
## The initialization procedure
|
||||
|
||||
|
||||
|
||||
A typical WAMR API usage is shown below (some return value checks are ignored):
|
||||
``` C
|
||||
static char global_heap_buf[512 * 1024];
|
||||
|
||||
|
@ -13,27 +16,162 @@ A typical WAMR API usage is shown below (some return value checks are ignored):
|
|||
wasm_module_inst_t module_inst;
|
||||
wasm_function_inst_t func;
|
||||
wasm_exec_env_t exec_env;
|
||||
uint32 argv[2], size, stack_size = 8092, heap_size = 8092;
|
||||
uint32 size, stack_size = 8092, heap_size = 8092;
|
||||
|
||||
// all the WAMR heap and WASM applications are limited in this buffer
|
||||
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
|
||||
|
||||
wasm_runtime_init();
|
||||
|
||||
// read WASM file into a memory buffer
|
||||
buffer = read_wasm_binary_to_buffer(…, &size);
|
||||
|
||||
// parse the WASM file from buffer and create a WASM module
|
||||
module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf));
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
func = wasm_runtime_lookup_function(module_inst, "fib", "(i32)i32");
|
||||
|
||||
// create an instance of the WASM module (WASM linear memory is ready)
|
||||
module_inst = wasm_runtime_instantiate(module,
|
||||
stack_size,
|
||||
heap_size,
|
||||
error_buf,
|
||||
sizeof(error_buf));
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Native calls WASM functions and passes parameters
|
||||
|
||||
After a module is instantiated, the runtime native can lookup WASM functions by the names and call them.
|
||||
|
||||
```c
|
||||
unit32 argv[2];
|
||||
|
||||
// lookup a WASM function by its name
|
||||
func = wasm_runtime_lookup_function(module_inst, "fib", NULL);
|
||||
|
||||
// creat a excution environment which can be used by executing WASM functions
|
||||
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
|
||||
|
||||
// arguments are always transferred in 32 bits element
|
||||
argv[0] = 8;
|
||||
if (wasm_runtime_call_wasm(exec_env, func, 1, argv_buf) ) {
|
||||
|
||||
// call the WASM function
|
||||
if (wasm_runtime_call_wasm(exec_env, func, 1, argv) ) {
|
||||
|
||||
/* the return value is stored in argv[0] */
|
||||
printf("fib function return: %d\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
printf("%s\n", wasm_runtime_get_exception(module_inst));
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
The parameters are transferred in an array of 32 bits elements. For parameters that occupy 4 or fewer bytes, each parameter can be a single array element. For parameters in types like double or int64, each parameter will take two array elements. The function return value will be sent back in the first one or two elements of the array according to the value type. See the sample code below:
|
||||
|
||||
```c
|
||||
unit32 argv[6];
|
||||
char arg1 = 'a';
|
||||
int arg2 = 10;
|
||||
double arg3 = 1.0;
|
||||
int 64 arg4 = 100;
|
||||
double ret;
|
||||
|
||||
argv[0] = arg1;
|
||||
argv[1] = arg2;
|
||||
|
||||
// use memory copy for 8 bytes parameters rather than
|
||||
// *(double*)(&argv[2]) = arg3 here because some archs
|
||||
// like ARM, MIPS requires address is 8 aligned.
|
||||
// Or use the aligned malloc or compiler align attribute
|
||||
// to ensure the array address is 8 bytes aligned
|
||||
memcpy(&argv[2], &arg3, sizeof(arg3));
|
||||
memcpy(&argv[4], &arg4, sizeof(arg4));
|
||||
|
||||
//
|
||||
// attention: the arg number is 6 here since both
|
||||
// arg3 and arg4 each takes 2 elements
|
||||
//
|
||||
wasm_runtime_call_wasm(exec_env, func, 6, argv);
|
||||
|
||||
// if the return value is type of 8 bytes, it takes
|
||||
// the first two array elements
|
||||
memcpy(&ret, &argv[0], sizeof(ret));
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Pass buffer to WASM function
|
||||
|
||||
|
||||
|
||||
If we need to transfer a buffer to WASM function, we can pass the buffer address through a parameter. **Attention**: The sandbox will forbid the WASM code to access outside memory, we must **allocate the buffer from WASM instance's own memory space and pass the buffer address in instance's space (not the runtime native address)**.
|
||||
|
||||
|
||||
|
||||
There are two runtime APIs available for this purpose.
|
||||
|
||||
```c
|
||||
/*
|
||||
* description: malloc a buffer from instance's private memory space.
|
||||
*
|
||||
* return: the buffer address in instance's memory space (pass to the WASM funciton)
|
||||
* p_native_addr: return the native address of allocated memory
|
||||
* size: the buffer size to allocate
|
||||
*/
|
||||
int32_t
|
||||
wasm_runtime_module_malloc(wasm_module_inst_t module_inst,
|
||||
uint32_t size,
|
||||
void **p_native_addr);
|
||||
|
||||
/*
|
||||
* description: malloc a buffer from instance's private memory space,
|
||||
* and copy the data from another native buffer to it.
|
||||
* return: the buffer address in instance's memory space (pass to the WASM funciton)
|
||||
* src: the native buffer address
|
||||
* size: the size of buffer to be allocated and copy data
|
||||
*/
|
||||
int32
|
||||
wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
|
||||
const char *src,
|
||||
uint32 size);
|
||||
```
|
||||
|
||||
|
||||
|
||||
Usage sample:
|
||||
|
||||
```c
|
||||
char * buffer = NULL;
|
||||
int32_t buffer_for_wasm;
|
||||
|
||||
buffer_for_wasm = wasm_runtime_module_malloc(module_inst, 100, &buffer);
|
||||
if(buffer_for_wasm != 0)
|
||||
{
|
||||
unit32 argv[2];
|
||||
strncpy(buffer, "hello", 100); // use native address for accessing in runtime
|
||||
argv[0] = buffer_for_wasm; // pass the buffer address for WASM space.
|
||||
argv[1] = 100; // the size of buffer
|
||||
wasm_runtime_call_wasm(exec_env, func, 2, argv);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Pass structured data to WASM function
|
||||
|
||||
We can't pass structure data or class objects through the pointer since the memory layout can different in two worlds. The way to do it is serialization. Refer to [export_native_api.md](./export_native_api.md) for the details.
|
||||
|
||||
|
||||
|
||||
## The deinitialization procedure
|
||||
|
||||
```
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
wasm_runtime_unload(module);
|
||||
|
@ -41,3 +179,8 @@ A typical WAMR API usage is shown below (some return value checks are ignored):
|
|||
bh_memory_destroy();
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Native calling WASM function working flow
|
||||
|
||||
![WAMR embed diagram](./pics/embed.PNG "WAMR embed architecture diagram")
|
||||
|
|
|
@ -2,202 +2,232 @@
|
|||
Export native API to WASM application
|
||||
=======================================================
|
||||
|
||||
The basic working flow for WASM application calling into the native API is shown in the following diagram:
|
||||
|
||||
![WAMR WASM API ext diagram](./pics/extend_library.PNG "WAMR WASM API ext architecture diagram")
|
||||
|
||||
|
||||
WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library.
|
||||
Exporting native API steps
|
||||
--------------------------
|
||||
|
||||
#### Step 1: Declare the function interface in WASM app
|
||||
|
||||
Create a header file in a WASM app and declare the functions that are exported from native. In this example, we declare foo and foo2 as below in the header file "example.h"
|
||||
|
||||
```c
|
||||
/*** file name: example.h ***/
|
||||
|
||||
int foo(int a, int b);
|
||||
void foo2(char * msg, char * buffer, int buf_len);
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Step 2: Define the native API
|
||||
|
||||
Define the native functions which are executed from the WASM app in the runtime source file. The native function can be any name, for example **foo_native** and **foo2** here:
|
||||
|
||||
``` C
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
EXPORT_WASM_API(wasm_register_resource),
|
||||
EXPORT_WASM_API(wasm_response_send),
|
||||
EXPORT_WASM_API(wasm_post_request),
|
||||
EXPORT_WASM_API(wasm_sub_event),
|
||||
EXPORT_WASM_API(wasm_create_timer),
|
||||
EXPORT_WASM_API(wasm_timer_set_interval),
|
||||
EXPORT_WASM_API(wasm_timer_cancel),
|
||||
EXPORT_WASM_API(wasm_timer_restart)
|
||||
int foo_native(wasm_exec_env_t exec_env , int a, int b)
|
||||
{
|
||||
return a+b;
|
||||
}
|
||||
|
||||
void foo2(wasm_exec_env_t exec_env, char * msg, uint8 * buffer, int buf_len)
|
||||
{
|
||||
strncpy(buffer, msg, buf_len);
|
||||
}
|
||||
```
|
||||
|
||||
The first parameter exec_env must be defined using type **wasm_exec_env_t** which is the calling convention for exporting native API by WAMR.
|
||||
|
||||
The rest parameters should be in the same types as the parameters of WASM function foo(), but there are a few special cases that are explained in section "Buffer address conversion and boundary check". Regarding the parameter names, they don't have to be the same, but we would suggest using the same names for easy maintenance.
|
||||
|
||||
|
||||
|
||||
#### Step 3: Register the native APIs
|
||||
|
||||
Register the native APIs in the runtime, then everything is fine. It is ready to build the runtime software.
|
||||
|
||||
``` C
|
||||
// Define an array of NativeSymbol for the APIs to be exported.
|
||||
// Note: the array must be static defined since runtime
|
||||
// will keep it after registration
|
||||
static NativeSymbol native_symbols[] =
|
||||
{
|
||||
{
|
||||
"foo", // the name of WASM function name
|
||||
foo_native, // the native function pointer
|
||||
"(ii)i" // the function prototype signature
|
||||
},
|
||||
{
|
||||
"foo2", // the name of WASM function name
|
||||
foo2, // the native function pointer
|
||||
"($*~)" // the function prototype signature
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
if (!wasm_runtime_register_natives("env",
|
||||
native_symbols,
|
||||
n_native_symbols)) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**Function signature**:
|
||||
|
||||
The function signature field in **NativeSymbol** structure is a string for describing the function prototype. It is critical to ensure the function signature is correctly mapping the native function interface.
|
||||
|
||||
Each letter in the "()" represents a parameter type, and the one following after ")" represents the return value type. The meaning of each letter:
|
||||
|
||||
- 'i': i32
|
||||
- 'I': i64
|
||||
- 'f': f32
|
||||
- 'F': f64
|
||||
- '*': the parameter is a buffer address in WASM application
|
||||
- '~': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail
|
||||
- '$': the parameter is a string in WASM application
|
||||
|
||||
**Use EXPORT_WASM_API_WITH_SIG**
|
||||
|
||||
The above foo2 NativeSymbol element can be also defined with macro EXPORT_WASM_API_WITH_SIG. This macro can be used when the native function name is the same as the WASM symbol name.
|
||||
|
||||
```c
|
||||
static NativeSymbol native_symbols[] =
|
||||
{
|
||||
EXPORT_WASM_API_WITH_SIG(foo2, "($*~)")
|
||||
};
|
||||
```
|
||||
|
||||
**Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
|
||||
|
||||
|
||||
- Only use 32 bits number for parameters
|
||||
- Should not pass data to the structure pointer (do data serialization instead)
|
||||
- Should do the pointer address conversion in the native API
|
||||
- Should not pass function pointer as callback
|
||||
## Call exported API in wasm application
|
||||
|
||||
|
||||
|
||||
Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world.
|
||||
|
||||
In wasm world:
|
||||
``` C
|
||||
void api_send_request(request_t * request, response_handler_f response_handler,
|
||||
void * user_data)
|
||||
{
|
||||
int size;
|
||||
char *buffer;
|
||||
transaction_t *trans;
|
||||
|
||||
if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) {
|
||||
printf(
|
||||
"send request: allocate memory for request transaction failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(trans, 0, sizeof(transaction_t));
|
||||
trans->handler = response_handler;
|
||||
trans->mid = request->mid;
|
||||
trans->time = wasm_get_sys_tick_ms();
|
||||
trans->user_data = user_data;
|
||||
|
||||
// pack request
|
||||
if ((buffer = pack_request(request, &size)) == NULL) {
|
||||
printf("send request: pack request failed!\n");
|
||||
free(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
transaction_add(trans);
|
||||
|
||||
/* if the trans is the 1st one, start the timer */
|
||||
if (trans == g_transactions) {
|
||||
/* assert(g_trans_timer == NULL); */
|
||||
if (g_trans_timer == NULL) {
|
||||
g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS,
|
||||
false,
|
||||
true, transaction_timeout_handler);
|
||||
}
|
||||
}
|
||||
|
||||
// call native API
|
||||
wasm_post_request(buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
```
|
||||
|
||||
In native world:
|
||||
``` C
|
||||
void
|
||||
wasm_post_request(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
// do boundary check
|
||||
if (!validate_app_addr(buffer_offset, size))
|
||||
return;
|
||||
|
||||
// do address conversion
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
request_t req[1];
|
||||
|
||||
// De-serialize data
|
||||
if (!unpack_request(buffer, size, req))
|
||||
return;
|
||||
|
||||
// set sender to help dispatch the response to the sender app later
|
||||
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App,
|
||||
module_inst);
|
||||
bh_assert(mod_id != ID_NONE);
|
||||
req->sender = mod_id;
|
||||
|
||||
if (req->action == COAP_EVENT) {
|
||||
am_publish_event(req);
|
||||
return;
|
||||
}
|
||||
|
||||
am_dispatch_request(req);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Steps for exporting native API
|
||||
==========================
|
||||
|
||||
WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps:
|
||||
|
||||
|
||||
## Step 1: Define the native API for exporting
|
||||
|
||||
Define the function **example_native_func** in your source file, namely `example.c` here:
|
||||
``` C
|
||||
int example_native_func(wasm_exec_env_t exec_env,
|
||||
int arg1, int arg2)
|
||||
{
|
||||
// Your implementation here
|
||||
}
|
||||
```
|
||||
The first function argument must be defined using type **wasm_exec_env_t** which is the WAMR calling convention for native API exporting.
|
||||
|
||||
The function prototype should also be declared in a header file so the wasm application can include it.
|
||||
``` C
|
||||
#ifndef _EXAMPLE_H_
|
||||
#define _EXAMPLE_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void example_native_func(int arg1, int arg2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
## Step 2: Declare the native API exporting
|
||||
|
||||
Declare the function **example_native_func** with macro **EXPORT_WASM_API** in your **.inl** file, namely `example.inl` in this sample.
|
||||
``` C
|
||||
EXPORT_WASM_API(example_native_func),
|
||||
```
|
||||
|
||||
Then include the file **example.inl** in definition of array **extended_native_symbol_defs** in the `ext_lib_export.c`.
|
||||
``` C
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "example.inl"
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
|
||||
## Step 3: Compile the runtime product
|
||||
Add the source file **example.c** and **ext_lib_export.c** into the CMakeList.txt for building runtime with the exported API's:
|
||||
``` cmake
|
||||
set (EXT_API_SOURCE example.c)
|
||||
|
||||
add_executable (sample
|
||||
# other source files
|
||||
# ......
|
||||
${EXT_API_SOURCE}
|
||||
ext_lib_export.c
|
||||
)
|
||||
```
|
||||
|
||||
# Use exported API in wasm application
|
||||
|
||||
We can call the exported native API **example_native_func** in wasm application like this:
|
||||
Now we can call the exported native API in wasm application like this:
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include "example.h"
|
||||
#include "example.h" // where the APIs are declared
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int a = 0, b = 1;
|
||||
char * msg = "hello";
|
||||
char buffer[100];
|
||||
|
||||
example_native_func(a, b);
|
||||
int c = foo(a, b); // call into native foo_native()
|
||||
foo2(msg, buffer, sizeof(buffer)); // call into native foo2()
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Buffer address conversion and boundary check
|
||||
|
||||
A WebAssembly sandbox ensures applications only access to its own memory with a private address space. When passing a pointer address from WASM to native, the address value must be converted to native address before the native function can access it. It is also the native world's responsibility to check the buffer length is not over its sandbox boundary.
|
||||
|
||||
|
||||
|
||||
The signature letter '$', '\*' and '\~' help the runtime do automatic address conversion and buffer boundary check, so the native function directly uses the string and buffer address. **Notes**: if '\*' is not followed by '\~', the native function should not assume the length of the buffer is more than 1 byte.
|
||||
|
||||
|
||||
|
||||
As function parameters are always passed in 32 bits numbers, you can also use 'i' for the pointer type argument, then you must do all the address conversion and boundary checking in your native function. For example, if you change the foo2 signature to "(iii)", then you will implement the native part as the following sample:
|
||||
|
||||
```c
|
||||
void foo2(wasm_exec_env_t exec_env,
|
||||
uint32 msg_offset,
|
||||
uint32 buffer_offset,
|
||||
int32 buf_len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer;
|
||||
char * msg ;
|
||||
|
||||
// do boundary check
|
||||
if (!wasm_runtime_validate_app_str_add(msg_offset))
|
||||
return 0;
|
||||
|
||||
if (!wasm_runtime_validate_app_addr(buffer_offset, buf_len))
|
||||
return;
|
||||
|
||||
// do address conversion
|
||||
buffer = wasm_runtime_addr_app_to_native(buffer_offset);
|
||||
msg = wasm_runtime_addr_app_to_native(msg_offset);
|
||||
|
||||
strncpy(buffer, msg, buf_len);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Sandbox security attention
|
||||
|
||||
The runtime builder should ensure not broking the memory sandbox when exporting the native function to WASM.
|
||||
|
||||
A few key ground rules:
|
||||
|
||||
- Never pass any structure/class object pointer to native (do data serialization instead)
|
||||
- Do the pointer address conversion in the native API if "$\*" is not used for the pointer in the function signature
|
||||
- Never pass a function pointer to the native
|
||||
|
||||
|
||||
|
||||
## Pass structured data or class object
|
||||
|
||||
We must do data serialization for passing structured data or class objects between the two worlds of WASM and native. There are two serialization methods available in WASM as below, and yet you can introduce more like json, cbor etc.
|
||||
|
||||
- [attributes container](../core/app-framework/app-native-shared/attr_container.c)
|
||||
- [restful request/response](../core/app-framework/app-native-shared/restful_utils.c)
|
||||
|
||||
Note the serialization library is separately compiled into WASM and runtime. And the source files are located in the folder "[core/app-framework/app-native-shared](../core/app-framework/app-native-shared)“ where all source files will be compiled into both worlds.
|
||||
|
||||
|
||||
|
||||
The following sample code demonstrates WASM app packs a response structure to buffer, then pass the buffer pointer to the native:
|
||||
|
||||
```c
|
||||
/*** file name: core/app-framework/base/app/request.c ***/
|
||||
|
||||
void api_response_send(response_t *response)
|
||||
{
|
||||
int size;
|
||||
char * buffer = pack_response(response, &size);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
wasm_response_send(buffer, size); // calling exported native API
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
The following code demonstrates the native API unpack the WASM buffer to local native data structure:
|
||||
|
||||
```c
|
||||
/*** file name: core/app-framework/base/native/request_response.c ***/
|
||||
|
||||
bool
|
||||
wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
response_t response[1];
|
||||
|
||||
if (NULL == unpack_response(buffer, size, response))
|
||||
return false;
|
||||
|
||||
am_send_response(response);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
|
BIN
doc/pics/app_framework.PNG
Normal file
BIN
doc/pics/app_framework.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 38 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
|
@ -92,7 +92,7 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \
|
|||
${IWASM_ROOT}/common/wasm_native.c \
|
||||
${IWASM_ROOT}/common/wasm_exec_env.c \
|
||||
${IWASM_ROOT}/common/arch/${INVOKE_NATIVE} \
|
||||
src/main.c src/ext_lib_export.c
|
||||
src/main.c
|
||||
|
||||
ifeq (${WAMR_BUILD_INTERP}, 1)
|
||||
$(NAME)_SOURCES += ${IWASM_ROOT}/interpreter/wasm_interp.c \
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -4,22 +4,23 @@
|
|||
cmake_minimum_required (VERSION 3.4.1)
|
||||
|
||||
set (CMAKE_VERBOSE_MAKEFILE on)
|
||||
set (CMAKE_BUILD_TYPE Release)
|
||||
|
||||
set (CMAKE_TOOLCHAIN_FILE "$ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake")
|
||||
set (ANDROID_NDK $ENV{ANDROID_NDK_HOME})
|
||||
set (ANDROID_SDK $ENV{ANDROID_SDK_HOME})
|
||||
set (ANDROID_ABI "armeabi-v7a")
|
||||
set (ANDROID_ABI "x86")
|
||||
set (ANDROID_LD lld)
|
||||
|
||||
project (iwasm)
|
||||
|
||||
set (WAMR_BUILD_PLATFORM "android")
|
||||
set (WAMR_BUILD_TARGET "ARMv7")
|
||||
set (WAMR_BUILD_TYPE Debug)
|
||||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
set (WAMR_BUILD_TYPE Release)
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set (WAMR_BUILD_LIBC_WASI 0)
|
||||
set (CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
# Reset default linker flags
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
@ -89,8 +90,12 @@ 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")
|
||||
|
||||
add_library (iwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE} ext_lib_export.c)
|
||||
add_library (iwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
if (CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
target_link_libraries (iwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -landroid -llog -s)
|
||||
else()
|
||||
target_link_libraries (iwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -landroid -llog)
|
||||
endif()
|
||||
|
||||
set (distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build/distribution)
|
||||
set_target_properties (iwasm PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${distribution_DIR}/wasm/lib")
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -62,7 +62,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
|||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
add_executable (iwasm main.c ext_lib_export.c)
|
||||
add_executable (iwasm main.c)
|
||||
|
||||
install (TARGETS iwasm DESTINATION bin)
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -113,4 +113,3 @@ add_library (vmlib
|
|||
${IWASM_AOT_SOURCE}
|
||||
${IWASM_COMPL_SOURCE})
|
||||
|
||||
add_library (extlib ext_lib_export.c)
|
||||
|
|
|
@ -96,7 +96,7 @@ Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fst
|
|||
Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++
|
||||
Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \
|
||||
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
|
||||
libvmlib.a libextlib.a \
|
||||
libvmlib.a \
|
||||
-Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \
|
||||
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
|
||||
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
|
||||
|
@ -174,11 +174,7 @@ libvmlib.a: ../build/libvmlib.a
|
|||
@cp $< $@
|
||||
@echo "CP $@ <= $<"
|
||||
|
||||
libextlib.a: ../build/libextlib.a
|
||||
@cp $< $@
|
||||
@echo "CP $@ <= $<"
|
||||
|
||||
$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) libvmlib.a libextlib.a
|
||||
$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) libvmlib.a
|
||||
@$(CXX) $^ -o $@ $(Enclave_Link_Flags)
|
||||
@echo "LINK => $@"
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -76,7 +76,7 @@ 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")
|
||||
|
||||
add_executable (iwasm main.c ext_lib_export.c)
|
||||
add_executable (iwasm main.c)
|
||||
|
||||
install (TARGETS iwasm DESTINATION bin)
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -66,7 +66,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
|||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
add_executable (iwasm main.c ext_lib_export.c)
|
||||
add_executable (iwasm main.c)
|
||||
|
||||
install (TARGETS iwasm DESTINATION bin)
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -80,6 +80,5 @@ set (VM_LIB_SRCS
|
|||
|
||||
target_sources(app PRIVATE
|
||||
${VM_LIB_SRCS}
|
||||
src/main.c
|
||||
src/ext_lib_export.c)
|
||||
src/main.c)
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -112,3 +112,9 @@ First, connect PC and STM32 with UART. Then install to use host_tool.</br>
|
|||
- Install AOT version WASM application
|
||||
`wamrc --target=thumbv7 --target-abi=eabi --cpu=cortex-m7 -o ui_app.aot ui_app.wasm`
|
||||
`./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app.aot`
|
||||
|
||||
|
||||
|
||||
The graphic user interface demo photo:
|
||||
|
||||
![WAMR samples diagram](../../doc/pics/vgl_demo.png "WAMR samples diagram")
|
|
@ -42,7 +42,6 @@ include_directories(
|
|||
set (SOURCES
|
||||
${PROJECT_SRC_DIR}/main.c
|
||||
${PROJECT_SRC_DIR}/iwasm_main.c
|
||||
${PROJECT_SRC_DIR}/../../ext_lib_export.c
|
||||
${LV_DRIVERS_SOURCES}
|
||||
)
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#include "lib_export.h"
|
||||
#include "sensor_native_api.h"
|
||||
#include "connection_native_api.h"
|
||||
#include "gui_native_api.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "runtime_sensor.inl"
|
||||
#include "connection.inl"
|
||||
#include "wamr_gui.inl"
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -73,5 +73,4 @@ target_sources(app PRIVATE
|
|||
${LVGL_DRV_SRCS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c
|
||||
)
|
||||
|
|
|
@ -4,7 +4,6 @@ This sample demonstrates that a graphic user interface application in WebAssembl
|
|||
|
||||
In this sample, the whole LittlevGL source code is built into the WebAssembly code with the user application. The platform interfaces defined by LittlevGL is implemented in the runtime and exported to the application through the declarations from source "ext_lib_export.c" as below:
|
||||
|
||||
EXPORT_WASM_API(display_init),
|
||||
EXPORT_WASM_API(display_input_read),
|
||||
EXPORT_WASM_API(display_flush),
|
||||
EXPORT_WASM_API(display_fill),
|
||||
|
|
|
@ -38,7 +38,7 @@ fi
|
|||
|
||||
echo "##################### 0. build wamr-sdk littlevgl start#####################"
|
||||
cd ${WAMR_DIR}/wamr-sdk
|
||||
./build_sdk.sh -n littlevgl -x ${PROJECT_DIR}/wamr_config_littlevgl.cmake -e ${LV_CFG_PATH}
|
||||
./build_sdk.sh -n littlevgl -x ${PROJECT_DIR}/wamr_config_littlevgl.cmake -e ${LV_CFG_PATH} -c
|
||||
[ $? -eq 0 ] || exit $?
|
||||
echo "#####################build wamr-sdk littlevgl success"
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
|||
|
||||
add_executable (vgl_wasm_runtime src/platform/${WAMR_BUILD_PLATFORM}/main.c
|
||||
src/platform/${WAMR_BUILD_PLATFORM}/iwasm_main.c
|
||||
src/ext_lib_export.c src/platform/${WAMR_BUILD_PLATFORM}/display_indev.c
|
||||
src/platform/${WAMR_BUILD_PLATFORM}/display_indev.c
|
||||
src/platform/${WAMR_BUILD_PLATFORM}/mouse.c)
|
||||
|
||||
target_link_libraries (vgl_wasm_runtime vmlib -lm -ldl -lpthread -lSDL2)
|
||||
|
|
|
@ -58,11 +58,11 @@ enum {
|
|||
|
||||
extern void xpt2046_init(void);
|
||||
|
||||
extern bool touchscreen_read(lv_indev_data_t * data);
|
||||
extern bool touchscreen_read(lv_indev_data_t *data);
|
||||
|
||||
extern bool mouse_read(lv_indev_data_t * data);
|
||||
extern bool mouse_read(lv_indev_data_t *data);
|
||||
|
||||
extern void display_init(wasm_exec_env_t exec_env);
|
||||
extern void display_init(void);
|
||||
|
||||
extern void display_deinit(wasm_exec_env_t exec_env);
|
||||
|
||||
|
@ -70,22 +70,21 @@ extern int time_get_ms(wasm_exec_env_t exec_env);
|
|||
|
||||
extern void display_flush(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
int32 color_p_offset);
|
||||
lv_color_t *color);
|
||||
|
||||
extern void display_fill(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color_p);
|
||||
lv_color_t *color);
|
||||
|
||||
extern void display_map(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p);
|
||||
const lv_color_t *color);
|
||||
|
||||
extern bool display_input_read(wasm_exec_env_t exec_env,
|
||||
int32 data_offset);
|
||||
extern bool display_input_read(wasm_exec_env_t exec_env, void *data);
|
||||
|
||||
void display_vdb_write(wasm_exec_env_t exec_env,
|
||||
int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
|
||||
lv_coord_t y, int32 color_p_offset, lv_opa_t opa);
|
||||
void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t *color, lv_opa_t opa);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#include "lib_export.h"
|
||||
#include "sensor_native_api.h"
|
||||
#include "connection_native_api.h"
|
||||
#include "display_indev.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "runtime_sensor.inl"
|
||||
#include "connection.inl"
|
||||
EXPORT_WASM_API(display_init),
|
||||
EXPORT_WASM_API(display_input_read),
|
||||
EXPORT_WASM_API(display_flush),
|
||||
EXPORT_WASM_API(display_fill),
|
||||
EXPORT_WASM_API(display_vdb_write),
|
||||
EXPORT_WASM_API(display_map),
|
||||
EXPORT_WASM_API(time_get_ms)
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -41,7 +41,7 @@ static volatile bool sdl_refr_qry = false;
|
|||
static volatile bool sdl_quit_qry = false;
|
||||
|
||||
void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p)
|
||||
const lv_color_t * color)
|
||||
{
|
||||
/*Return if the area is out the screen*/
|
||||
if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1
|
||||
|
@ -53,10 +53,10 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
uint32_t w = x2 - x1 + 1;
|
||||
|
||||
for (y = y1; y <= y2; y++) {
|
||||
memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p,
|
||||
memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color,
|
||||
w * sizeof(lv_color_t));
|
||||
|
||||
color_p += w;
|
||||
color += w;
|
||||
}
|
||||
sdl_refr_qry = true;
|
||||
|
||||
|
@ -72,7 +72,7 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
* @param color fill color
|
||||
*/
|
||||
void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color)
|
||||
lv_color_t *color)
|
||||
{
|
||||
/*Return if the area is out the screen*/
|
||||
if (x2 < 0)
|
||||
|
@ -92,7 +92,7 @@ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint32_t color32 = color.full; //lv_color_to32(color);
|
||||
uint32_t color32 = color->full; //lv_color_to32(color);
|
||||
|
||||
for (x = act_x1; x <= act_x2; x++) {
|
||||
for (y = act_y1; y <= act_y2; y++) {
|
||||
|
@ -109,10 +109,10 @@ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
* @param y1 top coordinate
|
||||
* @param x2 right coordinate
|
||||
* @param y2 bottom coordinate
|
||||
* @param color_p an array of colors
|
||||
* @param color an array of colors
|
||||
*/
|
||||
void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p)
|
||||
const lv_color_t *color)
|
||||
{
|
||||
/*Return if the area is out the screen*/
|
||||
if (x2 < 0)
|
||||
|
@ -135,11 +135,11 @@ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
|
||||
for (y = act_y1; y <= act_y2; y++) {
|
||||
for (x = act_x1; x <= act_x2; x++) {
|
||||
tft_fb[y * MONITOR_HOR_RES + x] = color_p->full; //lv_color_to32(*color_p);
|
||||
color_p++;
|
||||
tft_fb[y * MONITOR_HOR_RES + x] = color->full; //lv_color_to32(*color);
|
||||
color++;
|
||||
}
|
||||
|
||||
color_p += x2 - act_x2;
|
||||
color += x2 - act_x2;
|
||||
}
|
||||
|
||||
sdl_refr_qry = true;
|
||||
|
@ -147,62 +147,64 @@ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|||
|
||||
|
||||
void
|
||||
display_init(wasm_exec_env_t exec_env)
|
||||
display_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
display_flush(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
int32 color_p_offset)
|
||||
lv_color_t *color)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
|
||||
return;
|
||||
lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst,
|
||||
color_p_offset);
|
||||
|
||||
monitor_flush(x1, y1, x2, y2, color_p);
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
color, sizeof(lv_color_t)))
|
||||
return;
|
||||
|
||||
monitor_flush(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
void
|
||||
display_fill(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color_p)
|
||||
lv_color_t *color)
|
||||
{
|
||||
monitor_fill(x1, y1, x2, y2, color_p);
|
||||
monitor_fill(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
void
|
||||
display_map(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p)
|
||||
const lv_color_t *color)
|
||||
{
|
||||
monitor_map(x1, y1, x2, y2, color_p);
|
||||
monitor_map(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
typedef struct display_input_data {
|
||||
lv_point_t point;
|
||||
int32 user_data_offset;
|
||||
uint8 state;
|
||||
} display_input_data;
|
||||
|
||||
bool
|
||||
display_input_read(wasm_exec_env_t exec_env,
|
||||
int32 data_p_offset)
|
||||
void *input_data_app)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
display_input_data *data_app = (display_input_data*)input_data_app;
|
||||
bool ret;
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1))
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
data_app,
|
||||
sizeof(display_input_data)))
|
||||
return false;
|
||||
|
||||
struct {
|
||||
lv_point_t point;
|
||||
int32 user_data_offset;
|
||||
uint8 state;
|
||||
} *data_app;
|
||||
|
||||
lv_indev_data_t data = {0};
|
||||
|
||||
ret = mouse_read(&data);
|
||||
|
||||
data_app = wasm_runtime_addr_app_to_native(module_inst,
|
||||
data_p_offset);
|
||||
|
||||
data_app->point = data.point;
|
||||
data_app->user_data_offset =
|
||||
wasm_runtime_addr_native_to_app(module_inst, data.user_data);
|
||||
|
@ -218,35 +220,17 @@ display_deinit(wasm_exec_env_t exec_env)
|
|||
|
||||
void
|
||||
display_vdb_write(wasm_exec_env_t exec_env,
|
||||
int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
|
||||
lv_coord_t y, int32 color_p_offset, lv_opa_t opa)
|
||||
void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t *color, lv_opa_t opa)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
|
||||
unsigned char *buf_xy = (unsigned char*)buf + 4 * x + 4 * y * buf_w;
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
color, sizeof(lv_color_t)))
|
||||
return;
|
||||
lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst,
|
||||
color_p_offset);
|
||||
|
||||
void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset);
|
||||
|
||||
unsigned char *buf_xy = buf + 4 * x + 4 * y * buf_w;
|
||||
lv_color_t * temp = (lv_color_t *) buf_xy;
|
||||
*temp = *color;
|
||||
/*
|
||||
if (opa != LV_OPA_COVER) {
|
||||
lv_color_t mix_color;
|
||||
|
||||
mix_color.red = *buf_xy;
|
||||
mix_color.green = *(buf_xy+1);
|
||||
mix_color.blue = *(buf_xy+2);
|
||||
color = lv_color_mix(color, mix_color, opa);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
*buf_xy = color->red;
|
||||
*(buf_xy + 1) = color->green;
|
||||
*(buf_xy + 2) = color->blue;
|
||||
*/
|
||||
*(lv_color_t *)buf_xy = *color;
|
||||
}
|
||||
|
||||
int monitor_sdl_refr_thread(void * param)
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include "bi-inc/attr_container.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wasm_export.h"
|
||||
#include "sensor_native_api.h"
|
||||
#include "connection_native_api.h"
|
||||
#include "display_indev.h"
|
||||
|
||||
#define MAX 2048
|
||||
|
||||
#ifndef CONNECTION_UART
|
||||
|
@ -389,7 +393,9 @@ static bool parse_args(int argc, char *argv[])
|
|||
{ "uart", required_argument, NULL, 'u' },
|
||||
{ "baudrate", required_argument, NULL, 'b' },
|
||||
#endif
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
{ "wasi_root", required_argument, NULL, 'w' },
|
||||
#endif
|
||||
{ "help", required_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
@ -421,12 +427,14 @@ static bool parse_args(int argc, char *argv[])
|
|||
printf("uart baudrate: %s\n", optarg);
|
||||
break;
|
||||
#endif
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
case 'w':
|
||||
if (!wasm_set_wasi_root_dir(optarg)) {
|
||||
printf("Fail to set wasi root dir: %s\n", optarg);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'h':
|
||||
showUsage();
|
||||
return false;
|
||||
|
@ -439,10 +447,22 @@ static bool parse_args(int argc, char *argv[])
|
|||
return true;
|
||||
}
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
#include "runtime_sensor.inl"
|
||||
#include "connection.inl"
|
||||
EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_vdb_write, "(*iii*i)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_map, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(time_get_ms, "()i")
|
||||
};
|
||||
|
||||
// Driver function
|
||||
int iwasm_main(int argc, char *argv[])
|
||||
{
|
||||
korp_thread tid;
|
||||
uint32 n_native_symbols;
|
||||
|
||||
if (!parse_args(argc, argv))
|
||||
return -1;
|
||||
|
@ -457,6 +477,13 @@ int iwasm_main(int argc, char *argv[])
|
|||
goto fail1;
|
||||
}
|
||||
|
||||
/* Register native functions */
|
||||
n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
if (!wasm_runtime_register_natives("env",
|
||||
native_symbols, n_native_symbols)) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (!init_connection_framework()) {
|
||||
vm_thread_sys_destroy();
|
||||
goto fail1;
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
#define MONITOR_ZOOM 1
|
||||
#endif
|
||||
|
||||
extern int ili9340_init();
|
||||
|
||||
static int lcd_initialized = 0;
|
||||
|
||||
void
|
||||
display_init(wasm_exec_env_t exec_env)
|
||||
display_init(void)
|
||||
{
|
||||
if (lcd_initialized != 0) {
|
||||
return;
|
||||
|
@ -32,23 +34,23 @@ display_init(wasm_exec_env_t exec_env)
|
|||
void
|
||||
display_flush(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
int32 color_p_offset)
|
||||
lv_color_t *color)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
|
||||
struct display_buffer_descriptor desc;
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
color, sizeof(lv_color_t)))
|
||||
return;
|
||||
lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst,
|
||||
color_p_offset);
|
||||
|
||||
u16_t w = x2 - x1 + 1;
|
||||
u16_t h = y2 - y1 + 1;
|
||||
struct display_buffer_descriptor desc;
|
||||
|
||||
desc.buf_size = 3 * w * h;
|
||||
desc.width = w;
|
||||
desc.pitch = w;
|
||||
desc.height = h;
|
||||
display_write(NULL, x1, y1, &desc, (void *) color_p);
|
||||
display_write(NULL, x1, y1, &desc, (void *)color);
|
||||
|
||||
/*lv_flush_ready();*/
|
||||
}
|
||||
|
@ -56,27 +58,28 @@ display_flush(wasm_exec_env_t exec_env,
|
|||
void
|
||||
display_fill(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color_p)
|
||||
lv_color_t *color)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
display_map(wasm_exec_env_t exec_env,
|
||||
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p)
|
||||
const lv_color_t *color)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
display_input_read(wasm_exec_env_t exec_env, int32 data_p_offset)
|
||||
display_input_read(wasm_exec_env_t exec_env, void *data)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1))
|
||||
return false;
|
||||
lv_indev_data_t * data = wasm_runtime_addr_app_to_native(module_inst,
|
||||
data_p_offset);
|
||||
lv_indev_data_t *lv_data = (lv_indev_data_t*)data;
|
||||
|
||||
return touchscreen_read(data);
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
lv_data, sizeof(lv_indev_data_t)))
|
||||
return false;
|
||||
|
||||
return touchscreen_read(lv_data);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,28 +89,16 @@ display_deinit(wasm_exec_env_t exec_env)
|
|||
|
||||
void
|
||||
display_vdb_write(wasm_exec_env_t exec_env,
|
||||
int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
|
||||
lv_coord_t y, int32 color_p_offset, lv_opa_t opa)
|
||||
void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t *color, lv_opa_t opa)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
|
||||
u8_t *buf_xy = (u8_t*)buf + 3 * x + 3 * y * buf_w;
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(module_inst,
|
||||
color, sizeof(lv_color_t)))
|
||||
return;
|
||||
lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst,
|
||||
color_p_offset);
|
||||
|
||||
void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset);
|
||||
|
||||
u8_t *buf_xy = buf + 3 * x + 3 * y * buf_w;
|
||||
/*
|
||||
if (opa != LV_OPA_COVER) {
|
||||
lv_color_t mix_color;
|
||||
|
||||
mix_color.red = *buf_xy;
|
||||
mix_color.green = *(buf_xy+1);
|
||||
mix_color.blue = *(buf_xy+2);
|
||||
color = lv_color_mix(color, mix_color, opa);
|
||||
}
|
||||
*/
|
||||
*buf_xy = color->red;
|
||||
*(buf_xy + 1) = color->green;
|
||||
*(buf_xy + 2) = color->blue;
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "bi-inc/attr_container.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wasm_export.h"
|
||||
#include "sensor_native_api.h"
|
||||
#include "connection_native_api.h"
|
||||
#include "display_indev.h"
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <drivers/uart.h>
|
||||
|
@ -30,7 +33,6 @@ int uart_char_cnt = 0;
|
|||
static void uart_irq_callback(struct device *dev)
|
||||
{
|
||||
unsigned char ch;
|
||||
int size = 0;
|
||||
|
||||
while (uart_poll_in(dev, &ch) == 0) {
|
||||
uart_char_cnt++;
|
||||
|
@ -77,11 +79,21 @@ timer_ctx_t timer_ctx;
|
|||
|
||||
static char global_heap_buf[370 * 1024] = { 0 };
|
||||
|
||||
extern void display_init(void);
|
||||
static NativeSymbol native_symbols[] = {
|
||||
#include "runtime_sensor.inl"
|
||||
#include "connection.inl"
|
||||
EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_vdb_write, "(*iii*i)"),
|
||||
EXPORT_WASM_API_WITH_SIG(display_map, "(iiii*)"),
|
||||
EXPORT_WASM_API_WITH_SIG(time_get_ms, "()i")
|
||||
};
|
||||
|
||||
int iwasm_main()
|
||||
{
|
||||
korp_thread tid, tm_tid;
|
||||
uint32 n_native_symbols;
|
||||
|
||||
host_init();
|
||||
|
||||
|
@ -95,6 +107,13 @@ int iwasm_main()
|
|||
goto fail1;
|
||||
}
|
||||
|
||||
/* Register native functions */
|
||||
n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
if (!wasm_runtime_register_natives("env",
|
||||
native_symbols, n_native_symbols)) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
display_init();
|
||||
|
||||
// timer manager
|
||||
|
|
|
@ -65,5 +65,4 @@ target_sources(app PRIVATE
|
|||
${LVGL_DRV_SRCS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c
|
||||
)
|
||||
|
|
|
@ -10,13 +10,26 @@
|
|||
|
||||
#include "lvgl/lv_misc/lv_color.h"
|
||||
#include "lvgl/lv_hal/lv_hal_indev.h"
|
||||
|
||||
extern void display_init(void);
|
||||
extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p);
|
||||
extern bool display_input_read(lv_indev_data_t * data);
|
||||
|
||||
extern void display_deinit(void);
|
||||
extern void display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x,
|
||||
lv_coord_t y, lv_color_t *color, lv_opa_t opa);
|
||||
|
||||
extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color);
|
||||
|
||||
extern bool display_input_read(lv_indev_data_t *data);
|
||||
|
||||
extern void display_vdb_write(void *buf,
|
||||
lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t *color, lv_opa_t opa);
|
||||
|
||||
void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t *color);
|
||||
|
||||
void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t *color);
|
||||
|
||||
extern uint32_t time_get_ms(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,27 +119,32 @@ void on_init()
|
|||
* Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
|
||||
*/
|
||||
void display_flush_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p)
|
||||
const lv_color_t * color_p)
|
||||
{
|
||||
display_flush(x1, y1, x2, y2, color_p);
|
||||
lv_flush_ready();
|
||||
}
|
||||
void display_vdb_write_wrapper(uint8_t *buf, lv_coord_t buf_w, lv_coord_t x,
|
||||
lv_coord_t y, lv_color_t color, lv_opa_t opa)
|
||||
|
||||
void display_vdb_write_wrapper(uint8_t *buf,
|
||||
lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
display_vdb_write(buf, buf_w, x, y, &color, opa);
|
||||
}
|
||||
extern void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color_p);
|
||||
extern void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
const lv_color_t * color_p);
|
||||
|
||||
void display_fill_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
||||
lv_color_t color)
|
||||
{
|
||||
display_fill(x1, y1, x2, y2, &color);
|
||||
}
|
||||
|
||||
static void hal_init(void)
|
||||
{
|
||||
/* Add a display*/
|
||||
lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
|
||||
disp_drv.disp_flush = display_flush_wrapper; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
|
||||
disp_drv.disp_fill = display_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
|
||||
disp_drv.disp_fill = display_fill_wrapper; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
|
||||
disp_drv.disp_map = display_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
|
||||
#if LV_VDB_SIZE != 0
|
||||
disp_drv.vdb_wr = display_vdb_write_wrapper;
|
||||
|
|
|
@ -27,7 +27,7 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
|||
#Note: uncomment below line to use UART mode
|
||||
#add_definitions (-DCONNECTION_UART)
|
||||
|
||||
add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c)
|
||||
add_executable (simple src/main.c src/iwasm_main.c)
|
||||
target_link_libraries (simple vmlib -lm -ldl -lpthread -lrt)
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#include "lib_export.h"
|
||||
#include "sensor_native_api.h"
|
||||
#include "timer_native_api.h"
|
||||
#include "req_resp_native_api.h"
|
||||
#include "connection_native_api.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "runtime_sensor.inl"
|
||||
#include "connection.inl"
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -121,7 +121,7 @@ add_library (vmlib
|
|||
|
||||
add_library (aotclib ${IWASM_COMPL_SOURCE})
|
||||
|
||||
add_executable (wamrc main.c ext_lib_export.c)
|
||||
add_executable (wamrc main.c)
|
||||
|
||||
target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread)
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext_lib_export.h"
|
|
@ -1,52 +1,126 @@
|
|||
# SDK for Wasm Micro Runtime
|
||||
This folder contains some tools to generate sdk for wamr runtime and wasm applications, the script and cmake files here are called by `make`, don't use them manually.
|
||||
# WebAssembly Micro Runtime SDK
|
||||
|
||||
|
||||
**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK.
|
||||
|
||||
|
||||
|
||||
### SDK profile and configuration file
|
||||
|
||||
A SDK profile presents a configuration of build parameters for the selection of CPU architecture, software platforms, execution mode, libc and application framework components. The profile configurations are saved in a cmake file that will be included by the WAMR SDK building tool `build_sdk.sh`.
|
||||
|
||||
Here is the default configuration file [wamr-sdk/wamr_config_default.cmake](./wamr_config_default.cmake):
|
||||
|
||||
## Build the SDK
|
||||
``` Bash
|
||||
cd ${WAMR_ROOT}/wamr-sdk
|
||||
make config
|
||||
```
|
||||
Following the prompt to finish the settings for your customized runtime and app sdk, then you will get `out` folder under `${WAMR_ROOT}`
|
||||
|
||||
The structure of the output folder is like bellow:
|
||||
set (WAMR_BUILD_PLATFORM "linux")
|
||||
set (WAMR_BUILD_TARGET X86_64)
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set (WAMR_BUILD_LIBC_WASI 0)
|
||||
set (WAMR_BUILD_APP_FRAMEWORK 1)
|
||||
set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE)
|
||||
```
|
||||
out
|
||||
|--app-sdk/
|
||||
| |--sysroot/
|
||||
| |--wamr_toolchain.cmake
|
||||
|
|
||||
|--runtime-sdk/
|
||||
|--include
|
||||
|--lib
|
||||
|--wamr_config.cmake
|
||||
|
||||
|
||||
|
||||
Execute following command to build the WAMR SDK for a configuration profile:
|
||||
|
||||
```
|
||||
cd wamr-sdk
|
||||
./build_sdk.sh -n [profile name] -x [config file path]
|
||||
```
|
||||
### app-sdk usage
|
||||
The `app-sdk` is used to develop wasm applications, if your project are built with cmake, then the `wamr_toolchain.cmake` file is what you need to compile your project into wasm bytecode.
|
||||
|
||||
### runtime-sdk usage
|
||||
The `runtime-sdk` is used to help you embed WAMR runtime into your product easier. There are two method you can use the SDK:
|
||||
The output directory structure of a SDK package with profile name "simple":
|
||||
|
||||
1. Use the provided `runtime_lib.cmake` file:
|
||||
```
|
||||
simple/
|
||||
├── app-sdk
|
||||
│ ├── libc-builtin-sysroot
|
||||
│ │ ├── include
|
||||
│ │ └── share
|
||||
│ └── wamr-app-framework
|
||||
│ ├── include
|
||||
│ │ ├── bi-inc
|
||||
│ │ └── wa-inc
|
||||
│ ├── lib
|
||||
│ └── share
|
||||
└── runtime-sdk
|
||||
├── include
|
||||
│ └── bi-inc
|
||||
└── lib
|
||||
```
|
||||
|
||||
You can include `${WAMR_ROOT}/cmake/runtime_lib.cmake` in your project's `CMakeLists.txt` file:
|
||||
``` cmake
|
||||
include (${WAMR_ROOT}/cmake/runtime_lib.cmake)
|
||||
add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
# ......
|
||||
target_link_libraries (your_target vmlib -lm -ldl -lpthread)
|
||||
```
|
||||
2. Use the pre-built static library:
|
||||
|
||||
You can link the pre-built library:
|
||||
``` cmake
|
||||
link_directories(${SDK_DIR}/runtime-sdk/lib)
|
||||
include_directories(${SDK_DIR}/runtime-sdk/include)
|
||||
# ......
|
||||
target_link_libraries (your_target vmlib -lm -ldl -lpthread)
|
||||
```
|
||||
|
||||
This method can also be used when you don't use cmake
|
||||
Like the WAMR samples, a project probably has its own pre-defined SDK configuration file. The project building script can call the `build_sdk.sh` by passing the configuration file name to the build_sdk.sh to generate its own WAMR SDK package.
|
||||
|
||||
|
||||
|
||||
### Menu configuration for building SDK
|
||||
|
||||
Menu configuration is supported for easy integration of runtime components and application libraries for the target architecture and platform. Run following command to start the menu config.
|
||||
|
||||
```
|
||||
cd wamr-sdk
|
||||
./build_sdk.sh -i -n [profile name]
|
||||
```
|
||||
|
||||
The argument "-i" will make the command enter menu config mode as depicted below.
|
||||
|
||||
<img src="C:/Users/xwang98/repos/ssg_micro_runtime-wasm-poc/doc/pics/wamr_menu_config.png" alt="wamr build menu configuration" style="zoom:80%;" />
|
||||
|
||||
After the menu configuration is finished, the profile config file is saved and the building process is automatically started. When the building gets successful, the SDK package is generated under folder $wamr-sdk/out/{profile}, and the header files of configured components were copied into the SDK package.
|
||||
|
||||
|
||||
|
||||
### Build WASM applications with APP-SDK
|
||||
|
||||
The folder “**app-sdk**” under the profile output directory contains all the header files and WASM library for developing the WASM application. For C/C++ based WASM applications, the developers can use conventional cross-compilation procedure to build the WASM application. According to the profile selection of libc, following cmake toolchain files under folder [wamr-sdk/app](./app) are available for cross compiling WASM application:
|
||||
|
||||
- ` wamr_toolchain.cmake`
|
||||
- `wasi_toolchain.cmake`
|
||||
|
||||
|
||||
|
||||
Refer to [build WASM applications](./doc/build_wasm_app.md) for the details.
|
||||
|
||||
|
||||
|
||||
### Use Runtime SDK to build native application
|
||||
|
||||
The output folder "**runtime-sdk**" contains all the header files and library files for integration with project native code.
|
||||
|
||||
You can link the pre-built library:
|
||||
``` cmake
|
||||
link_directories(${SDK_DIR}/runtime-sdk/lib)
|
||||
include_directories(${SDK_DIR}/runtime-sdk/include)
|
||||
# ......
|
||||
target_link_libraries (your_target vmlib -lm -ldl -lpthread)
|
||||
```
|
||||
|
||||
This method can also be used when you don't use cmake
|
||||
|
||||
You can refer to this sample: [CMakeLists.txt](../samples/simple/CMakeLists.txt).
|
||||
|
||||
> NOTE: If you are familiar with how to configure WAMR by cmake and don't want to build the SDK, you can set the related settings on the top of your `CMakeLists.txt`, then the `runtime_lib.cmake` will not load settings from the SDK.
|
||||
> NOTE: If you are familiar with how to configure WAMR by cmake and don't want to build the SDK, you can set the related settings on the top of your `CMakeLists.txt`, then the `runtime_lib.cmake` will not load settings from the SDK.
|
||||
|
||||
|
||||
|
||||
### Integrate WAMR without pre-built WAMR library
|
||||
|
||||
Use the provided `runtime_lib.cmake` file:
|
||||
|
||||
You can include `${WAMR_ROOT}/cmake/runtime_lib.cmake` in your project's `CMakeLists.txt` file:
|
||||
|
||||
``` cmake
|
||||
include (${WAMR_ROOT}/cmake/runtime_lib.cmake)
|
||||
add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
# ......
|
||||
target_link_libraries (your_target vmlib -lm -ldl -lpthread)
|
||||
```
|
||||
|
||||
You can refer to to product-mini building for Linux: [`product-mini/platforms/linux/CMakeLists.txt`](../product-mini/platforms/linux/CMakeLists.txt).
|
||||
|
||||
>
|
Loading…
Reference in New Issue
Block a user