Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Wang Xin 2020-03-05 19:03:28 +08:00
commit 662aeb09e9
97 changed files with 2302 additions and 2319 deletions

View File

@ -14,8 +14,8 @@ WORKDIR /root
RUN git clone https://github.com/intel/wasm-micro-runtime
RUN cd wasm-micro-runtime/core/iwasm/products/linux/ && mkdir build && \
RUN cd wasm-micro-runtime/product-mini/platforms/linux/ && mkdir build && \
cd build && cmake .. && make
RUN cd /usr/bin && ln -s wasm-ld-8 wasm-ld
RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm iwasm
RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm iwasm

119
README.md
View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,8 @@
set (WASM_LIB_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions (-DAPP_FRAMEWORK_SENSOR)
include_directories(${WASM_LIB_SENSOR_DIR})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -0,0 +1,10 @@
WASM application management
=======
## structure
<img src="../../doc/pics/wamr-arch.JPG" width="80%">

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
return true;
}
void
wasm_native_destroy()
{
void *ret;
NativeSymbolsNode *node, *node_next;
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;
node = g_native_symbols_list;
while (node) {
node_next = node->next;
bh_free(node);
node = node_next;
}
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;
g_native_symbols_list = g_native_symbols_list_end = NULL;
}

View File

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

View File

@ -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:
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
{
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
stacks[n_stacks++] = *argv_src++;
/* 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++] = arg_i32;
else
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:
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
{
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
stacks[n_stacks++] = *argv_src++;
/* 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++] = arg_i64;
else
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) */

View File

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

View File

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

View File

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

View File

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

View File

@ -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,87 +279,24 @@ 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;
wasm_ret_type = VALUE_TYPE_VOID;
ret_type = VOID_TYPE;
}
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
aot_set_last_error("llvm build load failed.");
/* 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;
}
/* 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;
}
}
}
else {
func = func_ctxes[func_idx - import_func_count]->func;
}
/* Call the function */
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
@ -239,6 +309,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* 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,8 +458,7 @@ 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))
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]);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,6 +2983,7 @@ handle_next_reachable_block:
POP_TYPE(func_type->types[idx]);
}
if (func_type->result_count > 0)
PUSH_TYPE(func_type->types[func_type->param_count]);
func->has_op_func_call = true;

View File

@ -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);
if (buffer_offset != 0) {
char *buffer;
int32 buffer_offset = wasm_module_malloc(module_inst, size,
(void**)&buffer);
if (buffer_offset != 0) {
buffer = wasm_addr_app_to_native(module_inst, buffer_offset);
bh_memcpy_s(buffer, size, src, size);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,202 +2,239 @@
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
}
};
// ensure the memory and runtime initialization is finsihed
// before registering the native functions
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
wasm_runtime_init();
int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
if (!wasm_runtime_register_natives("env",
native_symbols,
n_native_symbols)) {
goto fail1;
}
// natives registeration must be done before loading WASM modules
module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf));
```
**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];
int c = foo(a, b); // call into native foo_native()
foo2(msg, buffer, sizeof(buffer)); // call into native foo2()
example_native_func(a, b);
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -113,4 +113,3 @@ add_library (vmlib
${IWASM_AOT_SOURCE}
${IWASM_COMPL_SOURCE})
add_library (extlib ext_lib_export.c)

View File

@ -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 => $@"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -62,7 +62,7 @@ extern bool touchscreen_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

View File

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

View File

@ -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);
}
bool
display_input_read(wasm_exec_env_t exec_env,
int32 data_p_offset)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
bool ret;
if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1))
return false;
struct {
typedef struct display_input_data {
lv_point_t point;
int32 user_data_offset;
uint8 state;
} *data_app;
} display_input_data;
bool
display_input_read(wasm_exec_env_t exec_env,
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_native_addr(module_inst,
data_app,
sizeof(display_input_data)))
return false;
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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -124,22 +124,27 @@ void display_flush_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
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;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,41 +1,96 @@
# 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:
```
### 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:
1. 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)
cd wamr-sdk
./build_sdk.sh -n [profile name] -x [config file path]
```
2. Use the pre-built static library:
The output 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
```
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="../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
@ -50,3 +105,22 @@ The `runtime-sdk` is used to help you embed WAMR runtime into your product easie
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.
### 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).
>