Enable AoT and wamr-sdk, and change arguments of call wasm API (#157)
* Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c * Add more strict security checks for libc wrapper API's * Use one libc wrapper copy for sgx and other platforms; remove bh_printf macro for other platform header files * Enhance security of libc strcpy/sprintf wrapper function * Fix issue of call native for x86_64/arm/mips, add module inst parameter for native wrapper functions * Remove get_module_inst() and fix issue of call native * Refine wgl lib: remove module_inst parameter from widget functions; move function index check to runtime instantiate * Refine interpreter call native process, refine memory boudary check * Fix issues of invokeNative function of arm/mips/general version * Add a switch to build simple sample without gui support * Add BUILD_TARGET setting in makefile to replace cpu compiler flags in source code * Re-org shared lib header files, remove unused info; fix compile issues of vxworks * Add build target general * Remove unused files * Update license header * test push * Restore file * Sync up with internal/feature * Sync up with internal/feature * Rename build_wamr_app to build_wasm_app * Fix small issues of README * Enhance malformed wasm file checking Fix issue of print hex int and implement utf8 string check Fix wasi file read/write right issue Fix minor issue of build wasm app doc * Sync up with internal/feature * Sync up with internal/feature: fix interpreter arm issue, fix read leb issue * Sync up with internal/feature * Fix bug of config.h and rename wasi config.h to ssp_config.h * Sync up with internal/feature * Import wamr aot * update document * update document * Update document, disable WASI in 32bit * update document * remove files * update document * Update document * update document * update document * update samples * Sync up with internal repo
This commit is contained in:
2511
core/iwasm/aot/aot_loader.c
Normal file
2511
core/iwasm/aot/aot_loader.c
Normal file
File diff suppressed because it is too large
Load Diff
858
core/iwasm/aot/aot_runtime.c
Normal file
858
core/iwasm/aot/aot_runtime.c
Normal file
@ -0,0 +1,858 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_runtime.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_log.h"
|
||||
#include "mem_alloc.h"
|
||||
|
||||
static void
|
||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||
{
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size, "%s", string);
|
||||
}
|
||||
|
||||
static bool
|
||||
global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i;
|
||||
InitializerExpression *init_expr;
|
||||
uint8 *p = (uint8*)module_inst->global_data.ptr;
|
||||
AOTImportGlobal *import_global = module->import_globals;;
|
||||
AOTGlobal *global = module->globals;
|
||||
|
||||
/* 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);
|
||||
memcpy(p, &import_global->global_data_linked, import_global->size);
|
||||
p += import_global->size;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
init_expr = &global->init_expr;
|
||||
switch (init_expr->init_expr_type) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
bh_assert(init_expr->u.global_index < module->import_global_count);
|
||||
memcpy(p,
|
||||
&module->import_globals[init_expr->u.global_index].global_data_linked,
|
||||
global->size);
|
||||
break;
|
||||
default:
|
||||
/* TODO: check whether global type and init_expr type are matching */
|
||||
memcpy(p, &init_expr->u, global->size);
|
||||
break;
|
||||
}
|
||||
p += global->size;
|
||||
}
|
||||
|
||||
bh_assert(module_inst->global_data_size == p - (uint8*)module_inst->global_data.ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i, global_index, global_data_offset, base_offset, length;
|
||||
AOTTableInitData *table_seg;
|
||||
|
||||
if (module->table_init_data_count > 0) {
|
||||
for (i = 0; i < module->table_init_data_count; i++) {
|
||||
table_seg = module->table_init_data_list[i];
|
||||
bh_assert(table_seg->offset.init_expr_type ==
|
||||
INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_seg->offset.init_expr_type ==
|
||||
INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
|
||||
/* Resolve table data base offset */
|
||||
if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = table_seg->offset.u.global_index;
|
||||
bh_assert(global_index <
|
||||
module->import_global_count + module->global_count);
|
||||
/* TODO: && globals[table_seg->offset.u.global_index].type ==
|
||||
VALUE_TYPE_I32*/
|
||||
if (global_index < module->import_global_count)
|
||||
global_data_offset =
|
||||
module->import_globals[global_index].data_offset;
|
||||
else
|
||||
global_data_offset =
|
||||
module->globals[global_index - module->import_global_count]
|
||||
.data_offset;
|
||||
|
||||
base_offset = *(uint32*)
|
||||
((uint8*)module_inst->global_data.ptr + global_data_offset);
|
||||
}
|
||||
else
|
||||
base_offset = (uint32)table_seg->offset.u.i32;
|
||||
|
||||
/* Copy table data */
|
||||
length = table_seg->func_index_count;
|
||||
if (base_offset < module_inst->table_size) {
|
||||
memcpy((uint32*)module_inst->table_data.ptr + base_offset,
|
||||
table_seg->func_indexes, length * sizeof(uint32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i, global_index, global_data_offset, base_offset, length;
|
||||
AOTMemInitData *data_seg;
|
||||
uint64 total_size = (uint64)NumBytesPerPage * module->mem_init_page_count;
|
||||
|
||||
/* Allocate memory */
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(module_inst->memory_data.ptr = wasm_malloc((uint32)total_size))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(module_inst->memory_data.ptr, 0, (uint32)total_size);
|
||||
|
||||
/* Init memory info */
|
||||
module_inst->memory_data_end.ptr = (uint8*)module_inst->memory_data.ptr
|
||||
+ total_size;
|
||||
module_inst->memory_data_size = (uint32)total_size;
|
||||
module_inst->mem_cur_page_count = module->mem_init_page_count;
|
||||
module_inst->mem_max_page_count = module->mem_max_page_count;
|
||||
|
||||
if (module->mem_init_page_count > 0) {
|
||||
for (i = 0; i < module->mem_init_data_count; i++) {
|
||||
data_seg = module->mem_init_data_list[i];
|
||||
bh_assert(data_seg->offset.init_expr_type ==
|
||||
INIT_EXPR_TYPE_I32_CONST
|
||||
|| data_seg->offset.init_expr_type ==
|
||||
INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
|
||||
/* Resolve memory data base offset */
|
||||
if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = data_seg->offset.u.global_index;
|
||||
bh_assert(global_index <
|
||||
module->import_global_count + module->global_count);
|
||||
/* TODO: && globals[data_seg->offset.u.global_index].type ==
|
||||
VALUE_TYPE_I32*/
|
||||
if (global_index < module->import_global_count)
|
||||
global_data_offset =
|
||||
module->import_globals[global_index].data_offset;
|
||||
else
|
||||
global_data_offset =
|
||||
module->globals[global_index - module->import_global_count]
|
||||
.data_offset;
|
||||
|
||||
base_offset = *(uint32*)
|
||||
((uint8*)module_inst->global_data.ptr + global_data_offset);
|
||||
}
|
||||
else
|
||||
base_offset = (uint32)data_seg->offset.u.i32;
|
||||
|
||||
length = data_seg->byte_count;
|
||||
|
||||
/* Check memory data */
|
||||
if (length > 0
|
||||
&& (base_offset >= module_inst->memory_data_size
|
||||
|| base_offset + length > module_inst->memory_data_size)) {
|
||||
wasm_free(module_inst->memory_data.ptr);
|
||||
module_inst->memory_data.ptr = NULL;
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: data segment out of range.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy memory data */
|
||||
memcpy((uint8*)module_inst->memory_data.ptr + base_offset,
|
||||
data_seg->bytes, length);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i;
|
||||
void **func_ptrs;
|
||||
uint64 total_size =
|
||||
((uint64)module->import_func_count + module->func_count) * sizeof(void*);
|
||||
|
||||
/* Allocate memory */
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(module_inst->func_ptrs.ptr = wasm_malloc((uint32)total_size))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(module_inst->func_ptrs.ptr, 0, (uint32)total_size);
|
||||
|
||||
/* Set import function pointers */
|
||||
func_ptrs = (void**)module_inst->func_ptrs.ptr;
|
||||
for (i = 0; i < module->import_func_count; i++, func_ptrs++)
|
||||
*func_ptrs = (void*)module->import_funcs[i].func_ptr_linked;
|
||||
|
||||
/* Set defined function pointers */
|
||||
memcpy(func_ptrs, module->func_ptrs, module->func_count * sizeof(void*));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 *func_type_index;
|
||||
uint64 total_size =
|
||||
((uint64)module->import_func_count + module->func_count) * sizeof(uint32);
|
||||
|
||||
/* Allocate memory */
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(module_inst->func_type_indexes.ptr = wasm_malloc((uint32)total_size))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(module_inst->func_type_indexes.ptr, 0, (uint32)total_size);
|
||||
|
||||
/* Set import function type indexes */
|
||||
func_type_index = (uint32*)module_inst->func_type_indexes.ptr;
|
||||
for (i = 0; i < module->import_func_count; i++, func_type_index++)
|
||||
*func_type_index = module->import_funcs[i].func_type_index;
|
||||
|
||||
memcpy(func_type_index, module->func_type_indexes,
|
||||
module->func_count * sizeof(uint32));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_post_inst_function(AOTModuleInstance *module_inst)
|
||||
{
|
||||
AOTFunctionInstance *post_inst_func =
|
||||
aot_lookup_function(module_inst, "__post_instantiate", "()");
|
||||
|
||||
if (!post_inst_func)
|
||||
/* Not found */
|
||||
return true;
|
||||
|
||||
return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_start_function(AOTModuleInstance *module_inst)
|
||||
{
|
||||
AOTModule *module = (AOTModule*)module_inst->aot_module.ptr;
|
||||
WASMExecEnv *exec_env;
|
||||
typedef void (*F)(WASMExecEnv*);
|
||||
union { F f; void *v; } u;
|
||||
|
||||
if (!module->start_function)
|
||||
return true;
|
||||
|
||||
if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst,
|
||||
module_inst->default_wasm_stack_size))) {
|
||||
aot_set_exception(module_inst, "allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
u.v = module->start_function;
|
||||
u.f(exec_env);
|
||||
|
||||
wasm_exec_env_destroy(exec_env);
|
||||
return !aot_get_exception(module_inst);
|
||||
}
|
||||
|
||||
AOTModuleInstance*
|
||||
aot_instantiate(AOTModule *module,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
AOTModuleInstance *module_inst;
|
||||
uint32 module_inst_struct_size =
|
||||
offsetof(AOTModuleInstance, global_table_heap_data.bytes);
|
||||
uint64 table_data_size = (uint64)module->table_size * sizeof(uint32);
|
||||
uint64 total_size = (uint64)module_inst_struct_size
|
||||
+ module->global_data_size
|
||||
+ table_data_size + heap_size;
|
||||
void *heap_handle;
|
||||
uint8 *p;
|
||||
|
||||
/* Check heap size */
|
||||
heap_size = align_uint(heap_size, 8);
|
||||
if (heap_size == 0)
|
||||
heap_size = APP_HEAP_SIZE_DEFAULT;
|
||||
if (heap_size < APP_HEAP_SIZE_MIN)
|
||||
heap_size = APP_HEAP_SIZE_MIN;
|
||||
if (heap_size > APP_HEAP_SIZE_MAX)
|
||||
heap_size = APP_HEAP_SIZE_MAX;
|
||||
|
||||
/* Allocate module instance, global data, table data and heap data */
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(module_inst = wasm_malloc((uint32)total_size))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(module_inst, 0, total_size);
|
||||
module_inst->module_type = Wasm_Module_AoT;
|
||||
module_inst->aot_module.ptr = module;
|
||||
|
||||
/* Initialize global info */
|
||||
p = (uint8*)module_inst + module_inst_struct_size;
|
||||
module_inst->global_data.ptr = p;
|
||||
module_inst->global_data_size = module->global_data_size;
|
||||
if (!global_instantiate(module_inst, module, error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
/* Initialize table info */
|
||||
p += module->global_data_size;
|
||||
module_inst->table_data.ptr = p;
|
||||
module_inst->table_size = module->table_size;
|
||||
/* Set all elements to -1 to mark them as uninitialized elements */
|
||||
memset(module_inst->table_data.ptr, -1, (uint32)table_data_size);
|
||||
if (!table_instantiate(module_inst, module, error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
/* Initialize heap info */
|
||||
p += (uint32)table_data_size;
|
||||
module_inst->heap_data.ptr = p;
|
||||
p += heap_size;
|
||||
module_inst->heap_data_end.ptr = p;
|
||||
module_inst->heap_data_size = heap_size;
|
||||
#if WASM_ENABLE_MEMORY_GROW != 0
|
||||
module_inst->heap_base_offset = DEFAULT_APP_HEAP_BASE_OFFSET;
|
||||
#else
|
||||
module_inst->heap_base_offset = module_inst->memory_data_size;
|
||||
#endif
|
||||
if (!(heap_handle = mem_allocator_create(module_inst->heap_data.ptr,
|
||||
heap_size))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module instantiate failed: init app heap failed.");
|
||||
goto fail;
|
||||
}
|
||||
module_inst->heap_handle.ptr = heap_handle;
|
||||
|
||||
/* Initialize memory space */
|
||||
if (!memory_instantiate(module_inst, module, error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
/* Initialize function pointers */
|
||||
if (!init_func_ptrs(module_inst, module, error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
/* Initialize function type indexes */
|
||||
if (!init_func_type_indexes(module_inst, module, error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst,
|
||||
module->wasi_args.dir_list,
|
||||
module->wasi_args.dir_count,
|
||||
module->wasi_args.map_dir_list,
|
||||
module->wasi_args.map_dir_count,
|
||||
module->wasi_args.env,
|
||||
module->wasi_args.env_count,
|
||||
module->wasi_args.argv,
|
||||
module->wasi_args.argc,
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
/* Initialize the thread related data */
|
||||
if (stack_size == 0)
|
||||
stack_size = DEFAULT_WASM_STACK_SIZE;
|
||||
module_inst->default_wasm_stack_size = stack_size;
|
||||
|
||||
/* Execute __post_instantiate function and start function*/
|
||||
if (!execute_post_inst_function(module_inst)
|
||||
|| !execute_start_function(module_inst)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
module_inst->cur_exception);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return module_inst;
|
||||
|
||||
fail:
|
||||
aot_deinstantiate(module_inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
aot_deinstantiate(AOTModuleInstance *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
/* Destroy wasi resource before freeing app heap, since some fields of
|
||||
wasi contex are allocated from app heap, and if app heap is freed,
|
||||
these fields will be set to NULL, we cannot free their internal data
|
||||
which may allocated from global heap. */
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
|
||||
#endif
|
||||
|
||||
if (module_inst->memory_data.ptr)
|
||||
wasm_free(module_inst->memory_data.ptr);
|
||||
|
||||
if (module_inst->heap_handle.ptr)
|
||||
mem_allocator_destroy(module_inst->heap_handle.ptr);
|
||||
|
||||
if (module_inst->func_ptrs.ptr)
|
||||
wasm_free(module_inst->func_ptrs.ptr);
|
||||
|
||||
if (module_inst->func_type_indexes.ptr)
|
||||
wasm_free(module_inst->func_type_indexes.ptr);
|
||||
|
||||
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)
|
||||
{
|
||||
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))
|
||||
return &module->export_funcs[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define PUT_I64_TO_ADDR(addr, value) do { \
|
||||
union { int64 val; uint32 parts[2]; } u; \
|
||||
u.val = (value); \
|
||||
(addr)[0] = u.parts[0]; \
|
||||
(addr)[1] = u.parts[1]; \
|
||||
} while (0)
|
||||
|
||||
#define PUT_F64_TO_ADDR(addr, value) do { \
|
||||
union { float64 val; uint32 parts[2]; } u; \
|
||||
u.val = (value); \
|
||||
(addr)[0] = u.parts[0]; \
|
||||
(addr)[1] = u.parts[1]; \
|
||||
} while (0)
|
||||
|
||||
bool
|
||||
aot_call_function(WASMExecEnv *exec_env,
|
||||
AOTFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[])
|
||||
{
|
||||
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);
|
||||
return ret && !aot_get_exception(module_inst) ? true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
||||
AOTFunctionInstance *func,
|
||||
unsigned argc, uint32 argv[])
|
||||
{
|
||||
WASMExecEnv *exec_env;
|
||||
bool ret;
|
||||
|
||||
if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst,
|
||||
module_inst->default_wasm_stack_size))) {
|
||||
aot_set_exception(module_inst, "allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = aot_call_function(exec_env, func, argc, argv);
|
||||
wasm_exec_env_destroy(exec_env);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
aot_set_exception(AOTModuleInstance *module_inst,
|
||||
const char *exception)
|
||||
{
|
||||
if (exception)
|
||||
snprintf(module_inst->cur_exception,
|
||||
sizeof(module_inst->cur_exception),
|
||||
"Exception: %s", exception);
|
||||
else
|
||||
module_inst->cur_exception[0] = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
aot_set_exception_with_id(AOTModuleInstance *module_inst,
|
||||
uint32 id)
|
||||
{
|
||||
switch (id) {
|
||||
case EXCE_UNREACHABLE:
|
||||
aot_set_exception(module_inst, "unreachable");
|
||||
break;
|
||||
case EXCE_OUT_OF_MEMORY:
|
||||
aot_set_exception(module_inst, "allocate memory failed");
|
||||
break;
|
||||
case EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS:
|
||||
aot_set_exception(module_inst, "out of bounds memory access");
|
||||
break;
|
||||
case EXCE_INTEGER_OVERFLOW:
|
||||
aot_set_exception(module_inst, "integer overflow");
|
||||
break;
|
||||
case EXCE_INTEGER_DIVIDE_BY_ZERO:
|
||||
aot_set_exception(module_inst, "integer divide by zero");
|
||||
break;
|
||||
case EXCE_INVALID_CONVERSION_TO_INTEGER:
|
||||
aot_set_exception(module_inst, "invalid conversion to integer");
|
||||
break;
|
||||
case EXCE_INVALID_FUNCTION_TYPE_INDEX:
|
||||
aot_set_exception(module_inst, "indirect call type mismatch");
|
||||
break;
|
||||
case EXCE_INVALID_FUNCTION_INDEX:
|
||||
aot_set_exception(module_inst, "invalid function index");
|
||||
break;
|
||||
case EXCE_UNDEFINED_ELEMENT:
|
||||
aot_set_exception(module_inst, "undefined element");
|
||||
break;
|
||||
case EXCE_UNINITIALIZED_ELEMENT:
|
||||
aot_set_exception(module_inst, "uninitialized element");
|
||||
break;
|
||||
case EXCE_CALL_UNLINKED_IMPORT_FUNC:
|
||||
aot_set_exception(module_inst, "fail to call unlinked import function");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
aot_get_exception(AOTModuleInstance *module_inst)
|
||||
{
|
||||
if (module_inst->cur_exception[0] == '\0')
|
||||
return NULL;
|
||||
else
|
||||
return module_inst->cur_exception;
|
||||
}
|
||||
|
||||
void
|
||||
aot_clear_exception(AOTModuleInstance *module_inst)
|
||||
{
|
||||
module_inst->cur_exception[0] = '\0';
|
||||
}
|
||||
|
||||
int32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size)
|
||||
{
|
||||
uint8 *addr =
|
||||
mem_allocator_malloc(module_inst->heap_handle.ptr, size);
|
||||
|
||||
if (!addr) {
|
||||
aot_set_exception(module_inst, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
return (int32)(module_inst->heap_base_offset
|
||||
+ (addr - (uint8*)module_inst->heap_data.ptr));
|
||||
}
|
||||
|
||||
void
|
||||
aot_module_free(AOTModuleInstance *module_inst, int32 ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
uint8 *addr = (uint8*)module_inst->heap_data.ptr
|
||||
+ (ptr - module_inst->heap_base_offset);
|
||||
if ((uint8*)module_inst->heap_data.ptr < addr
|
||||
&& addr < (uint8*)module_inst->heap_data_end.ptr)
|
||||
mem_allocator_free(module_inst->heap_handle.ptr, addr);
|
||||
}
|
||||
}
|
||||
|
||||
int32
|
||||
aot_module_dup_data(AOTModuleInstance *module_inst,
|
||||
const char *src, uint32 size)
|
||||
{
|
||||
int32 buffer_offset = aot_module_malloc(module_inst, size);
|
||||
|
||||
if (buffer_offset != 0) {
|
||||
char *buffer;
|
||||
buffer = aot_addr_app_to_native(module_inst, buffer_offset);
|
||||
memcpy(buffer, src, size);
|
||||
}
|
||||
return buffer_offset;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_validate_app_addr(AOTModuleInstance *module_inst,
|
||||
int32 app_offset, uint32 size)
|
||||
{
|
||||
uint8 *addr;
|
||||
|
||||
/* integer overflow check */
|
||||
if(app_offset + (int32)size < app_offset) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 <= app_offset
|
||||
&& app_offset < (int32)module_inst->memory_data_size) {
|
||||
addr = (uint8*)module_inst->memory_data.ptr + app_offset;
|
||||
if (!((uint8*)module_inst->memory_data.ptr <= addr
|
||||
&& addr + size <= (uint8*)module_inst->memory_data_end.ptr))
|
||||
goto fail;
|
||||
return true;
|
||||
}
|
||||
/* Currently heap_size is no more than 1G, and heap_base_offset is 1G,
|
||||
heap_base_offset + heap_data_size will not be larger than INT32_MAX */
|
||||
else if (module_inst->heap_base_offset < app_offset
|
||||
&& app_offset < module_inst->heap_base_offset
|
||||
+ (int32)module_inst->heap_data_size) {
|
||||
addr = (uint8*)module_inst->heap_data.ptr
|
||||
+ (app_offset - module_inst->heap_base_offset);
|
||||
if (!((uint8*)module_inst->heap_data.ptr <= addr
|
||||
&& addr + size <= (uint8*)module_inst->heap_data_end.ptr))
|
||||
goto fail;
|
||||
return true;
|
||||
}
|
||||
|
||||
fail:
|
||||
aot_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_validate_native_addr(AOTModuleInstance *module_inst,
|
||||
void *native_ptr, uint32 size)
|
||||
{
|
||||
uint8 *addr = native_ptr;
|
||||
|
||||
/* integer overflow check */
|
||||
if (addr + size < addr) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (((uint8*)module_inst->memory_data.ptr <= addr
|
||||
&& addr + size <= (uint8*)module_inst->memory_data_end.ptr)
|
||||
|| ((uint8*)module_inst->heap_data.ptr <= addr
|
||||
&& addr + size <= (uint8*)module_inst->heap_data_end.ptr)
|
||||
)
|
||||
return true;
|
||||
|
||||
fail:
|
||||
aot_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
void *
|
||||
aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset)
|
||||
{
|
||||
if (0 <= app_offset && app_offset < module_inst->heap_base_offset)
|
||||
return (uint8*)module_inst->memory_data.ptr + app_offset;
|
||||
|
||||
if (module_inst->heap_base_offset < app_offset
|
||||
&& app_offset < module_inst->heap_base_offset
|
||||
+ (int32)module_inst->heap_data_size)
|
||||
return (uint8*)module_inst->heap_data.ptr
|
||||
+ (app_offset - module_inst->heap_base_offset);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32
|
||||
aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr)
|
||||
{
|
||||
if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr
|
||||
&& (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr)
|
||||
return (int32)((uint8*)native_ptr - (uint8*)module_inst->memory_data.ptr);
|
||||
|
||||
if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr
|
||||
&& (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr)
|
||||
return (int32)(module_inst->heap_base_offset
|
||||
+ ((uint8*)native_ptr - (uint8*)module_inst->heap_data.ptr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_get_app_addr_range(AOTModuleInstance *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset)
|
||||
{
|
||||
int32 app_start_offset, app_end_offset;
|
||||
|
||||
if (0 <= app_offset && app_offset < (int32)module_inst->memory_data_size) {
|
||||
app_start_offset = 0;
|
||||
app_end_offset = (int32)module_inst->memory_data_size;
|
||||
}
|
||||
else if (module_inst->heap_base_offset < app_offset
|
||||
&& app_offset < module_inst->heap_base_offset
|
||||
+ (int32)module_inst->heap_data_size) {
|
||||
app_start_offset = module_inst->heap_base_offset;
|
||||
app_end_offset = module_inst->heap_base_offset
|
||||
+ (int32)module_inst->heap_data_size;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (p_app_start_offset)
|
||||
*p_app_start_offset = app_start_offset;
|
||||
if (p_app_end_offset)
|
||||
*p_app_end_offset = app_end_offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_get_native_addr_range(AOTModuleInstance *module_inst,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr)
|
||||
{
|
||||
uint8 *native_start_addr, *native_end_addr;
|
||||
|
||||
if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr
|
||||
&& (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr) {
|
||||
native_start_addr = (uint8*)module_inst->memory_data.ptr;
|
||||
native_end_addr = (uint8*)module_inst->memory_data_end.ptr;
|
||||
}
|
||||
else if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr
|
||||
&& (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr) {
|
||||
native_start_addr = (uint8*)module_inst->heap_data.ptr;
|
||||
native_end_addr = (uint8*)module_inst->heap_data_end.ptr;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (p_native_start_addr)
|
||||
*p_native_start_addr = native_start_addr;
|
||||
if (p_native_end_addr)
|
||||
*p_native_end_addr = native_end_addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
|
||||
{
|
||||
uint8 *mem_data_old = module_inst->memory_data.ptr, *mem_data_new;
|
||||
uint32 cur_page_count = module_inst->mem_cur_page_count;
|
||||
uint32 max_page_count = module_inst->mem_max_page_count;
|
||||
uint32 total_page_count = cur_page_count + inc_page_count;
|
||||
uint32 old_size = NumBytesPerPage * cur_page_count;
|
||||
uint64 total_size = (uint64)NumBytesPerPage * total_page_count;
|
||||
|
||||
if (inc_page_count <= 0)
|
||||
/* No need to enlarge memory */
|
||||
return true;
|
||||
|
||||
if (total_page_count < cur_page_count /* integer overflow */
|
||||
|| total_page_count > max_page_count) {
|
||||
aot_set_exception(module_inst, "fail to enlarge memory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(mem_data_new = wasm_malloc((uint32)total_size))) {
|
||||
aot_set_exception(module_inst, "fail to enlarge memory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(mem_data_new, mem_data_old, old_size);
|
||||
memset(mem_data_new + old_size, 0, (uint32)total_size - old_size);
|
||||
module_inst->mem_cur_page_count = total_page_count;
|
||||
module_inst->memory_data_size = (uint32)total_size;
|
||||
module_inst->memory_data.ptr = mem_data_new;
|
||||
module_inst->memory_data_end.ptr = mem_data_new + (uint32)total_size;
|
||||
|
||||
wasm_free(mem_data_old);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
||||
uint32 type1_idx, uint32 type2_idx)
|
||||
{
|
||||
WASMType *type1, *type2;
|
||||
AOTModule *module = (AOTModule*)module_inst->aot_module.ptr;
|
||||
|
||||
if (type1_idx >= module->func_type_count
|
||||
|| type2_idx >= module->func_type_count) {
|
||||
aot_set_exception(module_inst, "type index out of bounds");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type1_idx == type2_idx)
|
||||
return true;
|
||||
|
||||
type1 = module->func_types[type1_idx];
|
||||
type2 = module->func_types[type2_idx];
|
||||
|
||||
return wasm_type_equal(type1, type2);
|
||||
}
|
||||
434
core/iwasm/aot/aot_runtime.h
Normal file
434
core/iwasm/aot/aot_runtime.h
Normal file
@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_RUNTIME_H_
|
||||
#define _AOT_RUNTIME_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../compilation/aot.h"
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#include "../compilation/aot_llvm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AOT_MAGIC_NUMBER 0x746f6100
|
||||
#define AOT_CURRENT_VERSION 1
|
||||
|
||||
typedef enum AOTExceptionID {
|
||||
EXCE_UNREACHABLE = 0,
|
||||
EXCE_OUT_OF_MEMORY,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
EXCE_INTEGER_OVERFLOW,
|
||||
EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
EXCE_INVALID_FUNCTION_TYPE_INDEX,
|
||||
EXCE_INVALID_FUNCTION_INDEX,
|
||||
EXCE_UNDEFINED_ELEMENT,
|
||||
EXCE_UNINITIALIZED_ELEMENT,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
EXCE_NUM,
|
||||
} AOTExceptionID;
|
||||
|
||||
typedef enum AOTSectionType {
|
||||
AOT_SECTION_TYPE_TARGET_INFO = 0,
|
||||
AOT_SECTION_TYPE_INIT_DATA,
|
||||
AOT_SECTION_TYPE_TEXT,
|
||||
AOT_SECTION_TYPE_FUNCTION,
|
||||
AOT_SECTION_TYPE_EXPORT,
|
||||
AOT_SECTION_TYPE_RELOCATION,
|
||||
AOT_SECTION_TYPE_SIGANATURE
|
||||
} AOTSectionType;
|
||||
|
||||
typedef struct AOTObjectDataSection {
|
||||
char *name;
|
||||
uint8 *data;
|
||||
uint32 size;
|
||||
} AOTObjectDataSection;
|
||||
|
||||
/* Relocation info */
|
||||
typedef struct AOTRelocation {
|
||||
uint64 relocation_offset;
|
||||
uint64 relocation_addend;
|
||||
uint32 relocation_type;
|
||||
char *symbol_name;
|
||||
/* index in the symbol offset field */
|
||||
uint32 symbol_index;
|
||||
} AOTRelocation;
|
||||
|
||||
/* Relocation Group */
|
||||
typedef struct AOTRelocationGroup {
|
||||
char *section_name;
|
||||
/* index in the symbol offset field */
|
||||
uint32 name_index;
|
||||
uint32 relocation_count;
|
||||
AOTRelocation *relocations;
|
||||
} AOTRelocationGroup;
|
||||
|
||||
typedef struct AOTModule {
|
||||
uint32 module_type;
|
||||
|
||||
/* memory info */
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
uint32 mem_init_data_count;
|
||||
AOTMemInitData **mem_init_data_list;
|
||||
|
||||
/* table info */
|
||||
uint32 table_size;
|
||||
uint32 table_init_data_count;
|
||||
AOTTableInitData **table_init_data_list;
|
||||
|
||||
/* function type info */
|
||||
uint32 func_type_count;
|
||||
AOTFuncType **func_types;
|
||||
|
||||
/* import global varaible info */
|
||||
uint32 import_global_count;
|
||||
AOTImportGlobal *import_globals;
|
||||
|
||||
/* global variable info */
|
||||
uint32 global_count;
|
||||
AOTGlobal *globals;
|
||||
|
||||
/* total global variable size */
|
||||
uint32 global_data_size;
|
||||
|
||||
/* import function info */
|
||||
uint32 import_func_count;
|
||||
AOTImportFunc *import_funcs;
|
||||
|
||||
/* function info */
|
||||
uint32 func_count;
|
||||
/* point to AOTed/JITed functions */
|
||||
void **func_ptrs;
|
||||
/* function type indexes */
|
||||
uint32 *func_type_indexes;
|
||||
|
||||
/* export function info */
|
||||
uint32 export_func_count;
|
||||
AOTExportFunc *export_funcs;
|
||||
|
||||
/* start function index, -1 denotes no start function */
|
||||
uint32 start_func_index;
|
||||
/* start function, point to AOTed/JITed function */
|
||||
void *start_function;
|
||||
|
||||
/* AOTed code, NULL for JIT mode */
|
||||
void *code;
|
||||
uint32 code_size;
|
||||
|
||||
/* data sections in AOT object file, including .data, .rodata
|
||||
* and .rodata.cstN. NULL for JIT mode. */
|
||||
AOTObjectDataSection *data_sections;
|
||||
uint32 data_section_count;
|
||||
|
||||
/* constant string set */
|
||||
HashMap *const_str_set;
|
||||
|
||||
/* is jit mode or not */
|
||||
bool is_jit_mode;
|
||||
|
||||
#if WASM_ENABLE_JIT
|
||||
WASMModule *wasm_module;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTCompData *comp_data;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIArguments wasi_args;
|
||||
bool is_wasi_module;
|
||||
#endif
|
||||
} AOTModule;
|
||||
|
||||
typedef union {
|
||||
uint64 _make_it_8_bytes_;
|
||||
void *ptr;
|
||||
} AOTPointer;
|
||||
|
||||
typedef struct AOTModuleInstance {
|
||||
uint32 module_type;
|
||||
|
||||
/* memory space info */
|
||||
uint32 mem_cur_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
uint32 memory_data_size;
|
||||
AOTPointer memory_data;
|
||||
AOTPointer memory_data_end;
|
||||
|
||||
/* heap space info */
|
||||
int32 heap_base_offset;
|
||||
uint32 heap_data_size;
|
||||
AOTPointer heap_data;
|
||||
AOTPointer heap_data_end;
|
||||
AOTPointer heap_handle;
|
||||
|
||||
/* global and table info */
|
||||
uint32 global_data_size;
|
||||
uint32 table_size;
|
||||
AOTPointer global_data;
|
||||
AOTPointer table_data;
|
||||
|
||||
/* funciton pointer array */
|
||||
AOTPointer func_ptrs;
|
||||
/* function type indexes */
|
||||
AOTPointer func_type_indexes;
|
||||
|
||||
/* The exception buffer for current thread. */
|
||||
char cur_exception[128];
|
||||
/* The custom data that can be set/get by
|
||||
* wasm_runtime_set_custom_data/wasm_runtime_get_custom_data */
|
||||
AOTPointer custom_data;
|
||||
/* The AOT module */
|
||||
AOTPointer aot_module;
|
||||
/* WASI context */
|
||||
AOTPointer wasi_ctx;
|
||||
|
||||
/* others */
|
||||
int32 temp_ret;
|
||||
uint32 llvm_stack;
|
||||
int32 DYNAMICTOP_PTR_offset;
|
||||
uint32 default_wasm_stack_size;
|
||||
|
||||
/* reserved */
|
||||
uint32 reserved[16];
|
||||
|
||||
union {
|
||||
uint64 _make_it_8_byte_aligned_;
|
||||
uint8 bytes[1];
|
||||
} global_table_heap_data;
|
||||
} AOTModuleInstance;
|
||||
|
||||
typedef AOTExportFunc AOTFunctionInstance;
|
||||
|
||||
/* Target info, read from ELF header of object file */
|
||||
typedef struct AOTTargetInfo {
|
||||
/* Binary type, elf32l/elf32b/elf64l/elf64b */
|
||||
uint32 bin_type;
|
||||
/* Object file type */
|
||||
uint16 e_type;
|
||||
/* Architecture */
|
||||
uint16 e_machine;
|
||||
/* Object file version */
|
||||
uint32 e_version;
|
||||
/* Processor-specific flags */
|
||||
uint32 e_flags;
|
||||
/* Reserved */
|
||||
uint32 reserved;
|
||||
/* Arch name */
|
||||
char arch[16];
|
||||
} AOTTargetInfo;
|
||||
|
||||
/**
|
||||
* Load a AOT module from aot file buffer
|
||||
* @param buf the byte buffer which contains the AOT file data
|
||||
* @param size the size of the buffer
|
||||
* @param error_buf output of the error info
|
||||
* @param error_buf_size the size of the error string
|
||||
*
|
||||
* @return return AOT module loaded, NULL if failed
|
||||
*/
|
||||
AOTModule*
|
||||
aot_load_from_aot_file(const uint8 *buf, uint32 size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/**
|
||||
* Load a AOT module from a specified AOT section list.
|
||||
*
|
||||
* @param section_list the section list which contains each section data
|
||||
* @param error_buf output of the error info
|
||||
* @param error_buf_size the size of the error string
|
||||
*
|
||||
* @return return AOT module loaded, NULL if failed
|
||||
*/
|
||||
AOTModule*
|
||||
aot_load_from_sections(AOTSection *section_list,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
/**
|
||||
* Convert WASM module to AOT module
|
||||
*
|
||||
* @param wasm_module the WASM module to convert
|
||||
* @param error_buf output of the error info
|
||||
* @param error_buf_size the size of the error string
|
||||
*
|
||||
* @return return AOT module loaded, NULL if failed
|
||||
*/
|
||||
AOTModule*
|
||||
aot_convert_wasm_module(WASMModule *wasm_module,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Unload a AOT module.
|
||||
*
|
||||
* @param module the module to be unloaded
|
||||
*/
|
||||
void
|
||||
aot_unload(AOTModule *module);
|
||||
|
||||
/**
|
||||
* Instantiate a AOT module.
|
||||
*
|
||||
* @param module the AOT module to instantiate
|
||||
* @param heap_size the default heap size of the module instance, a heap will
|
||||
* be created besides the app memory space. Both wasm app and native
|
||||
* function can allocate memory from the heap. If heap_size is 0, the
|
||||
* default heap size will be used.
|
||||
* @param error_buf buffer to output the error info if failed
|
||||
* @param error_buf_size the size of the error buffer
|
||||
*
|
||||
* @return return the instantiated AOT module instance, NULL if failed
|
||||
*/
|
||||
AOTModuleInstance*
|
||||
aot_instantiate(AOTModule *module,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/**
|
||||
* Deinstantiate a AOT module instance, destroy the resources.
|
||||
*
|
||||
* @param module_inst the AOT module instance to destroy
|
||||
*/
|
||||
void
|
||||
aot_deinstantiate(AOTModuleInstance *module_inst);
|
||||
|
||||
/**
|
||||
* Lookup an exported function in the AOT module instance.
|
||||
*
|
||||
* @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"
|
||||
*
|
||||
* @return the function instance found
|
||||
*/
|
||||
AOTFunctionInstance*
|
||||
aot_lookup_function(const AOTModuleInstance *module_inst,
|
||||
const char *name, const char *signature);
|
||||
/**
|
||||
* Call the given AOT function of a AOT module instance with
|
||||
* arguments.
|
||||
*
|
||||
* @param exec_env the execution environment
|
||||
* @param function the function to be called
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments. If the function method has return value,
|
||||
* the first (or first two in case 64-bit return value) element of
|
||||
* argv stores the return value of the called AOT function after this
|
||||
* function returns.
|
||||
*
|
||||
* @return true if success, false otherwise and exception will be thrown,
|
||||
* the caller can call aot_get_exception to get exception info.
|
||||
*/
|
||||
bool
|
||||
aot_call_function(WASMExecEnv *exec_env,
|
||||
AOTFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
||||
AOTFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
/**
|
||||
* Set AOT module instance exception with exception string
|
||||
*
|
||||
* @param module the AOT module instance
|
||||
*
|
||||
* @param exception current exception string
|
||||
*/
|
||||
void
|
||||
aot_set_exception(AOTModuleInstance *module_inst,
|
||||
const char *exception);
|
||||
|
||||
void
|
||||
aot_set_exception_with_id(AOTModuleInstance *module_inst,
|
||||
uint32 id);
|
||||
|
||||
/**
|
||||
* Get exception info of the AOT module instance.
|
||||
*
|
||||
* @param module_inst the AOT module instance
|
||||
*
|
||||
* @return the exception string
|
||||
*/
|
||||
const char*
|
||||
aot_get_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
/**
|
||||
* Clear exception info of the AOT module instance.
|
||||
*
|
||||
* @param module_inst the AOT module instance
|
||||
*/
|
||||
void
|
||||
aot_clear_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
int32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size);
|
||||
|
||||
void
|
||||
aot_module_free(AOTModuleInstance *module_inst, int32 ptr);
|
||||
|
||||
int32
|
||||
aot_module_dup_data(AOTModuleInstance *module_inst,
|
||||
const char *src, uint32 size);
|
||||
|
||||
bool
|
||||
aot_validate_app_addr(AOTModuleInstance *module_inst,
|
||||
int32 app_offset, uint32 size);
|
||||
|
||||
|
||||
bool
|
||||
aot_validate_native_addr(AOTModuleInstance *module_inst,
|
||||
void *native_ptr, uint32 size);
|
||||
|
||||
void *
|
||||
aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset);
|
||||
|
||||
int32
|
||||
aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr);
|
||||
|
||||
bool
|
||||
aot_get_app_addr_range(AOTModuleInstance *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset);
|
||||
|
||||
bool
|
||||
aot_get_native_addr_range(AOTModuleInstance *module_inst,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr);
|
||||
|
||||
bool
|
||||
aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count);
|
||||
|
||||
/**
|
||||
* Compare whether two wasm types are equal according to the indexs
|
||||
*
|
||||
* @param module_inst the AOT module instance
|
||||
* @param type1_idx index of the first wasm type
|
||||
* @param type2_idx index of the second wasm type
|
||||
*
|
||||
* @return true if equal, false otherwise
|
||||
*/
|
||||
bool
|
||||
aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
|
||||
uint32 type1_idx, uint32 type2_idx);
|
||||
|
||||
uint32
|
||||
aot_get_plt_table_size();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_RUNTIME_H_ */
|
||||
|
||||
13
core/iwasm/aot/iwasm_aot.cmake
Normal file
13
core/iwasm/aot/iwasm_aot.cmake
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
set (IWASM_AOT_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
add_definitions (-DWASM_ENABLE_AOT=1)
|
||||
|
||||
include_directories (${IWASM_AOT_DIR})
|
||||
|
||||
file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c)
|
||||
|
||||
set (IWASM_AOT_SOURCE ${c_source_all})
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required (VERSION 3.5)
|
||||
project(hello_world)
|
||||
|
||||
add_library(print print.c)
|
||||
|
||||
add_executable(hello_world main.c)
|
||||
target_link_libraries(hello_world print)
|
||||
@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../../test-tools/toolchain/wamr_toolchain.cmake
|
||||
make
|
||||
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
void print_line(char* str);
|
||||
|
||||
int main()
|
||||
{
|
||||
print_line("Hello World!");
|
||||
print_line("Wasm Micro Runtime");
|
||||
return 0;
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
void print_line(char* str)
|
||||
{
|
||||
printf("%s\n", str);
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined, \
|
||||
-Wl,--export=main, \
|
||||
-Wl,--no-threads,--strip-all,--no-entry \
|
||||
-nostdlib -o test.wasm *.c
|
||||
#./jeffdump -o test_wasm.h -n wasm_test_file test.wasm
|
||||
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
printf("Hello world!\n");
|
||||
|
||||
buf = malloc(1024);
|
||||
if (!buf) {
|
||||
printf("malloc buf failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("buf ptr: %p\n", buf);
|
||||
|
||||
snprintf(buf, 1024, "%s", "1234\n");
|
||||
printf("buf: %s", buf);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined, \
|
||||
-Wl,--export=main, \
|
||||
-Wl,--no-threads,--strip-all,--no-entry \
|
||||
-nostdlib -o test.wasm *.c
|
||||
#./jeffdump -o ../test_wasm.h -n wasm_test_file test.wasm
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//User LED
|
||||
#define LED_PORT "GPIOA"
|
||||
#define LED 5
|
||||
|
||||
//User KEY
|
||||
#define KEY_PORT "GPIOC"
|
||||
#define KEY 13
|
||||
|
||||
/** GPIO pin to be input. */
|
||||
#define GPIO_DIR_IN (0 << 0)
|
||||
|
||||
/** GPIO pin to be output. */
|
||||
#define GPIO_DIR_OUT (1 << 0)
|
||||
|
||||
void *device_get_binding(const char *);
|
||||
int gpio_pin_configure(void *, unsigned int, int);
|
||||
int gpio_pin_read(void *, unsigned int, unsigned int *);
|
||||
int gpio_pin_write(void *, unsigned int, unsigned int);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int gpio_value;
|
||||
unsigned char flag = 0;
|
||||
struct device *dev, *key_dev;
|
||||
|
||||
dev = device_get_binding(LED_PORT);
|
||||
/* Set LED pin as output */
|
||||
gpio_pin_configure(dev, LED, GPIO_DIR_OUT);
|
||||
|
||||
key_dev = device_get_binding(KEY_PORT);
|
||||
/* Set KEY pin as input */
|
||||
gpio_pin_configure(key_dev, KEY, GPIO_DIR_IN);
|
||||
|
||||
while (1) {
|
||||
gpio_pin_read(key_dev, KEY, &gpio_value);
|
||||
if (!gpio_value) {
|
||||
gpio_pin_write(dev, LED, 1);
|
||||
if (!flag) {
|
||||
printf("object detected\n");
|
||||
flag = 1;
|
||||
}
|
||||
} else {
|
||||
gpio_pin_write(dev, LED, 0);
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -21,12 +21,12 @@ invokeNative:
|
||||
mov r4, r1 /* r4 = argv */
|
||||
mov r5, r2 /* r5 = argc */
|
||||
|
||||
cmp r5, #1 /* at least one argument required: module_inst */
|
||||
cmp r5, #1 /* at least one argument required: exec_env */
|
||||
blt return
|
||||
|
||||
mov r6, #0 /* increased stack size */
|
||||
|
||||
ldr r0, [r4], #4 /* r0 = argv[0] = module_inst */
|
||||
ldr r0, [r4], #4 /* r0 = argv[0] = exec_env */
|
||||
cmp r5, #1
|
||||
beq call_func
|
||||
|
||||
79
core/iwasm/common/arch/invokeNative_arm_vfp.s
Normal file
79
core/iwasm/common/arch/invokeNative_arm_vfp.s
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* r0 function ptr
|
||||
* r1 argv
|
||||
* r2 nstacks
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
stmfd sp!, {r4, r5, r6, r7, lr}
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
mov r4, r1 /* r4 = argv */
|
||||
mov r5, r2 /* r5 = nstacks */
|
||||
mov r6, sp
|
||||
|
||||
/* Fill all int args */
|
||||
ldr r0, [r4], #4 /* r0 = *(int*)&argv[0] = exec_env */
|
||||
ldr r1, [r4], #4 /* r1 = *(int*)&argv[1] */
|
||||
ldr r2, [r4], #4 /* r2 = *(int*)&argv[2] */
|
||||
ldr r3, [r4], #4 /* r3 = *(int*)&argv[3] */
|
||||
|
||||
/* Fill all float/double args to 16 single-precision registers, s0-s15, */
|
||||
/* which may also be accessed as 8 double-precision registers, d0-d7 (with */
|
||||
/* d0 overlapping s0, s1; d1 overlapping s2, s3; etc). */
|
||||
vldr s0, [r4, #0] /* s0 = *(float*)&argv[4] */
|
||||
vldr s1, [r4, #4]
|
||||
vldr s2, [r4, #8]
|
||||
vldr s3, [r4, #12]
|
||||
vldr s4, [r4, #16]
|
||||
vldr s5, [r4, #20]
|
||||
vldr s6, [r4, #24]
|
||||
vldr s7, [r4, #28]
|
||||
vldr s8, [r4, #32]
|
||||
vldr s9, [r4, #36]
|
||||
vldr s10, [r4, #40]
|
||||
vldr s11, [r4, #44]
|
||||
vldr s12, [r4, #48]
|
||||
vldr s13, [r4, #52]
|
||||
vldr s14, [r4, #56]
|
||||
vldr s15, [r4, #60]
|
||||
/* Directly call the fucntion if no args in stack */
|
||||
cmp r5, #0
|
||||
beq call_func
|
||||
|
||||
|
||||
/* Fill all stack args: reserve stack space and fill ony by one */
|
||||
add r4, r4, #64 /* r4 points to stack args */
|
||||
bic sp, sp, #7 /* Ensure stack is 8 byte aligned */
|
||||
mov r7, r5, lsl#2 /* r7 = nstacks * 4 */
|
||||
add r7, r7, #7 /* r7 = (r7 + 7) & ~7 */
|
||||
bic r7, r7, #7
|
||||
sub sp, sp, r7 /* reserved stack space for stack arguments */
|
||||
mov r7, sp
|
||||
|
||||
loop_stack_args: /* copy stack arguments to stack */
|
||||
cmp r5, #0
|
||||
beq call_func
|
||||
ldr lr, [r4], #4 /* Note: caller should insure int64 and */
|
||||
str lr, [r7], #4 /* double are placed in 8 bytes aligned address */
|
||||
sub r5, r5, #1
|
||||
b loop_stack_args
|
||||
|
||||
call_func:
|
||||
blx ip
|
||||
mov sp, r6 /* restore sp */
|
||||
|
||||
return:
|
||||
ldmfd sp!, {r4, r5, r6, r7, lr}
|
||||
bx lr
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef OS_MACOSX
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, @function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of OS_MACOSX */
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
/* rdi - function ptr */
|
||||
/* rsi - argv */
|
||||
/* rdx - n_stacks */
|
||||
@ -3,11 +3,12 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_runtime.h"
|
||||
#include "../wasm_runtime_common.h"
|
||||
#include "../wasm_exec_env.h"
|
||||
|
||||
void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
|
||||
{
|
||||
wasm_assert(argc >= sizeof(WASMModuleInstance *)/sizeof(uint32));
|
||||
bh_assert(argc >= sizeof(WASMExecEnv*)/sizeof(uint32));
|
||||
|
||||
switch(argc) {
|
||||
case 0:
|
||||
@ -76,7 +77,8 @@ void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
|
||||
default:
|
||||
{
|
||||
/* FIXME: If this happen, add more cases. */
|
||||
WASMModuleInstance *module_inst = *(WASMModuleInstance**)argv;
|
||||
WASMExecEnv *exec_env = *(WASMExecEnv**)argv;
|
||||
WASMModuleInstanceCommon *module_inst = exec_env->module_inst;
|
||||
wasm_runtime_set_exception(module_inst, "the argument number of native function exceeds maximum");
|
||||
return;
|
||||
}
|
||||
@ -5,14 +5,14 @@
|
||||
|
||||
.text
|
||||
.align 2
|
||||
#ifndef OS_MACOSX
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, @function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of OS_MACOSX */
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
push %ebp
|
||||
movl %esp, %ebp
|
||||
movl 16(%ebp), %ecx /* ecx = argc */
|
||||
@ -22,12 +22,12 @@ invokeNative:
|
||||
mov r4, r1 /* r4 = argv */
|
||||
mov r5, r2 /* r5 = argc */
|
||||
|
||||
cmp r5, #1 /* at least one argument required: module_inst */
|
||||
cmp r5, #1 /* at least one argument required: exec_env */
|
||||
blt return
|
||||
|
||||
mov r6, #0 /* increased stack size */
|
||||
|
||||
ldr r0, [r4] /* r0 = argv[0] = module_inst */
|
||||
ldr r0, [r4] /* r0 = argv[0] = exec_env */
|
||||
add r4, r4, #4 /* r4 += 4 */
|
||||
cmp r5, #1
|
||||
beq call_func
|
||||
93
core/iwasm/common/arch/invokeNative_thumb_vfp.s
Normal file
93
core/iwasm/common/arch/invokeNative_thumb_vfp.s
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* r0 function ptr
|
||||
* r1 argv
|
||||
* r2 nstacks
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
push {r4, r5, r6, r7}
|
||||
push {lr}
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
mov r4, r1 /* r4 = argv */
|
||||
mov r5, r2 /* r5 = nstacks */
|
||||
mov r7, sp
|
||||
|
||||
/* Fill all int args */
|
||||
ldr r0, [r4, #0] /* r0 = *(int*)&argv[0] = exec_env */
|
||||
ldr r1, [r4, #4] /* r1 = *(int*)&argv[1] */
|
||||
ldr r2, [r4, #8] /* r2 = *(int*)&argv[2] */
|
||||
ldr r3, [r4, #12] /* r3 = *(int*)&argv[3] */
|
||||
add r4, r4, #16 /* r4 points to float args */
|
||||
|
||||
/* Fill all float/double args to 16 single-precision registers, s0-s15, */
|
||||
/* which may also be accessed as 8 double-precision registers, d0-d7 (with */
|
||||
/* d0 overlapping s0, s1; d1 overlapping s2, s3; etc). */
|
||||
vldr s0, [r4, #0] /* s0 = *(float*)&argv[4] */
|
||||
vldr s1, [r4, #4]
|
||||
vldr s2, [r4, #8]
|
||||
vldr s3, [r4, #12]
|
||||
vldr s4, [r4, #16]
|
||||
vldr s5, [r4, #20]
|
||||
vldr s6, [r4, #24]
|
||||
vldr s7, [r4, #28]
|
||||
vldr s8, [r4, #32]
|
||||
vldr s9, [r4, #36]
|
||||
vldr s10, [r4, #40]
|
||||
vldr s11, [r4, #44]
|
||||
vldr s12, [r4, #48]
|
||||
vldr s13, [r4, #52]
|
||||
vldr s14, [r4, #56]
|
||||
vldr s15, [r4, #60]
|
||||
/* Directly call the fucntion if no args in stack */
|
||||
cmp r5, #0
|
||||
beq call_func
|
||||
|
||||
mov lr, r2 /* save r2 */
|
||||
|
||||
/* Fill all stack args: reserve stack space and fill ony by one */
|
||||
add r4, r4, #64 /* r4 points to stack args */
|
||||
mov r6, sp
|
||||
mov r7, #7
|
||||
bic r6, r6, r7 /* Ensure stack is 8 byte aligned */
|
||||
lsl r2, r5, #2 /* r2 = nstacks * 4 */
|
||||
add r2, r2, #7 /* r2 = (r2 + 7) & ~7 */
|
||||
bic r2, r2, r7
|
||||
sub r6, r6, r2 /* reserved stack space for stack arguments */
|
||||
mov r7, sp
|
||||
mov sp, r6
|
||||
|
||||
loop_stack_args: /* copy stack arguments to stack */
|
||||
cmp r5, #0
|
||||
beq call_func1
|
||||
ldr r2, [r4] /* Note: caller should insure int64 and */
|
||||
add r4, r4, #4 /* double are placed in 8 bytes aligned address */
|
||||
str r2, [r6]
|
||||
add r6, r6, #4
|
||||
|
||||
sub r5, r5, #1
|
||||
b loop_stack_args
|
||||
|
||||
call_func1:
|
||||
mov r2, lr /* restore r2 */
|
||||
|
||||
call_func:
|
||||
blx ip
|
||||
mov sp, r7 /* restore sp */
|
||||
|
||||
return:
|
||||
pop {r3}
|
||||
pop {r4, r5, r6, r7}
|
||||
mov lr, r3
|
||||
bx lr
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
invokeNative:
|
||||
entry a1, 256
|
||||
|
||||
blti a4, 1, return /* at least one argument required: module_inst */
|
||||
blti a4, 1, return /* at least one argument required: exec_env */
|
||||
|
||||
/* register a10 ~ a15 are used to pass first 6 arguments */
|
||||
|
||||
43
core/iwasm/common/iwasm_common.cmake
Normal file
43
core/iwasm/common/iwasm_common.cmake
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
set (IWASM_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories (${IWASM_COMMON_DIR})
|
||||
|
||||
file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
|
||||
|
||||
if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
|
||||
elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
|
||||
elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
|
||||
if (${WAMR_BUILD_TARGET} MATCHES "ARM.*_VFP")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s)
|
||||
else ()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm.s)
|
||||
endif ()
|
||||
elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
|
||||
if (${WAMR_BUILD_TARGET} MATCHES "THUMB.*_VFP")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb_vfp.s)
|
||||
else ()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
|
||||
endif ()
|
||||
elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
|
||||
elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
|
||||
elseif (${WAMR_BUILD_TARGET} STREQUAL "GENERAL")
|
||||
# Use invokeNative_general.c instead of assembly code,
|
||||
# but the maximum number of native arguments is limited to 20,
|
||||
# and there are possible issues when passing arguments to
|
||||
# native function for some cpus, e.g. int64 and double arguments
|
||||
# in arm and mips need to be 8-bytes aligned, and some arguments
|
||||
# of x86_64 are passed by registers but not stack
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
|
||||
else ()
|
||||
message (FATAL_ERROR "Build target isn't set")
|
||||
endif ()
|
||||
|
||||
set (IWASM_COMMON_SOURCE ${source_all})
|
||||
|
||||
42
core/iwasm/common/wasm_exec_env.c
Normal file
42
core/iwasm/common/wasm_exec_env.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_exec_env.h"
|
||||
#include "bh_memory.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size)
|
||||
{
|
||||
uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
|
||||
+ (uint64)stack_size;
|
||||
WASMExecEnv *exec_env;
|
||||
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(exec_env = wasm_malloc((uint32)total_size)))
|
||||
return NULL;
|
||||
|
||||
memset(exec_env, 0, (uint32)total_size);
|
||||
exec_env->module_inst = module_inst;
|
||||
exec_env->wasm_stack_size = stack_size;
|
||||
exec_env->wasm_stack.s.top_boundary =
|
||||
exec_env->wasm_stack.s.bottom + stack_size;
|
||||
exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
|
||||
return exec_env;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_destroy(WASMExecEnv *exec_env)
|
||||
{
|
||||
wasm_free(exec_env);
|
||||
}
|
||||
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->module_inst;
|
||||
}
|
||||
|
||||
151
core/iwasm/common/wasm_exec_env.h
Normal file
151
core/iwasm/common/wasm_exec_env.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_EXEC_ENV_H
|
||||
#define _WASM_EXEC_ENV_H
|
||||
|
||||
#include "bh_thread.h"
|
||||
#include "bh_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct WASMModuleInstanceCommon;
|
||||
struct WASMInterpFrame;
|
||||
|
||||
/* Execution environment */
|
||||
typedef struct WASMExecEnv {
|
||||
/* Next thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *next;
|
||||
|
||||
/* Previous thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *prev;
|
||||
|
||||
/* The WASM module instance of current thread */
|
||||
struct WASMModuleInstanceCommon *module_inst;
|
||||
|
||||
/* Current interpreter frame of current thread */
|
||||
struct WASMInterpFrame *cur_frame;
|
||||
|
||||
/* The native thread handle of current thread */
|
||||
korp_tid handle;
|
||||
|
||||
/* The boundary of native stack. When interpreter detects that native
|
||||
frame may overrun this boundary, it throws a stack overflow
|
||||
exception. */
|
||||
void *native_stack_boundary;
|
||||
|
||||
/* The WASM stack size */
|
||||
uint32 wasm_stack_size;
|
||||
|
||||
/* The WASM stack of current thread */
|
||||
union {
|
||||
uint64 __make_it_8_byte_aligned_;
|
||||
|
||||
struct {
|
||||
/* The top boundary of the stack. */
|
||||
uint8 *top_boundary;
|
||||
|
||||
/* Top cell index which is free. */
|
||||
uint8 *top;
|
||||
|
||||
/* The Java stack. */
|
||||
uint8 bottom[1];
|
||||
} s;
|
||||
} wasm_stack;
|
||||
} WASMExecEnv;
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
||||
void
|
||||
wasm_exec_env_destroy(WASMExecEnv *exec_env);
|
||||
|
||||
/**
|
||||
* Allocate a WASM frame from the WASM stack.
|
||||
*
|
||||
* @param exec_env the current execution environment
|
||||
* @param size size of the WASM frame, it must be a multiple of 4
|
||||
*
|
||||
* @return the WASM frame if there is enough space in the stack area
|
||||
* with a protection area, NULL otherwise
|
||||
*/
|
||||
static inline void *
|
||||
wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
|
||||
{
|
||||
uint8 *addr = exec_env->wasm_stack.s.top;
|
||||
|
||||
bh_assert(!(size & 3));
|
||||
|
||||
/* The outs area size cannot be larger than the frame size, so
|
||||
multiplying by 2 is enough. */
|
||||
if (addr + size * 2 > exec_env->wasm_stack.s.top_boundary) {
|
||||
/* WASM stack overflow. */
|
||||
/* When throwing SOE, the preserved space must be enough. */
|
||||
/* bh_assert(!exec_env->throwing_soe);*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
exec_env->wasm_stack.s.top += size;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top)
|
||||
{
|
||||
bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.s.bottom);
|
||||
exec_env->wasm_stack.s.top = (uint8 *)prev_top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current WASM stack top pointer.
|
||||
*
|
||||
* @param exec_env the current execution environment
|
||||
*
|
||||
* @return the current WASM stack top pointer
|
||||
*/
|
||||
static inline void*
|
||||
wasm_exec_env_wasm_stack_top(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->wasm_stack.s.top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current frame pointer.
|
||||
*
|
||||
* @param exec_env the current execution environment
|
||||
* @param frame the WASM frame to be set for the current exec env
|
||||
*/
|
||||
static inline void
|
||||
wasm_exec_env_set_cur_frame(WASMExecEnv *exec_env,
|
||||
struct WASMInterpFrame *frame)
|
||||
{
|
||||
exec_env->cur_frame = frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current frame pointer.
|
||||
*
|
||||
* @param exec_env the current execution environment
|
||||
*
|
||||
* @return the current frame pointer
|
||||
*/
|
||||
static inline struct WASMInterpFrame*
|
||||
wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->cur_frame;
|
||||
}
|
||||
|
||||
struct WASMModuleInstanceCommon *
|
||||
wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_EXEC_ENV_H */
|
||||
@ -3,11 +3,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "wasm_native.h"
|
||||
|
||||
|
||||
static bool sort_flag = false;
|
||||
|
||||
typedef struct NativeSymbol {
|
||||
const char *symbol;
|
||||
void *func_ptr;
|
||||
@ -53,42 +51,73 @@ lookup_symbol(NativeSymbol *ptr, int len, const char *symbol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
int
|
||||
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
|
||||
|
||||
int
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
||||
|
||||
static NativeSymbol *base_native_symbol_defs;
|
||||
static NativeSymbol *ext_native_symbol_defs;
|
||||
static int base_native_symbol_len;
|
||||
static int ext_native_symbol_len;
|
||||
|
||||
void *
|
||||
wasm_dlsym(void *handle, const char *symbol)
|
||||
wasm_native_lookup_base_lib_func(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (!sort_flag) {
|
||||
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);
|
||||
ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs);
|
||||
|
||||
if (base_native_symbol_len > 0)
|
||||
sort_symbol_ptr(base_native_symbol_defs, base_native_symbol_len);
|
||||
|
||||
is_base_lib_sorted = true;
|
||||
}
|
||||
|
||||
if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len,
|
||||
func_name))
|
||||
|| (func_name[0] == '_'
|
||||
&& (ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len,
|
||||
func_name + 1))))
|
||||
return ret;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_BASE_LIB */
|
||||
|
||||
static bool is_ext_lib_sorted = false;
|
||||
static NativeSymbol *ext_native_symbol_defs;
|
||||
static int ext_native_symbol_len;
|
||||
|
||||
int
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
||||
|
||||
void *
|
||||
wasm_native_lookup_extension_lib_func(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (strcmp(module_name, "env"))
|
||||
return NULL;
|
||||
|
||||
if (!is_ext_lib_sorted) {
|
||||
ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs);
|
||||
|
||||
if (ext_native_symbol_len > 0)
|
||||
sort_symbol_ptr(ext_native_symbol_defs, ext_native_symbol_len);
|
||||
|
||||
sort_flag = true;
|
||||
is_ext_lib_sorted = true;
|
||||
}
|
||||
|
||||
if (!symbol)
|
||||
return NULL;
|
||||
|
||||
if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len,
|
||||
symbol))
|
||||
|| (ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len,
|
||||
symbol)))
|
||||
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;
|
||||
92
core/iwasm/common/wasm_native.h
Normal file
92
core/iwasm/common/wasm_native.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_NATIVE_H
|
||||
#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);
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
/**
|
||||
* Lookup global variable of a given import global
|
||||
* in 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
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @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_wasi_func(const char *module_name,
|
||||
const char *func_name);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_NATIVE_H */
|
||||
|
||||
1820
core/iwasm/common/wasm_runtime_common.c
Normal file
1820
core/iwasm/common/wasm_runtime_common.c
Normal file
File diff suppressed because it is too large
Load Diff
296
core/iwasm/common/wasm_runtime_common.h
Normal file
296
core/iwasm/common/wasm_runtime_common.h
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_COMMON_H
|
||||
#define _WASM_COMMON_H
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "bh_common.h"
|
||||
#include "bh_thread.h"
|
||||
#include "wasm_exec_env.h"
|
||||
#include "../interpreter/wasm.h"
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#include "wasmtime_ssp.h"
|
||||
#include "posix.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define wasm_malloc bh_malloc
|
||||
#define wasm_free bh_free
|
||||
|
||||
/* Package Type */
|
||||
typedef enum {
|
||||
Wasm_Module_Bytecode = 0,
|
||||
Wasm_Module_AoT,
|
||||
Package_Type_Unknown = 0xFFFF
|
||||
} PackageType;
|
||||
|
||||
typedef struct WASMModuleCommon {
|
||||
/* Module type, for module loaded from WASM bytecode binary,
|
||||
this field is Wasm_Module_Bytecode, and this structure should
|
||||
be treated as WASMModule structure;
|
||||
for module loaded from AOT binary, this field is
|
||||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModule structure. */
|
||||
uint32 module_type;
|
||||
uint8 module_data[1];
|
||||
} WASMModuleCommon;
|
||||
|
||||
typedef struct WASMModuleInstanceCommon {
|
||||
/* Module instance type, for module instance loaded from WASM
|
||||
bytecode binary, this field is Wasm_Module_Bytecode, and this
|
||||
structure should be treated as WASMModuleInstance structure;
|
||||
for module instance loaded from AOT binary, this field is
|
||||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModuleInstance structure. */
|
||||
uint32 module_type;
|
||||
uint8 module_inst_data[1];
|
||||
} WASMModuleInstanceCommon;
|
||||
|
||||
typedef void WASMFunctionInstanceCommon;
|
||||
|
||||
/* WASM section */
|
||||
typedef struct WASMSection {
|
||||
struct WASMSection *next;
|
||||
/* section type */
|
||||
int section_type;
|
||||
/* section body, not include type and size */
|
||||
const uint8 *section_body;
|
||||
/* section body size */
|
||||
uint32 section_body_size;
|
||||
} WASMSection, AOTSection;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
typedef struct WASIContext {
|
||||
struct fd_table *curfds;
|
||||
struct fd_prestats *prestats;
|
||||
struct argv_environ_values *argv_environ;
|
||||
} WASIContext;
|
||||
#endif
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_init();
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_destroy();
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
PackageType
|
||||
get_package_type(const uint8 *buf, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleCommon *
|
||||
wasm_runtime_load(const uint8 *buf, uint32 size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleCommon *
|
||||
wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_unload(WASMModuleCommon *module);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_instantiate(WASMModuleCommon *module,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMFunctionInstanceCommon *
|
||||
wasm_runtime_lookup_function(const WASMModuleInstanceCommon *module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMExecEnv *
|
||||
wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
|
||||
int argc, char *argv[]);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
const char *name, int argc, char *argv[]);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_set_exception(WASMModuleInstanceCommon *module,
|
||||
const char *exception);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
const char *
|
||||
wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
|
||||
void *custom_data);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, int32 ptr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
|
||||
const char *src, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_str_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
void
|
||||
wasm_runtime_set_temp_ret(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 temp_ret);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_llvm_stack(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
void
|
||||
wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 llvm_stack);
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_set_wasi_args(WASMModuleCommon *module,
|
||||
const char *dir_list[], uint32 dir_count,
|
||||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
const char *env_list[], uint32 env_count,
|
||||
const char *argv[], uint32 argc);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMFunctionInstanceCommon *
|
||||
wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
bool
|
||||
wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
||||
const char *dir_list[], uint32 dir_count,
|
||||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
const char *env[], uint32 env_count,
|
||||
const char *argv[], uint32 argc,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
void
|
||||
wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
void
|
||||
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
|
||||
WASIContext *wasi_ctx);
|
||||
|
||||
WASIContext *
|
||||
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
/**
|
||||
* Enlarge wasm memory data space.
|
||||
*
|
||||
* @param module the wasm module instance
|
||||
* @param inc_page_count denote the page number to increase
|
||||
* @return return true if enlarge successfully, false otherwise
|
||||
*/
|
||||
bool
|
||||
wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
|
||||
WASMExecEnv *exec_env,
|
||||
uint32 *argv, uint32 argc, uint32 *ret);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_COMMON_H */
|
||||
|
||||
510
core/iwasm/compilation/aot.c
Normal file
510
core/iwasm/compilation/aot.c
Normal file
@ -0,0 +1,510 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot.h"
|
||||
#include "bh_memory.h"
|
||||
|
||||
|
||||
static char aot_error[128];
|
||||
|
||||
char*
|
||||
aot_get_last_error()
|
||||
{
|
||||
return aot_error[0] == '\0' ? "" : aot_error;
|
||||
}
|
||||
|
||||
void
|
||||
aot_set_last_error(const char *error)
|
||||
{
|
||||
if (error)
|
||||
snprintf(aot_error, sizeof(aot_error), "Error: %s", error);
|
||||
else
|
||||
aot_error[0] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_free(data_list[i]);
|
||||
wasm_free(data_list);
|
||||
}
|
||||
|
||||
static AOTMemInitData **
|
||||
aot_create_mem_init_data_list(const WASMModule *module)
|
||||
{
|
||||
AOTMemInitData **data_list;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(data_list = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(data_list, 0, size);
|
||||
|
||||
/* Create each memory data segment */
|
||||
for (i = 0; i < module->data_seg_count; i++) {
|
||||
size = offsetof(AOTMemInitData, bytes) +
|
||||
(uint64)module->data_segments[i]->data_length;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(data_list[i] = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data_list[i]->offset = module->data_segments[i]->base_offset;
|
||||
data_list[i]->byte_count = module->data_segments[i]->data_length;
|
||||
memcpy(data_list[i]->bytes, module->data_segments[i]->data,
|
||||
module->data_segments[i]->data_length);
|
||||
}
|
||||
|
||||
return data_list;
|
||||
|
||||
fail:
|
||||
aot_destroy_mem_init_data_list(data_list, module->data_seg_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_free(data_list[i]);
|
||||
wasm_free(data_list);
|
||||
}
|
||||
|
||||
static AOTTableInitData **
|
||||
aot_create_table_init_data_list(const WASMModule *module)
|
||||
{
|
||||
AOTTableInitData **data_list;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(data_list = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(data_list, 0, size);
|
||||
|
||||
/* Create each table data segment */
|
||||
for (i = 0; i < module->table_seg_count; i++) {
|
||||
size = offsetof(AOTTableInitData, func_indexes) +
|
||||
sizeof(uint32) * (uint64)module->table_segments[i].function_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(data_list[i] = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data_list[i]->offset = module->table_segments[i].base_offset;
|
||||
data_list[i]->func_index_count = module->table_segments[i].function_count;
|
||||
memcpy(data_list[i]->func_indexes, module->table_segments[i].func_indexes,
|
||||
sizeof(uint32) * module->table_segments[i].function_count);
|
||||
}
|
||||
|
||||
return data_list;
|
||||
|
||||
fail:
|
||||
aot_destroy_table_init_data_list(data_list, module->table_seg_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static AOTImportGlobal *
|
||||
aot_create_import_globals(const WASMModule *module,
|
||||
uint32 *p_import_global_data_size)
|
||||
{
|
||||
AOTImportGlobal *import_globals;
|
||||
uint64 size;
|
||||
uint32 i, data_offset = 0;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(import_globals = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(import_globals, 0, (uint32)size);
|
||||
|
||||
/* Create each import global */
|
||||
for (i = 0; i < module->import_global_count; i++) {
|
||||
WASMGlobalImport *import_global = &module->import_globals[i].u.global;
|
||||
import_globals[i].module_name = import_global->module_name;
|
||||
import_globals[i].global_name = import_global->field_name;
|
||||
import_globals[i].type = import_global->type;
|
||||
import_globals[i].is_mutable = import_global->is_mutable;
|
||||
import_globals[i].global_data_linked = import_global->global_data_linked;
|
||||
import_globals[i].size = wasm_value_type_size(import_global->type);
|
||||
/* Calculate data offset */
|
||||
import_globals[i].data_offset = data_offset;
|
||||
data_offset += wasm_value_type_size(import_global->type);
|
||||
}
|
||||
|
||||
*p_import_global_data_size = data_offset;
|
||||
return import_globals;
|
||||
}
|
||||
|
||||
static AOTGlobal *
|
||||
aot_create_globals(const WASMModule *module,
|
||||
uint32 global_data_start_offset,
|
||||
uint32 *p_global_data_size)
|
||||
{
|
||||
AOTGlobal *globals;
|
||||
uint64 size;
|
||||
uint32 i, data_offset = global_data_start_offset;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTGlobal) * (uint64)module->global_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(globals = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(globals, 0, (uint32)size);
|
||||
|
||||
/* Create each global */
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
WASMGlobal *global = &module->globals[i];
|
||||
globals[i].type = global->type;
|
||||
globals[i].is_mutable = global->is_mutable;
|
||||
globals[i].size = wasm_value_type_size(global->type);
|
||||
memcpy(&globals[i].init_expr, &global->init_expr,
|
||||
sizeof(global->init_expr));
|
||||
/* Calculate data offset */
|
||||
globals[i].data_offset = data_offset;
|
||||
data_offset += wasm_value_type_size(global->type);
|
||||
}
|
||||
|
||||
*p_global_data_size = data_offset - global_data_start_offset;
|
||||
return globals;
|
||||
}
|
||||
|
||||
static void
|
||||
aot_destroy_func_types(AOTFuncType **func_types, uint32 count)
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (func_types[i])
|
||||
wasm_free(func_types[i]);
|
||||
wasm_free(func_types);
|
||||
}
|
||||
|
||||
static AOTFuncType **
|
||||
aot_create_func_types(const WASMModule *module)
|
||||
{
|
||||
AOTFuncType **func_types;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTFuncType*) * (uint64)module->type_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(func_types = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(func_types, 0, size);
|
||||
|
||||
/* Create each function type */
|
||||
for (i = 0; i < module->type_count; i++) {
|
||||
size = offsetof(AOTFuncType, types) +
|
||||
(uint64)module->types[i]->param_count +
|
||||
(uint64)module->types[i]->result_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(func_types[i] = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
memcpy(func_types[i], module->types[i], size);
|
||||
}
|
||||
|
||||
return func_types;
|
||||
|
||||
fail:
|
||||
aot_destroy_func_types(func_types, module->type_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static AOTImportFunc *
|
||||
aot_create_import_funcs(const WASMModule *module)
|
||||
{
|
||||
AOTImportFunc *import_funcs;
|
||||
uint64 size;
|
||||
uint32 i, j;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTImportFunc) * (uint64)module->import_function_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(import_funcs = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create each import function */
|
||||
for (i = 0; i < module->import_function_count; i++) {
|
||||
WASMFunctionImport *import_func = &module->import_functions[i].u.function;
|
||||
import_funcs[i].module_name = import_func->module_name;
|
||||
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;
|
||||
/* Resolve function type index */
|
||||
for (j = 0; j < module->type_count; j++)
|
||||
if (import_func->func_type == module->types[j]) {
|
||||
import_funcs[i].func_type_index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return import_funcs;
|
||||
}
|
||||
|
||||
static void
|
||||
aot_destroy_funcs(AOTFunc **funcs, uint32 count)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (funcs[i])
|
||||
wasm_free(funcs[i]);
|
||||
wasm_free(funcs);
|
||||
}
|
||||
|
||||
static AOTFunc **
|
||||
aot_create_funcs(const WASMModule *module)
|
||||
{
|
||||
AOTFunc **funcs;
|
||||
uint64 size;
|
||||
uint32 i, j;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTFunc*) * (uint64)module->function_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(funcs = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(funcs, 0, size);
|
||||
|
||||
/* Create each function */
|
||||
for (i = 0; i < module->function_count; i++) {
|
||||
WASMFunction *func = module->functions[i];
|
||||
size = sizeof (AOTFunc);
|
||||
if (!(funcs[i] = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
funcs[i]->func_type = func->func_type;
|
||||
|
||||
/* Resolve function type index */
|
||||
for (j = 0; j < module->type_count; j++)
|
||||
if (func->func_type == module->types[j]) {
|
||||
funcs[i]->func_type_index = j;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Resolve local variable info and code info */
|
||||
funcs[i]->local_count = func->local_count;
|
||||
funcs[i]->local_types = func->local_types;
|
||||
funcs[i]->code = func->code;
|
||||
funcs[i]->code_size = func->code_size;
|
||||
}
|
||||
|
||||
return funcs;
|
||||
|
||||
fail:
|
||||
aot_destroy_funcs(funcs, module->function_count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static AOTExportFunc *
|
||||
aot_create_export_funcs(const WASMModule *module,
|
||||
uint32 export_func_count)
|
||||
{
|
||||
AOTExportFunc *export_funcs;
|
||||
uint64 size;
|
||||
uint32 i, j = 0;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTExportFunc) * (uint64)export_func_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(export_funcs = wasm_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create each export function */
|
||||
for (i = 0; i < module->export_count; i++) {
|
||||
if (module->exports[i].kind == EXPORT_KIND_FUNC) {
|
||||
export_funcs[j].func_name = module->exports[i].name;
|
||||
export_funcs[j].func_index = module->exports[i].index;
|
||||
export_funcs[j].func_type =
|
||||
module->functions[module->exports[i].index
|
||||
- module->import_function_count]->func_type;
|
||||
/* Function pointer to be linked in JIT mode */
|
||||
export_funcs[j].func_ptr = NULL;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return export_funcs;
|
||||
}
|
||||
|
||||
AOTCompData*
|
||||
aot_create_comp_data(WASMModule *module)
|
||||
{
|
||||
AOTCompData *comp_data;
|
||||
uint32 import_global_data_size = 0, global_data_size = 0, i;
|
||||
|
||||
/* Allocate memory */
|
||||
if (!(comp_data = wasm_malloc(sizeof(AOTCompData)))) {
|
||||
aot_set_last_error("create compile data failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(comp_data, 0, sizeof(AOTCompData));
|
||||
|
||||
/* Set memory page count */
|
||||
if (module->import_memory_count) {
|
||||
comp_data->mem_init_page_count =
|
||||
module->import_memories[0].u.memory.init_page_count;
|
||||
comp_data->mem_max_page_count =
|
||||
module->import_memories[0].u.memory.max_page_count;
|
||||
}
|
||||
else if (module->memory_count) {
|
||||
comp_data->mem_init_page_count =
|
||||
module->memories[0].init_page_count;
|
||||
comp_data->mem_max_page_count =
|
||||
module->memories[0].max_page_count;
|
||||
}
|
||||
|
||||
/* Create memory data segments */
|
||||
comp_data->mem_init_data_count = module->data_seg_count;
|
||||
if (comp_data->mem_init_data_count > 0
|
||||
&& !(comp_data->mem_init_data_list =
|
||||
aot_create_mem_init_data_list(module)))
|
||||
goto fail;
|
||||
|
||||
/* Set table size */
|
||||
if (module->import_table_count)
|
||||
comp_data->table_size = module->import_tables[0].u.table.init_size;
|
||||
else if (module->table_count)
|
||||
comp_data->table_size = module->tables[0].init_size;
|
||||
|
||||
/* Create table data segments */
|
||||
comp_data->table_init_data_count = module->table_seg_count;
|
||||
if (comp_data->table_init_data_count > 0
|
||||
&& !(comp_data->table_init_data_list =
|
||||
aot_create_table_init_data_list(module)))
|
||||
goto fail;
|
||||
|
||||
/* Create import globals */
|
||||
comp_data->import_global_count = module->import_global_count;
|
||||
if (comp_data->import_global_count > 0
|
||||
&& !(comp_data->import_globals =
|
||||
aot_create_import_globals(module, &import_global_data_size)))
|
||||
goto fail;
|
||||
|
||||
/* Create globals */
|
||||
comp_data->global_count = module->global_count;
|
||||
if (comp_data->global_count
|
||||
&& !(comp_data->globals = aot_create_globals
|
||||
(module, import_global_data_size, &global_data_size)))
|
||||
goto fail;
|
||||
|
||||
comp_data->global_data_size = import_global_data_size +
|
||||
global_data_size;
|
||||
|
||||
/* Create function types */
|
||||
comp_data->func_type_count = module->type_count;
|
||||
if (comp_data->func_type_count
|
||||
&& !(comp_data->func_types = aot_create_func_types(module)))
|
||||
goto fail;
|
||||
|
||||
/* Create import functions */
|
||||
comp_data->import_func_count = module->import_function_count;
|
||||
if (comp_data->import_func_count
|
||||
&& !(comp_data->import_funcs = aot_create_import_funcs(module)))
|
||||
goto fail;
|
||||
|
||||
/* Create functions */
|
||||
comp_data->func_count = module->function_count;
|
||||
if (comp_data->func_count
|
||||
&& !(comp_data->funcs = aot_create_funcs(module)))
|
||||
goto fail;
|
||||
|
||||
/* Create export functions */
|
||||
for (i = 0; i < module->export_count; i++)
|
||||
if (module->exports[i].kind == EXPORT_KIND_FUNC)
|
||||
comp_data->export_func_count++;
|
||||
|
||||
if (comp_data->export_func_count
|
||||
&& !(comp_data->export_funcs = aot_create_export_funcs
|
||||
(module, comp_data->export_func_count)))
|
||||
goto fail;
|
||||
|
||||
comp_data->start_func_index = module->start_function;
|
||||
comp_data->wasm_module = module;
|
||||
|
||||
return comp_data;
|
||||
|
||||
fail:
|
||||
|
||||
aot_destroy_comp_data(comp_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
aot_destroy_comp_data(AOTCompData *comp_data)
|
||||
{
|
||||
if (!comp_data)
|
||||
return;
|
||||
|
||||
if (comp_data->mem_init_data_list)
|
||||
aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
|
||||
comp_data->mem_init_data_count);
|
||||
|
||||
if (comp_data->table_init_data_list)
|
||||
aot_destroy_table_init_data_list(comp_data->table_init_data_list,
|
||||
comp_data->table_init_data_count);
|
||||
|
||||
if (comp_data->import_globals)
|
||||
wasm_free(comp_data->import_globals);
|
||||
|
||||
if (comp_data->globals)
|
||||
wasm_free(comp_data->globals);
|
||||
|
||||
if (comp_data->func_types)
|
||||
aot_destroy_func_types(comp_data->func_types,
|
||||
comp_data->func_type_count);
|
||||
|
||||
if (comp_data->import_funcs)
|
||||
wasm_free(comp_data->import_funcs);
|
||||
|
||||
if (comp_data->funcs)
|
||||
aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
|
||||
|
||||
if (comp_data->export_funcs)
|
||||
wasm_free(comp_data->export_funcs);
|
||||
|
||||
wasm_free(comp_data);
|
||||
}
|
||||
|
||||
165
core/iwasm/compilation/aot.h
Normal file
165
core/iwasm/compilation/aot.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_H_
|
||||
#define _AOT_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "bh_assert.h"
|
||||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../interpreter/wasm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AOT_FUNC_PREFIX "aot_func#"
|
||||
|
||||
typedef InitializerExpression AOTInitExpr;
|
||||
typedef WASMType AOTFuncType;
|
||||
|
||||
/**
|
||||
* A segment of memory init data
|
||||
*/
|
||||
typedef struct AOTMemInitData {
|
||||
/* Start address of init data */
|
||||
AOTInitExpr offset;
|
||||
/* Byte count */
|
||||
uint32 byte_count;
|
||||
/* Byte array */
|
||||
uint8 bytes[1];
|
||||
} AOTMemInitData;
|
||||
|
||||
/**
|
||||
* A segment of table init data
|
||||
*/
|
||||
typedef struct AOTTableInitData {
|
||||
/* Start address of init data */
|
||||
AOTInitExpr offset;
|
||||
/* Function index count */
|
||||
uint32 func_index_count;
|
||||
/* Function index array */
|
||||
uint32 func_indexes[1];
|
||||
} AOTTableInitData;
|
||||
|
||||
/**
|
||||
* Import global variable
|
||||
*/
|
||||
typedef struct AOTImportGlobal {
|
||||
char *module_name;
|
||||
char *global_name;
|
||||
/* VALUE_TYPE_I32/I64/F32/F64 */
|
||||
uint8 type;
|
||||
bool is_mutable;
|
||||
uint32 size;
|
||||
/* The data offset of current global in global data */
|
||||
uint32 data_offset;
|
||||
/* global data after linked */
|
||||
WASMValue global_data_linked;
|
||||
} AOTImportGlobal;
|
||||
|
||||
/**
|
||||
* Global variable
|
||||
*/
|
||||
typedef struct AOTGlobal {
|
||||
/* VALUE_TYPE_I32/I64/F32/F64 */
|
||||
uint8 type;
|
||||
bool is_mutable;
|
||||
uint32 size;
|
||||
/* The data offset of current global in global data */
|
||||
uint32 data_offset;
|
||||
AOTInitExpr init_expr;
|
||||
} AOTGlobal;
|
||||
|
||||
/**
|
||||
* Import function
|
||||
*/
|
||||
typedef struct AOTImportFunc {
|
||||
char *module_name;
|
||||
char *func_name;
|
||||
AOTFuncType *func_type;
|
||||
uint32 func_type_index;
|
||||
/* function pointer after linked */
|
||||
void *func_ptr_linked;
|
||||
} AOTImportFunc;
|
||||
|
||||
/**
|
||||
* Function
|
||||
*/
|
||||
typedef struct AOTFunc {
|
||||
AOTFuncType *func_type;
|
||||
uint32 func_type_index;
|
||||
uint32 local_count;
|
||||
uint8 *local_types;
|
||||
uint32 code_size;
|
||||
uint8 *code;
|
||||
} AOTFunc;
|
||||
|
||||
/**
|
||||
* Export function
|
||||
*/
|
||||
typedef struct AOTExportFunc {
|
||||
char *func_name;
|
||||
AOTFuncType *func_type;
|
||||
/* function pointer linked */
|
||||
void *func_ptr;
|
||||
uint32 func_index;
|
||||
} AOTExportFunc;
|
||||
|
||||
typedef struct AOTCompData {
|
||||
/* Memory and memory init data info */
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
uint32 mem_init_data_count;
|
||||
AOTMemInitData **mem_init_data_list;
|
||||
|
||||
/* Table and table init data info */
|
||||
uint32 table_size;
|
||||
AOTTableInitData **table_init_data_list;
|
||||
uint32 table_init_data_count;
|
||||
|
||||
AOTImportGlobal *import_globals;
|
||||
uint32 import_global_count;
|
||||
|
||||
AOTGlobal *globals;
|
||||
uint32 global_count;
|
||||
|
||||
AOTFuncType **func_types;
|
||||
uint32 func_type_count;
|
||||
|
||||
AOTImportFunc *import_funcs;
|
||||
uint32 import_func_count;
|
||||
|
||||
AOTFunc **funcs;
|
||||
uint32 func_count;
|
||||
|
||||
AOTExportFunc *export_funcs;
|
||||
uint32 export_func_count;
|
||||
|
||||
uint32 start_func_index;
|
||||
uint32 addr_data_size;
|
||||
uint32 global_data_size;
|
||||
|
||||
WASMModule *wasm_module;
|
||||
} AOTCompData;
|
||||
|
||||
AOTCompData*
|
||||
aot_create_comp_data(WASMModule *module);
|
||||
|
||||
void
|
||||
aot_destroy_comp_data(AOTCompData *comp_data);
|
||||
|
||||
char*
|
||||
aot_get_last_error();
|
||||
|
||||
void
|
||||
aot_set_last_error(const char *error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_H_ */
|
||||
|
||||
804
core/iwasm/compilation/aot_compiler.c
Normal file
804
core/iwasm/compilation/aot_compiler.c
Normal file
@ -0,0 +1,804 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_compiler.h"
|
||||
#include "aot_emit_compare.h"
|
||||
#include "aot_emit_conversion.h"
|
||||
#include "aot_emit_memory.h"
|
||||
#include "aot_emit_variable.h"
|
||||
#include "aot_emit_const.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "aot_emit_numberic.h"
|
||||
#include "aot_emit_control.h"
|
||||
#include "aot_emit_function.h"
|
||||
#include "aot_emit_parametric.h"
|
||||
#include "bh_memory.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "../interpreter/wasm_opcode.h"
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define CHECK_BUF(buf, buf_end, length) do { \
|
||||
if (buf + length > buf_end) { \
|
||||
aot_set_last_error("read leb failed: unexpected end."); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
read_leb(const uint8 *buf, const uint8 *buf_end,
|
||||
uint32 *p_offset, uint32 maxbits,
|
||||
bool sign, uint64 *p_result)
|
||||
{
|
||||
uint64 result = 0;
|
||||
uint32 shift = 0;
|
||||
uint32 bcnt = 0;
|
||||
uint64 byte;
|
||||
|
||||
while (true) {
|
||||
CHECK_BUF(buf, buf_end, 1);
|
||||
byte = buf[*p_offset];
|
||||
*p_offset += 1;
|
||||
result |= ((byte & 0x7f) << shift);
|
||||
shift += 7;
|
||||
if ((byte & 0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
bcnt += 1;
|
||||
}
|
||||
if (bcnt > (((maxbits + 8) >> 3) - (maxbits + 8))) {
|
||||
aot_set_last_error("read leb failed: unsigned leb overflow.");
|
||||
return false;
|
||||
}
|
||||
if (sign && (shift < maxbits) && (byte & 0x40)) {
|
||||
/* Sign extend */
|
||||
result |= (uint64)(- (((uint64)1) << shift));
|
||||
}
|
||||
*p_result = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define read_leb_uint32(p, p_end, res) do { \
|
||||
uint32 off = 0; \
|
||||
uint64 res64; \
|
||||
if (!read_leb(p, p_end, &off, 32, false, &res64)) \
|
||||
return false; \
|
||||
p += off; \
|
||||
res = (uint32)res64; \
|
||||
} while (0)
|
||||
|
||||
#define read_leb_int32(p, p_end, res) do { \
|
||||
uint32 off = 0; \
|
||||
uint64 res64; \
|
||||
if (!read_leb(p, p_end, &off, 32, true, &res64)) \
|
||||
return false; \
|
||||
p += off; \
|
||||
res = (int32)res64; \
|
||||
} while (0)
|
||||
|
||||
#define read_leb_int64(p, p_end, res) do { \
|
||||
uint32 off = 0; \
|
||||
uint64 res64; \
|
||||
if (!read_leb(p, p_end, &off, 64, true, &res64)) \
|
||||
return false; \
|
||||
p += off; \
|
||||
res = (int64)res64; \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
||||
{
|
||||
AOTFuncContext *func_ctx = comp_ctx->func_ctxes[func_index];
|
||||
uint8 *frame_ip = func_ctx->aot_func->code, opcode, *p_f32, *p_f64;
|
||||
uint8 *frame_ip_end = frame_ip + func_ctx->aot_func->code_size;
|
||||
uint32 block_ret_type, br_depth, *br_depths, br_count;
|
||||
uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i;
|
||||
uint32 bytes = 4, align, offset;
|
||||
bool sign = true;
|
||||
int32 i32_const;
|
||||
int64 i64_const;
|
||||
float32 f32_const;
|
||||
float64 f64_const;
|
||||
|
||||
/* Start to translate the opcodes */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder,
|
||||
func_ctx->block_stack.block_list_head
|
||||
->llvm_entry_block);
|
||||
while (frame_ip < frame_ip_end) {
|
||||
opcode = *frame_ip++;
|
||||
switch (opcode) {
|
||||
case WASM_OP_UNREACHABLE:
|
||||
if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_NOP:
|
||||
break;
|
||||
|
||||
case WASM_OP_BLOCK:
|
||||
case WASM_OP_LOOP:
|
||||
case WASM_OP_IF:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, block_ret_type);
|
||||
if (!aot_compile_op_block(comp_ctx, func_ctx,
|
||||
&frame_ip, frame_ip_end,
|
||||
(uint32)(BLOCK_TYPE_BLOCK + opcode - WASM_OP_BLOCK),
|
||||
block_ret_type))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_ELSE:
|
||||
if (!aot_compile_op_else(comp_ctx, func_ctx, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_END:
|
||||
if (!aot_compile_op_end(comp_ctx, func_ctx, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_BR:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, br_depth);
|
||||
if (!aot_compile_op_br(comp_ctx, func_ctx, br_depth, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_BR_IF:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, br_depth);
|
||||
if (!aot_compile_op_br_if(comp_ctx, func_ctx, br_depth, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_BR_TABLE:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, br_count);
|
||||
if (!(br_depths = wasm_malloc((uint32)sizeof(uint32) * (br_count + 1)))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i <= br_count; i++)
|
||||
read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]);
|
||||
|
||||
if (!aot_compile_op_br_table(comp_ctx, func_ctx,
|
||||
br_depths, br_count, &frame_ip)) {
|
||||
wasm_free(br_depths);
|
||||
return false;
|
||||
}
|
||||
|
||||
wasm_free(br_depths);
|
||||
break;
|
||||
|
||||
case WASM_OP_RETURN:
|
||||
if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_CALL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, func_idx);
|
||||
if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, &frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_CALL_INDIRECT:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_idx);
|
||||
frame_ip++; /* skip 0x00 */
|
||||
if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_DROP_32:
|
||||
if (!aot_compile_op_drop(comp_ctx, func_ctx, true))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_DROP_64:
|
||||
if (!aot_compile_op_drop(comp_ctx, func_ctx, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_SELECT_32:
|
||||
if (!aot_compile_op_select(comp_ctx, func_ctx, true))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_SELECT_64:
|
||||
if (!aot_compile_op_select(comp_ctx, func_ctx, false))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_GET_LOCAL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, local_idx);
|
||||
if (!aot_compile_op_get_local(comp_ctx, func_ctx, local_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_SET_LOCAL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, local_idx);
|
||||
if (!aot_compile_op_set_local(comp_ctx, func_ctx, local_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_TEE_LOCAL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, local_idx);
|
||||
if (!aot_compile_op_tee_local(comp_ctx, func_ctx, local_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_GET_GLOBAL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
if (!aot_compile_op_get_global(comp_ctx, func_ctx, global_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_SET_GLOBAL:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
if (!aot_compile_op_set_global(comp_ctx, func_ctx, global_idx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_LOAD:
|
||||
bytes = 4;
|
||||
sign = true;
|
||||
goto op_i32_load;
|
||||
case WASM_OP_I32_LOAD8_S:
|
||||
case WASM_OP_I32_LOAD8_U:
|
||||
bytes = 1;
|
||||
sign = (opcode == WASM_OP_I32_LOAD8_S) ? true : false;
|
||||
goto op_i32_load;
|
||||
case WASM_OP_I32_LOAD16_S:
|
||||
case WASM_OP_I32_LOAD16_U:
|
||||
bytes = 2;
|
||||
sign = (opcode == WASM_OP_I32_LOAD16_S) ? true : false;
|
||||
op_i32_load:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, offset,
|
||||
bytes, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_LOAD:
|
||||
bytes = 8;
|
||||
sign = true;
|
||||
goto op_i64_load;
|
||||
case WASM_OP_I64_LOAD8_S:
|
||||
case WASM_OP_I64_LOAD8_U:
|
||||
bytes = 1;
|
||||
sign = (opcode == WASM_OP_I64_LOAD8_S) ? true : false;
|
||||
goto op_i64_load;
|
||||
case WASM_OP_I64_LOAD16_S:
|
||||
case WASM_OP_I64_LOAD16_U:
|
||||
bytes = 2;
|
||||
sign = (opcode == WASM_OP_I64_LOAD16_S) ? true : false;
|
||||
goto op_i64_load;
|
||||
case WASM_OP_I64_LOAD32_S:
|
||||
case WASM_OP_I64_LOAD32_U:
|
||||
bytes = 4;
|
||||
sign = (opcode == WASM_OP_I64_LOAD32_S) ? true : false;
|
||||
op_i64_load:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset,
|
||||
bytes, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_LOAD:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_LOAD:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_STORE:
|
||||
bytes = 4;
|
||||
goto op_i32_store;
|
||||
case WASM_OP_I32_STORE8:
|
||||
bytes = 1;
|
||||
goto op_i32_store;
|
||||
case WASM_OP_I32_STORE16:
|
||||
bytes = 2;
|
||||
op_i32_store:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, bytes))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_STORE:
|
||||
bytes = 8;
|
||||
goto op_i64_store;
|
||||
case WASM_OP_I64_STORE8:
|
||||
bytes = 1;
|
||||
goto op_i64_store;
|
||||
case WASM_OP_I64_STORE16:
|
||||
bytes = 2;
|
||||
goto op_i64_store;
|
||||
case WASM_OP_I64_STORE32:
|
||||
bytes = 4;
|
||||
op_i64_store:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, bytes))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_STORE:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_STORE:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, align);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, offset);
|
||||
if (!aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_MEMORY_SIZE:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
|
||||
if (!aot_compile_op_memory_size(comp_ctx, func_ctx))
|
||||
return false;
|
||||
(void)mem_idx;
|
||||
break;
|
||||
|
||||
case WASM_OP_MEMORY_GROW:
|
||||
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
|
||||
if (!aot_compile_op_memory_grow(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CONST:
|
||||
read_leb_int32(frame_ip, frame_ip_end, i32_const);
|
||||
if (!aot_compile_op_i32_const(comp_ctx, func_ctx, i32_const))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_CONST:
|
||||
read_leb_int64(frame_ip, frame_ip_end, i64_const);
|
||||
if (!aot_compile_op_i64_const(comp_ctx, func_ctx, i64_const))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_CONST:
|
||||
p_f32 = (uint8*)&f32_const;
|
||||
for (i = 0; i < sizeof(float32); i++)
|
||||
*p_f32++ = *frame_ip++;
|
||||
if (!aot_compile_op_f32_const(comp_ctx, func_ctx, f32_const))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_CONST:
|
||||
p_f64 = (uint8*)&f64_const;
|
||||
for (i = 0; i < sizeof(float64); i++)
|
||||
*p_f64++ = *frame_ip++;
|
||||
if (!aot_compile_op_f64_const(comp_ctx, func_ctx, f64_const))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_EQZ:
|
||||
case WASM_OP_I32_EQ:
|
||||
case WASM_OP_I32_NE:
|
||||
case WASM_OP_I32_LT_S:
|
||||
case WASM_OP_I32_LT_U:
|
||||
case WASM_OP_I32_GT_S:
|
||||
case WASM_OP_I32_GT_U:
|
||||
case WASM_OP_I32_LE_S:
|
||||
case WASM_OP_I32_LE_U:
|
||||
case WASM_OP_I32_GE_S:
|
||||
case WASM_OP_I32_GE_U:
|
||||
if (!aot_compile_op_i32_compare(comp_ctx, func_ctx,
|
||||
INT_EQZ + opcode - WASM_OP_I32_EQZ))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EQZ:
|
||||
case WASM_OP_I64_EQ:
|
||||
case WASM_OP_I64_NE:
|
||||
case WASM_OP_I64_LT_S:
|
||||
case WASM_OP_I64_LT_U:
|
||||
case WASM_OP_I64_GT_S:
|
||||
case WASM_OP_I64_GT_U:
|
||||
case WASM_OP_I64_LE_S:
|
||||
case WASM_OP_I64_LE_U:
|
||||
case WASM_OP_I64_GE_S:
|
||||
case WASM_OP_I64_GE_U:
|
||||
if (!aot_compile_op_i64_compare(comp_ctx, func_ctx,
|
||||
INT_EQZ + opcode - WASM_OP_I64_EQZ))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_EQ:
|
||||
case WASM_OP_F32_NE:
|
||||
case WASM_OP_F32_LT:
|
||||
case WASM_OP_F32_GT:
|
||||
case WASM_OP_F32_LE:
|
||||
case WASM_OP_F32_GE:
|
||||
if (!aot_compile_op_f32_compare(comp_ctx, func_ctx,
|
||||
FLOAT_EQ + opcode - WASM_OP_F32_EQ))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_EQ:
|
||||
case WASM_OP_F64_NE:
|
||||
case WASM_OP_F64_LT:
|
||||
case WASM_OP_F64_GT:
|
||||
case WASM_OP_F64_LE:
|
||||
case WASM_OP_F64_GE:
|
||||
if (!aot_compile_op_f64_compare(comp_ctx, func_ctx,
|
||||
FLOAT_EQ + opcode - WASM_OP_F64_EQ))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CLZ:
|
||||
if (!aot_compile_op_i32_clz(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CTZ:
|
||||
if (!aot_compile_op_i32_ctz(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_POPCNT:
|
||||
if (!aot_compile_op_i32_popcnt(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_ADD:
|
||||
case WASM_OP_I32_SUB:
|
||||
case WASM_OP_I32_MUL:
|
||||
case WASM_OP_I32_DIV_S:
|
||||
case WASM_OP_I32_DIV_U:
|
||||
case WASM_OP_I32_REM_S:
|
||||
case WASM_OP_I32_REM_U:
|
||||
if (!aot_compile_op_i32_arithmetic(comp_ctx, func_ctx,
|
||||
INT_ADD + opcode - WASM_OP_I32_ADD,
|
||||
&frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_AND:
|
||||
case WASM_OP_I32_OR:
|
||||
case WASM_OP_I32_XOR:
|
||||
if (!aot_compile_op_i32_bitwise(comp_ctx, func_ctx,
|
||||
INT_SHL + opcode - WASM_OP_I32_AND))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_SHL:
|
||||
case WASM_OP_I32_SHR_S:
|
||||
case WASM_OP_I32_SHR_U:
|
||||
case WASM_OP_I32_ROTL:
|
||||
case WASM_OP_I32_ROTR:
|
||||
if (!aot_compile_op_i32_shift(comp_ctx, func_ctx,
|
||||
INT_SHL + opcode - WASM_OP_I32_SHL))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_CLZ:
|
||||
if (!aot_compile_op_i64_clz(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_CTZ:
|
||||
if (!aot_compile_op_i64_ctz(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_POPCNT:
|
||||
if (!aot_compile_op_i64_popcnt(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_ADD:
|
||||
case WASM_OP_I64_SUB:
|
||||
case WASM_OP_I64_MUL:
|
||||
case WASM_OP_I64_DIV_S:
|
||||
case WASM_OP_I64_DIV_U:
|
||||
case WASM_OP_I64_REM_S:
|
||||
case WASM_OP_I64_REM_U:
|
||||
if (!aot_compile_op_i64_arithmetic(comp_ctx, func_ctx,
|
||||
INT_ADD + opcode - WASM_OP_I64_ADD,
|
||||
&frame_ip))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_AND:
|
||||
case WASM_OP_I64_OR:
|
||||
case WASM_OP_I64_XOR:
|
||||
if (!aot_compile_op_i64_bitwise(comp_ctx, func_ctx,
|
||||
INT_SHL + opcode - WASM_OP_I64_AND))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_SHL:
|
||||
case WASM_OP_I64_SHR_S:
|
||||
case WASM_OP_I64_SHR_U:
|
||||
case WASM_OP_I64_ROTL:
|
||||
case WASM_OP_I64_ROTR:
|
||||
if (!aot_compile_op_i64_shift(comp_ctx, func_ctx,
|
||||
INT_SHL + opcode - WASM_OP_I64_SHL))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_ABS:
|
||||
case WASM_OP_F32_NEG:
|
||||
case WASM_OP_F32_CEIL:
|
||||
case WASM_OP_F32_FLOOR:
|
||||
case WASM_OP_F32_TRUNC:
|
||||
case WASM_OP_F32_NEAREST:
|
||||
case WASM_OP_F32_SQRT:
|
||||
if (!aot_compile_op_f32_math(comp_ctx, func_ctx,
|
||||
FLOAT_ABS + opcode - WASM_OP_F32_ABS))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_ADD:
|
||||
case WASM_OP_F32_SUB:
|
||||
case WASM_OP_F32_MUL:
|
||||
case WASM_OP_F32_DIV:
|
||||
case WASM_OP_F32_MIN:
|
||||
case WASM_OP_F32_MAX:
|
||||
if (!aot_compile_op_f32_arithmetic(comp_ctx, func_ctx,
|
||||
FLOAT_ADD + opcode - WASM_OP_F32_ADD))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_COPYSIGN:
|
||||
if (!aot_compile_op_f32_copysign(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_ABS:
|
||||
case WASM_OP_F64_NEG:
|
||||
case WASM_OP_F64_CEIL:
|
||||
case WASM_OP_F64_FLOOR:
|
||||
case WASM_OP_F64_TRUNC:
|
||||
case WASM_OP_F64_NEAREST:
|
||||
case WASM_OP_F64_SQRT:
|
||||
if (!aot_compile_op_f64_math(comp_ctx, func_ctx,
|
||||
FLOAT_ABS + opcode - WASM_OP_F64_ABS))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_ADD:
|
||||
case WASM_OP_F64_SUB:
|
||||
case WASM_OP_F64_MUL:
|
||||
case WASM_OP_F64_DIV:
|
||||
case WASM_OP_F64_MIN:
|
||||
case WASM_OP_F64_MAX:
|
||||
if (!aot_compile_op_f64_arithmetic(comp_ctx, func_ctx,
|
||||
FLOAT_ADD + opcode - WASM_OP_F64_ADD))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_COPYSIGN:
|
||||
if (!aot_compile_op_f64_copysign(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_WRAP_I64:
|
||||
if (!aot_compile_op_i32_wrap_i64(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_TRUNC_S_F32:
|
||||
case WASM_OP_I32_TRUNC_U_F32:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_TRUNC_S_F64:
|
||||
case WASM_OP_I32_TRUNC_U_F64:
|
||||
sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_EXTEND_S_I32:
|
||||
case WASM_OP_I64_EXTEND_U_I32:
|
||||
sign = (opcode == WASM_OP_I64_EXTEND_S_I32) ? true : false;
|
||||
if (!aot_compile_op_i64_extend_i32(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_TRUNC_S_F32:
|
||||
case WASM_OP_I64_TRUNC_U_F32:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_TRUNC_S_F64:
|
||||
case WASM_OP_I64_TRUNC_U_F64:
|
||||
sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false;
|
||||
if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_CONVERT_S_I32:
|
||||
case WASM_OP_F32_CONVERT_U_I32:
|
||||
sign = (opcode == WASM_OP_F32_CONVERT_S_I32) ? true : false;
|
||||
if (!aot_compile_op_f32_convert_i32(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_CONVERT_S_I64:
|
||||
case WASM_OP_F32_CONVERT_U_I64:
|
||||
sign = (opcode == WASM_OP_F32_CONVERT_S_I64) ? true : false;
|
||||
if (!aot_compile_op_f32_convert_i64(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_DEMOTE_F64:
|
||||
if (!aot_compile_op_f32_demote_f64(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_CONVERT_S_I32:
|
||||
case WASM_OP_F64_CONVERT_U_I32:
|
||||
sign = (opcode == WASM_OP_F64_CONVERT_S_I32) ? true : false;
|
||||
if (!aot_compile_op_f64_convert_i32(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_CONVERT_S_I64:
|
||||
case WASM_OP_F64_CONVERT_U_I64:
|
||||
sign = (opcode == WASM_OP_F64_CONVERT_S_I64) ? true : false;
|
||||
if (!aot_compile_op_f64_convert_i64(comp_ctx, func_ctx, sign))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_PROMOTE_F32:
|
||||
if (!aot_compile_op_f64_promote_f32(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_REINTERPRET_F32:
|
||||
if (!aot_compile_op_i32_reinterpret_f32(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_I64_REINTERPRET_F64:
|
||||
if (!aot_compile_op_i64_reinterpret_f64(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F32_REINTERPRET_I32:
|
||||
if (!aot_compile_op_f32_reinterpret_i32(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case WASM_OP_F64_REINTERPRET_I64:
|
||||
if (!aot_compile_op_f64_reinterpret_i64(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move func_return block to the bottom */
|
||||
if (func_ctx->func_return_block) {
|
||||
LLVMBasicBlockRef last_block =
|
||||
LLVMGetLastBasicBlock(func_ctx->func);
|
||||
if (last_block != func_ctx->func_return_block)
|
||||
LLVMMoveBasicBlockAfter(func_ctx->func_return_block,
|
||||
last_block);
|
||||
}
|
||||
|
||||
/* Move got_exception block to the bottom */
|
||||
if (func_ctx->got_exception_block) {
|
||||
LLVMBasicBlockRef last_block =
|
||||
LLVMGetLastBasicBlock(func_ctx->func);
|
||||
if (last_block != func_ctx->got_exception_block)
|
||||
LLVMMoveBasicBlockAfter(func_ctx->got_exception_block,
|
||||
last_block);
|
||||
|
||||
/* Move all other exception blocks before got_exception block */
|
||||
for (i = 0; i < EXCE_NUM; i++) {
|
||||
if (func_ctx->exception_blocks[i])
|
||||
LLVMMoveBasicBlockBefore(func_ctx->exception_blocks[i],
|
||||
func_ctx->got_exception_block);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||
{
|
||||
char *msg = NULL;
|
||||
bool ret;
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
||||
if (!aot_compile_func(comp_ctx, i)) {
|
||||
#if 0
|
||||
LLVMDumpModule(comp_ctx->module);
|
||||
char *err;
|
||||
LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module,
|
||||
"./test.o", LLVMObjectFile, &err);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
LLVMDumpModule(comp_ctx->module);
|
||||
/* Clear error no, LLVMDumpModule may set errno */
|
||||
errno = 0;
|
||||
#endif
|
||||
|
||||
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
|
||||
if (!ret && msg) {
|
||||
if (msg[0] != '\0') {
|
||||
aot_set_last_error(msg);
|
||||
LLVMDisposeMessage(msg);
|
||||
return false;
|
||||
}
|
||||
LLVMDisposeMessage(msg);
|
||||
}
|
||||
|
||||
if (comp_ctx->optimize) {
|
||||
LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr);
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
||||
LLVMRunFunctionPassManager(comp_ctx->pass_mgr,
|
||||
comp_ctx->func_ctxes[i]->func);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
|
||||
{
|
||||
char *err = NULL;
|
||||
|
||||
if (LLVMPrintModuleToFile(comp_ctx->module, file_name, &err) != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("emit llvm ir to file failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
|
||||
{
|
||||
char *err = NULL;
|
||||
|
||||
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
|
||||
comp_ctx->module,
|
||||
file_name,
|
||||
LLVMObjectFile,
|
||||
&err) != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("emit elf to memory buffer failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
248
core/iwasm/compilation/aot_compiler.h
Normal file
248
core/iwasm/compilation/aot_compiler.h
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_COMPILER_H_
|
||||
#define _AOT_COMPILER_H_
|
||||
|
||||
#include "aot.h"
|
||||
#include "aot_llvm.h"
|
||||
#include "bh_memory.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum IntCond {
|
||||
INT_EQZ = 0,
|
||||
INT_EQ,
|
||||
INT_NE,
|
||||
INT_LT_S,
|
||||
INT_LT_U,
|
||||
INT_GT_S,
|
||||
INT_GT_U,
|
||||
INT_LE_S,
|
||||
INT_LE_U,
|
||||
INT_GE_S,
|
||||
INT_GE_U
|
||||
} IntCond;
|
||||
|
||||
typedef enum FloatCond {
|
||||
FLOAT_EQ = 0,
|
||||
FLOAT_NE,
|
||||
FLOAT_LT,
|
||||
FLOAT_GT,
|
||||
FLOAT_LE,
|
||||
FLOAT_GE
|
||||
} FloatCond;
|
||||
|
||||
typedef enum IntArithmetic {
|
||||
INT_ADD = 0,
|
||||
INT_SUB,
|
||||
INT_MUL,
|
||||
INT_DIV_S,
|
||||
INT_DIV_U,
|
||||
INT_REM_S,
|
||||
INT_REM_U
|
||||
} IntArithmetic;
|
||||
|
||||
typedef enum IntBitwise {
|
||||
INT_AND = 0,
|
||||
INT_OR,
|
||||
INT_XOR,
|
||||
} IntBitwise;
|
||||
|
||||
typedef enum IntShift {
|
||||
INT_SHL = 0,
|
||||
INT_SHR_S,
|
||||
INT_SHR_U,
|
||||
INT_ROTL,
|
||||
INT_ROTR
|
||||
} IntShift;
|
||||
|
||||
typedef enum FloatMath {
|
||||
FLOAT_ABS = 0,
|
||||
FLOAT_NEG,
|
||||
FLOAT_CEIL,
|
||||
FLOAT_FLOOR,
|
||||
FLOAT_TRUNC,
|
||||
FLOAT_NEAREST,
|
||||
FLOAT_SQRT
|
||||
} FloatMath;
|
||||
|
||||
typedef enum FloatArithmetic {
|
||||
FLOAT_ADD = 0,
|
||||
FLOAT_SUB,
|
||||
FLOAT_MUL,
|
||||
FLOAT_DIV,
|
||||
FLOAT_MIN,
|
||||
FLOAT_MAX
|
||||
} FloatArithmetic;
|
||||
|
||||
#define CHECK_STACK() do { \
|
||||
if (!func_ctx->block_stack.block_list_end) { \
|
||||
aot_set_last_error("WASM block stack underflow."); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (!func_ctx->block_stack.block_list_end-> \
|
||||
value_stack.value_list_end) { \
|
||||
aot_set_last_error("WASM data stack underflow."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define POP(llvm_value, value_type) do { \
|
||||
AOTValue *aot_value; \
|
||||
CHECK_STACK(); \
|
||||
aot_value = aot_value_stack_pop \
|
||||
(&func_ctx->block_stack.block_list_end->value_stack); \
|
||||
if ((value_type != VALUE_TYPE_I32 \
|
||||
&& aot_value->type != value_type) \
|
||||
|| (value_type == VALUE_TYPE_I32 \
|
||||
&& (aot_value->type != VALUE_TYPE_I32 \
|
||||
&& aot_value->type != VALUE_TYPE_I1))) { \
|
||||
aot_set_last_error("invalid WASM stack data type."); \
|
||||
wasm_free(aot_value); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (aot_value->type == value_type) \
|
||||
llvm_value = aot_value->value; \
|
||||
else { \
|
||||
bh_assert(aot_value->type == VALUE_TYPE_I1); \
|
||||
if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \
|
||||
aot_value->value, I32_TYPE, "i1toi32"))) { \
|
||||
aot_set_last_error("invalid WASM stack data type.");\
|
||||
wasm_free(aot_value); \
|
||||
goto fail; \
|
||||
} \
|
||||
} \
|
||||
wasm_free(aot_value); \
|
||||
} while (0)
|
||||
|
||||
#define POP_I32(v) POP(v, VALUE_TYPE_I32)
|
||||
#define POP_I64(v) POP(v, VALUE_TYPE_I64)
|
||||
#define POP_F32(v) POP(v, VALUE_TYPE_F32)
|
||||
#define POP_F64(v) POP(v, VALUE_TYPE_F64)
|
||||
|
||||
#define POP_COND(llvm_value) do { \
|
||||
AOTValue *aot_value; \
|
||||
CHECK_STACK(); \
|
||||
aot_value = aot_value_stack_pop \
|
||||
(&func_ctx->block_stack.block_list_end->value_stack); \
|
||||
if (aot_value->type != VALUE_TYPE_I1 \
|
||||
&& aot_value->type != VALUE_TYPE_I32) { \
|
||||
aot_set_last_error("invalid WASM stack data type."); \
|
||||
wasm_free(aot_value); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (aot_value->type == VALUE_TYPE_I1) \
|
||||
llvm_value = aot_value->value; \
|
||||
else { \
|
||||
if (!(llvm_value = LLVMBuildICmp(comp_ctx->builder, \
|
||||
LLVMIntNE, aot_value->value, I32_ZERO, \
|
||||
"i1_cond"))){ \
|
||||
aot_set_last_error("llvm build trunc failed."); \
|
||||
wasm_free(aot_value); \
|
||||
goto fail; \
|
||||
} \
|
||||
} \
|
||||
wasm_free(aot_value); \
|
||||
} while (0)
|
||||
|
||||
#define PUSH(llvm_value, value_type) do { \
|
||||
AOTValue *aot_value; \
|
||||
if (!func_ctx->block_stack.block_list_end) { \
|
||||
aot_set_last_error("WASM block stack underflow."); \
|
||||
goto fail; \
|
||||
} \
|
||||
aot_value = wasm_malloc(sizeof(AOTValue)); \
|
||||
memset(aot_value, 0, sizeof(AOTValue)); \
|
||||
if (!aot_value) { \
|
||||
aot_set_last_error("allocate memory failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
aot_value->type = value_type; \
|
||||
aot_value->value = llvm_value; \
|
||||
aot_value_stack_push \
|
||||
(&func_ctx->block_stack.block_list_end->value_stack,\
|
||||
aot_value); \
|
||||
} while (0)
|
||||
|
||||
#define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32)
|
||||
#define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
|
||||
#define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
|
||||
#define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
|
||||
#define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
|
||||
|
||||
#define TO_LLVM_TYPE(wasm_type) \
|
||||
wasm_type_to_llvm_type(&comp_ctx->basic_types, wasm_type)
|
||||
|
||||
#define I32_TYPE comp_ctx->basic_types.int32_type
|
||||
#define I64_TYPE comp_ctx->basic_types.int64_type
|
||||
#define F32_TYPE comp_ctx->basic_types.float32_type
|
||||
#define F64_TYPE comp_ctx->basic_types.float64_type
|
||||
#define VOID_TYPE comp_ctx->basic_types.void_type
|
||||
#define INT1_TYPE comp_ctx->basic_types.int1_type
|
||||
#define INT8_TYPE comp_ctx->basic_types.int8_type
|
||||
#define INT16_TYPE comp_ctx->basic_types.int16_type
|
||||
#define MD_TYPE comp_ctx->basic_types.meta_data_type
|
||||
#define INT8_PTR_TYPE comp_ctx->basic_types.int8_ptr_type
|
||||
#define INT16_PTR_TYPE comp_ctx->basic_types.int16_ptr_type
|
||||
#define INT32_PTR_TYPE comp_ctx->basic_types.int32_ptr_type
|
||||
#define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type
|
||||
#define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type
|
||||
#define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type
|
||||
#define VOID_PTR_TYPE comp_ctx->basic_types.void_ptr_type
|
||||
|
||||
#define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true)
|
||||
#define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true)
|
||||
#define F32_CONST(v) LLVMConstReal(F32_TYPE, v)
|
||||
#define F64_CONST(v) LLVMConstReal(F64_TYPE, v)
|
||||
#define I8_CONST(v) LLVMConstInt(INT8_TYPE, v, true)
|
||||
|
||||
#define I8_ZERO (comp_ctx->llvm_consts.i8_zero)
|
||||
#define I32_ZERO (comp_ctx->llvm_consts.i32_zero)
|
||||
#define I64_ZERO (comp_ctx->llvm_consts.i64_zero)
|
||||
#define F32_ZERO (comp_ctx->llvm_consts.f32_zero)
|
||||
#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_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)
|
||||
#define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one)
|
||||
#define I32_MIN (comp_ctx->llvm_consts.i32_min)
|
||||
#define I64_MIN (comp_ctx->llvm_consts.i64_min)
|
||||
#define I32_31 (comp_ctx->llvm_consts.i32_31)
|
||||
#define I32_32 (comp_ctx->llvm_consts.i32_32)
|
||||
#define I64_63 (comp_ctx->llvm_consts.i64_63)
|
||||
#define I64_64 (comp_ctx->llvm_consts.i64_64)
|
||||
|
||||
#define CHECK_LLVM_CONST(v) do { \
|
||||
if (!v) { \
|
||||
aot_set_last_error("create llvm const failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
bool
|
||||
aot_compile_wasm(AOTCompContext *comp_ctx);
|
||||
|
||||
bool
|
||||
aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name);
|
||||
|
||||
bool
|
||||
aot_emit_aot_file(AOTCompContext *comp_ctx,
|
||||
AOTCompData *comp_data,
|
||||
const char *file_name);
|
||||
|
||||
bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_COMPILER_H_ */
|
||||
|
||||
1934
core/iwasm/compilation/aot_emit_aot_file.c
Normal file
1934
core/iwasm/compilation/aot_emit_aot_file.c
Normal file
File diff suppressed because it is too large
Load Diff
196
core/iwasm/compilation/aot_emit_compare.c
Normal file
196
core/iwasm/compilation/aot_emit_compare.c
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_compare.h"
|
||||
|
||||
static bool
|
||||
int_cond_to_llvm_op(IntCond cond, LLVMIntPredicate *op)
|
||||
{
|
||||
if (cond < INT_EQZ || cond > INT_GE_U)
|
||||
return false;
|
||||
|
||||
switch (cond) {
|
||||
case INT_EQZ:
|
||||
case INT_EQ:
|
||||
*op = LLVMIntEQ;
|
||||
break;
|
||||
case INT_NE:
|
||||
*op = LLVMIntNE;
|
||||
break;
|
||||
case INT_LT_S:
|
||||
*op = LLVMIntSLT;
|
||||
break;
|
||||
case INT_LT_U:
|
||||
*op = LLVMIntULT;
|
||||
break;
|
||||
case INT_GT_S:
|
||||
*op = LLVMIntSGT;
|
||||
break;
|
||||
case INT_GT_U:
|
||||
*op = LLVMIntUGT;
|
||||
break;
|
||||
case INT_LE_S:
|
||||
*op = LLVMIntSLE;
|
||||
break;
|
||||
case INT_LE_U:
|
||||
*op = LLVMIntULE;
|
||||
break;
|
||||
case INT_GE_S:
|
||||
*op = LLVMIntSGE;
|
||||
break;
|
||||
case INT_GE_U:
|
||||
*op = LLVMIntUGE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
float_cond_to_llvm_op(FloatCond cond, LLVMRealPredicate *op)
|
||||
{
|
||||
if (cond < FLOAT_EQ || cond > FLOAT_GE)
|
||||
return false;
|
||||
|
||||
switch (cond) {
|
||||
case FLOAT_EQ:
|
||||
*op = LLVMRealOEQ;
|
||||
break;
|
||||
case FLOAT_NE:
|
||||
*op = LLVMRealUNE;
|
||||
break;
|
||||
case FLOAT_LT:
|
||||
*op = LLVMRealOLT;
|
||||
break;
|
||||
case FLOAT_GT:
|
||||
*op = LLVMRealOGT;
|
||||
break;
|
||||
case FLOAT_LE:
|
||||
*op = LLVMRealOLE;
|
||||
break;
|
||||
case FLOAT_GE:
|
||||
*op = LLVMRealOGE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntCond cond)
|
||||
{
|
||||
LLVMIntPredicate op;
|
||||
LLVMValueRef lhs, rhs, res;
|
||||
|
||||
if (!int_cond_to_llvm_op(cond, &op)) {
|
||||
aot_set_last_error("invalid WASM condition opcode");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cond == INT_EQZ)
|
||||
rhs = I32_ZERO;
|
||||
else
|
||||
POP_I32(rhs);
|
||||
|
||||
POP_I32(lhs);
|
||||
|
||||
if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i32_cmp"))) {
|
||||
aot_set_last_error("llvm build compare failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_COND(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntCond cond)
|
||||
{
|
||||
LLVMIntPredicate op;
|
||||
LLVMValueRef lhs, rhs, res;
|
||||
|
||||
if (!int_cond_to_llvm_op(cond, &op)) {
|
||||
aot_set_last_error("invalid WASM condition opcode");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cond == INT_EQZ)
|
||||
rhs = I64_CONST(0);
|
||||
else
|
||||
POP_I64(rhs);
|
||||
|
||||
POP_I64(lhs);
|
||||
|
||||
if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i64_cmp"))) {
|
||||
aot_set_last_error("llvm build compare failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_COND(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatCond cond)
|
||||
{
|
||||
LLVMRealPredicate op;
|
||||
LLVMValueRef lhs, rhs, res;
|
||||
|
||||
if (!float_cond_to_llvm_op(cond, &op)) {
|
||||
aot_set_last_error("invalid WASM condition opcode");
|
||||
return false;
|
||||
}
|
||||
|
||||
POP_F32(rhs);
|
||||
POP_F32(lhs);
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp"))) {
|
||||
aot_set_last_error("llvm build compare failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_COND(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatCond cond)
|
||||
{
|
||||
LLVMRealPredicate op;
|
||||
LLVMValueRef lhs, rhs, res;
|
||||
|
||||
if (!float_cond_to_llvm_op(cond, &op)) {
|
||||
aot_set_last_error("invalid WASM condition opcode");
|
||||
return false;
|
||||
}
|
||||
|
||||
POP_F64(rhs);
|
||||
POP_F64(lhs);
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp"))) {
|
||||
aot_set_last_error("llvm build compare failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_COND(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
37
core/iwasm/compilation/aot_emit_compare.h
Normal file
37
core/iwasm/compilation/aot_emit_compare.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_COMPARE_H_
|
||||
#define _AOT_EMIT_COMPARE_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatCond cond);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_COMPARE_H_ */
|
||||
|
||||
115
core/iwasm/compilation/aot_emit_const.c
Normal file
115
core/iwasm/compilation/aot_emit_const.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_const.h"
|
||||
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int32 i32_const)
|
||||
{
|
||||
LLVMValueRef value = I32_CONST((uint32)i32_const);
|
||||
CHECK_LLVM_CONST(value);
|
||||
PUSH_I32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int64 i64_const)
|
||||
{
|
||||
LLVMValueRef value = I64_CONST((uint64)i64_const);
|
||||
CHECK_LLVM_CONST(value);
|
||||
PUSH_I64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
float32 f32_const)
|
||||
{
|
||||
LLVMValueRef alloca, value;
|
||||
|
||||
if (!isnan(f32_const)) {
|
||||
value = F32_CONST(f32_const);
|
||||
CHECK_LLVM_CONST(value);
|
||||
PUSH_F32(value);
|
||||
}
|
||||
else {
|
||||
int32 i32_const;
|
||||
memcpy(&i32_const, &f32_const, sizeof(int32));
|
||||
if (!(alloca = LLVMBuildAlloca(comp_ctx->builder,
|
||||
INT32_PTR_TYPE, "i32_ptr"))) {
|
||||
aot_set_last_error("llvm build alloca failed.");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildStore(comp_ctx->builder,
|
||||
I32_CONST((uint32)i32_const), alloca)) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(alloca = LLVMBuildBitCast(comp_ctx->builder,
|
||||
alloca, F32_PTR_TYPE, "f32_ptr"))) {
|
||||
aot_set_last_error("llvm build bitcast failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_F32(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
float64 f64_const)
|
||||
{
|
||||
LLVMValueRef alloca, value;
|
||||
|
||||
if (!isnan(f64_const)) {
|
||||
value = F64_CONST(f64_const);
|
||||
CHECK_LLVM_CONST(value);
|
||||
PUSH_F64(value);
|
||||
}
|
||||
else {
|
||||
int64 i64_const;
|
||||
memcpy(&i64_const, &f64_const, sizeof(int64));
|
||||
if (!(alloca = LLVMBuildAlloca(comp_ctx->builder,
|
||||
I64_TYPE, "i64_ptr"))) {
|
||||
aot_set_last_error("llvm build alloca failed.");
|
||||
return false;
|
||||
}
|
||||
value = I64_CONST((uint64)i64_const);
|
||||
CHECK_LLVM_CONST(value);
|
||||
if (!LLVMBuildStore(comp_ctx->builder, value, alloca)) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(alloca = LLVMBuildBitCast(comp_ctx->builder,
|
||||
alloca, F64_PTR_TYPE, "f64_ptr"))) {
|
||||
aot_set_last_error("llvm build bitcast failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_F64(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
36
core/iwasm/compilation/aot_emit_const.h
Normal file
36
core/iwasm/compilation/aot_emit_const.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_CONST_H_
|
||||
#define _AOT_EMIT_CONST_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int32 i32_const);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int64 i64_const);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
float32 f32_const);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
float64 f64_const);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_CONST_H_ */
|
||||
|
||||
672
core/iwasm/compilation/aot_emit_control.c
Normal file
672
core/iwasm/compilation/aot_emit_control.c
Normal file
@ -0,0 +1,672 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_control.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "../interpreter/wasm_loader.h"
|
||||
#include "bh_memory.h"
|
||||
|
||||
static char *block_name_prefix[] = { "block", "loop", "if" };
|
||||
static char *block_name_suffix[] = { "begin", "else", "end" };
|
||||
|
||||
enum {
|
||||
LABEL_BEGIN = 0,
|
||||
LABEL_ELSE,
|
||||
LABEL_END
|
||||
};
|
||||
|
||||
static void
|
||||
format_block_name(char *name, uint32 name_size,
|
||||
uint32 block_index, uint32 block_type,
|
||||
uint32 label_type)
|
||||
{
|
||||
if (block_type != BLOCK_TYPE_FUNCTION)
|
||||
snprintf(name, name_size, "%s%d%s%s",
|
||||
block_name_prefix[block_type], block_index,
|
||||
"_", block_name_suffix[label_type]);
|
||||
else
|
||||
snprintf(name, name_size, "%s", "func_end");
|
||||
}
|
||||
|
||||
#define CREATE_BLOCK(new_llvm_block, name) do { \
|
||||
if (!(new_llvm_block = \
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
aot_set_last_error("add LLVM basic block failed.");\
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder)
|
||||
|
||||
#define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \
|
||||
LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after)
|
||||
|
||||
#define MOVE_BLOCK_AFTER_CURR(llvm_block) \
|
||||
LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK())
|
||||
|
||||
#define MOVE_BLOCK_BEFORE(llvm_block, llvm_block_before) \
|
||||
LLVMMoveBasicBlockBefore(llvm_block, llvm_block_before)
|
||||
|
||||
#define BUILD_BR(llvm_block) do { \
|
||||
if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \
|
||||
aot_set_last_error("llvm build br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_COND_BR(value_if, block_then, block_else) do {\
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, value_if, \
|
||||
block_then, block_else)) { \
|
||||
aot_set_last_error("llvm build cond br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SET_BUILDER_POS(llvm_block) \
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block)
|
||||
|
||||
#define CREATE_RETURN_VALUE_PHI(block) do { \
|
||||
if (block->return_type != VALUE_TYPE_VOID \
|
||||
&& !block->return_value_phi) { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
SET_BUILDER_POS(block->llvm_end_block); \
|
||||
if (!(block->return_value_phi = \
|
||||
LLVMBuildPhi(comp_ctx->builder, \
|
||||
TO_LLVM_TYPE(block->return_type),\
|
||||
"phi"))) { \
|
||||
aot_set_last_error("llvm build phi failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
SET_BUILDER_POS(block_curr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADD_TO_RETURN_PHI(block, value) do { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
LLVMAddIncoming(block->return_value_phi, \
|
||||
&value, &block_curr, 1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static LLVMBasicBlockRef
|
||||
find_next_llvm_end_block(AOTBlock *block)
|
||||
{
|
||||
block = block->prev;
|
||||
while (block && !block->llvm_end_block)
|
||||
block = block->prev;
|
||||
return block ? block->llvm_end_block : NULL;
|
||||
}
|
||||
|
||||
static AOTBlock*
|
||||
get_target_block(AOTFuncContext *func_ctx, uint32 br_depth)
|
||||
{
|
||||
uint32 i = br_depth;
|
||||
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
||||
|
||||
while (i-- > 0 && block) {
|
||||
block = block->prev;
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return NULL;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_next_reachable_block(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
||||
AOTBlock *block_prev;
|
||||
uint8 *frame_ip;
|
||||
|
||||
if (block->block_type == BLOCK_TYPE_IF
|
||||
&& block->llvm_else_block
|
||||
&& !block->skip_wasm_code_else
|
||||
&& *p_frame_ip <= block->wasm_code_else) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
*p_frame_ip = block->wasm_code_else + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
while (block && !block->is_reachable) {
|
||||
block_prev = block->prev;
|
||||
block = aot_block_stack_pop(&func_ctx->block_stack);
|
||||
|
||||
if (block->block_type == BLOCK_TYPE_IF
|
||||
&& block->llvm_end_block) {
|
||||
LLVMDeleteBasicBlock(block->llvm_end_block);
|
||||
block->llvm_end_block = NULL;
|
||||
}
|
||||
|
||||
frame_ip = block->wasm_code_end;
|
||||
aot_block_destroy(block);
|
||||
block = block_prev;
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
*p_frame_ip = frame_ip + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
*p_frame_ip = block->wasm_code_end + 1;
|
||||
SET_BUILDER_POS(block->llvm_end_block);
|
||||
|
||||
/* Pop block, push its return value, and destroy the block */
|
||||
block = aot_block_stack_pop(&func_ctx->block_stack);
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
bh_assert(block->return_value_phi);
|
||||
if (block->block_type != BLOCK_TYPE_FUNCTION)
|
||||
PUSH(block->return_value_phi, block->return_type);
|
||||
else
|
||||
LLVMBuildRet(comp_ctx->builder, block->return_value_phi);
|
||||
}
|
||||
else if (block->block_type == BLOCK_TYPE_FUNCTION) {
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
}
|
||||
aot_block_destroy(block);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip, uint8 *frame_ip_end,
|
||||
uint32 block_type, uint32 block_ret_type)
|
||||
{
|
||||
AOTBlock *block;
|
||||
uint8 *else_addr, *end_addr;
|
||||
LLVMValueRef value;
|
||||
char name[32];
|
||||
|
||||
/* Check block stack */
|
||||
if (!func_ctx->block_stack.block_list_end) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get block info */
|
||||
if (!(wasm_loader_find_block_addr(comp_ctx->comp_data->wasm_module,
|
||||
*p_frame_ip, frame_ip_end, (uint8)block_type,
|
||||
&else_addr, &end_addr, NULL, 0))) {
|
||||
aot_set_last_error("find block end addr failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
if (!(block = wasm_malloc(sizeof(AOTBlock)))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init aot block data */
|
||||
memset(block, 0, sizeof(AOTBlock));
|
||||
block->block_type = block_type;
|
||||
block->return_type = (uint8)block_ret_type;
|
||||
block->wasm_code_else = else_addr;
|
||||
block->wasm_code_end = end_addr;
|
||||
block->block_index = func_ctx->block_stack.block_index[block_type];
|
||||
func_ctx->block_stack.block_index[block_type]++;
|
||||
|
||||
if (block_type == BLOCK_TYPE_BLOCK
|
||||
|| block_type == BLOCK_TYPE_LOOP) {
|
||||
/* Create block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
/* Jump to the entry block */
|
||||
BUILD_BR(block->llvm_entry_block);
|
||||
/* Start to translate the block */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else if (block_type == BLOCK_TYPE_IF) {
|
||||
POP_COND(value);
|
||||
if (!LLVMIsConstant(value)) {
|
||||
/* Compare value is not constant, create condition br IR */
|
||||
/* Create entry block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
|
||||
/* Create end block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
|
||||
|
||||
if (else_addr) {
|
||||
/* Create else block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_ELSE);
|
||||
CREATE_BLOCK(block->llvm_else_block, name);
|
||||
MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block);
|
||||
/* Create condition br IR */
|
||||
BUILD_COND_BR(value, block->llvm_entry_block,
|
||||
block->llvm_else_block);
|
||||
}
|
||||
else {
|
||||
/* Create condition br IR */
|
||||
BUILD_COND_BR(value, block->llvm_entry_block,
|
||||
block->llvm_end_block);
|
||||
block->is_reachable = true;
|
||||
}
|
||||
/* Start to translate if branch of BLOCK if */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
|
||||
/* Compare value is not 0, condtion is true, else branch of
|
||||
BLOCK if cannot be reached */
|
||||
block->skip_wasm_code_else = true;
|
||||
/* Create entry block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
/* Jump to the entry block */
|
||||
BUILD_BR(block->llvm_entry_block);
|
||||
/* Start to translate the if branch */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
/* Compare value is not 0, condtion is false, if branch of
|
||||
BLOCK if cannot be reached */
|
||||
if (else_addr) {
|
||||
/* Create else block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_ELSE);
|
||||
CREATE_BLOCK(block->llvm_else_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
|
||||
/* Jump to the else block */
|
||||
BUILD_BR(block->llvm_else_block);
|
||||
/* Start to translate the else branch */
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
*p_frame_ip = else_addr + 1;
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
aot_set_last_error("WASM value stack underflow.");
|
||||
goto fail;
|
||||
}
|
||||
/* skip the block */
|
||||
wasm_free(block);
|
||||
*p_frame_ip = end_addr + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aot_set_last_error("Invalid block type.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
wasm_free(block);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
||||
LLVMValueRef value;
|
||||
char name[32];
|
||||
|
||||
/* Check block */
|
||||
if (!block) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return false;
|
||||
}
|
||||
if (block->block_type != BLOCK_TYPE_IF
|
||||
|| (!block->skip_wasm_code_else
|
||||
&& !block->llvm_else_block)) {
|
||||
aot_set_last_error("Invalid WASM block type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create end block if needed */
|
||||
if (!block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block->block_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
if (block->llvm_else_block)
|
||||
MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
|
||||
else
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_end_block);
|
||||
}
|
||||
|
||||
block->is_reachable = true;
|
||||
|
||||
/* Comes from the if branch of BLOCK if */
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block);
|
||||
ADD_TO_RETURN_PHI(block, value);
|
||||
}
|
||||
|
||||
/* Jump to end block */
|
||||
BUILD_BR(block->llvm_end_block);
|
||||
|
||||
if (!block->skip_wasm_code_else
|
||||
&& block->llvm_else_block) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* No else branch or no need to translate else branch */
|
||||
block->is_reachable = true;
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block;
|
||||
LLVMValueRef value;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
char name[32];
|
||||
|
||||
/* Check block stack */
|
||||
if (!(block = func_ctx->block_stack.block_list_end)) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create the end block */
|
||||
if (!block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block->block_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block)))
|
||||
MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
|
||||
}
|
||||
|
||||
/* Handle block return value */
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block);
|
||||
ADD_TO_RETURN_PHI(block, value);
|
||||
}
|
||||
|
||||
/* Jump to the end block */
|
||||
BUILD_BR(block->llvm_end_block);
|
||||
|
||||
block->is_reachable = true;
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 br_depth, uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block_dst;
|
||||
LLVMValueRef value_ret;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
char name[32];
|
||||
|
||||
if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block_dst->block_type == BLOCK_TYPE_LOOP) {
|
||||
/* Dest block is Loop block */
|
||||
BUILD_BR(block_dst->llvm_entry_block);
|
||||
}
|
||||
else {
|
||||
/* Dest block is Block/If/Function block */
|
||||
/* Create the end block */
|
||||
if (!block_dst->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block_dst->block_index, block_dst->block_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(block_dst->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
|
||||
MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
|
||||
next_llvm_end_block);
|
||||
}
|
||||
|
||||
block_dst->is_reachable = true;
|
||||
|
||||
/* Handle return value */
|
||||
if (block_dst->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, block_dst->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block_dst);
|
||||
ADD_TO_RETURN_PHI(block_dst, value_ret);
|
||||
}
|
||||
|
||||
/* Jump to the end block */
|
||||
BUILD_BR(block_dst->llvm_end_block);
|
||||
}
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 br_depth, uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block_dst;
|
||||
LLVMValueRef value_cmp, value_ret;
|
||||
LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
|
||||
char name[32];
|
||||
|
||||
POP_COND(value_cmp);
|
||||
if (!LLVMIsConstant(value_cmp)) {
|
||||
/* Compare value is not constant, create condition br IR */
|
||||
if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create llvm else block */
|
||||
CREATE_BLOCK(llvm_else_block, "br_if_else");
|
||||
MOVE_BLOCK_AFTER_CURR(llvm_else_block);
|
||||
|
||||
if (block_dst->block_type == BLOCK_TYPE_LOOP) {
|
||||
/* Dest block is Loop block */
|
||||
BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
|
||||
llvm_else_block);
|
||||
|
||||
/* Move builder to else block */
|
||||
SET_BUILDER_POS(llvm_else_block);
|
||||
}
|
||||
else {
|
||||
/* Dest block is Block/If/Function block */
|
||||
/* Create the end block */
|
||||
if (!block_dst->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block_dst->block_index, block_dst->block_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(block_dst->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
|
||||
MOVE_BLOCK_BEFORE(block_dst->llvm_end_block,
|
||||
next_llvm_end_block);
|
||||
}
|
||||
|
||||
/* Set reachable flag and create condtion br IR */
|
||||
block_dst->is_reachable = true;
|
||||
|
||||
/* Handle return value */
|
||||
if (block_dst->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, block_dst->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block_dst);
|
||||
ADD_TO_RETURN_PHI(block_dst, value_ret);
|
||||
PUSH(value_ret, block_dst->return_type);
|
||||
}
|
||||
|
||||
/* Condition jump to end block */
|
||||
BUILD_COND_BR(value_cmp, block_dst->llvm_end_block,
|
||||
llvm_else_block);
|
||||
|
||||
/* Move builder to else block */
|
||||
SET_BUILDER_POS(llvm_else_block);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
|
||||
/* Compare value is not 0, condtion is true, same as op_br */
|
||||
return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
|
||||
}
|
||||
else {
|
||||
/* Compare value is not 0, condtion is false, skip br_if */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 *br_depths, uint32 br_count,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
uint32 i;
|
||||
LLVMValueRef value_switch, value_cmp, value_case, value_ret = NULL;
|
||||
LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
AOTBlock *target_block;
|
||||
uint32 br_depth, depth_idx;
|
||||
char name[32];
|
||||
|
||||
POP_I32(value_cmp);
|
||||
if (!LLVMIsConstant(value_cmp)) {
|
||||
/* Compare value is not constant, create switch IR */
|
||||
for (i = 0; i <= br_count; i++) {
|
||||
target_block = get_target_block(func_ctx, br_depths[i]);
|
||||
if (!target_block)
|
||||
return false;
|
||||
|
||||
if (target_block->block_type != BLOCK_TYPE_LOOP) {
|
||||
/* Dest block is Block/If/Function block */
|
||||
/* Create the end block */
|
||||
if (!target_block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
target_block->block_index,
|
||||
target_block->block_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(target_block->llvm_end_block, name);
|
||||
if ((next_llvm_end_block =
|
||||
find_next_llvm_end_block(target_block)))
|
||||
MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
|
||||
next_llvm_end_block);
|
||||
}
|
||||
/* Handle return value */
|
||||
if (target_block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, target_block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(target_block);
|
||||
ADD_TO_RETURN_PHI(target_block, value_ret);
|
||||
PUSH(value_ret, target_block->return_type);
|
||||
}
|
||||
target_block->is_reachable = true;
|
||||
if (i == br_count)
|
||||
default_llvm_block = target_block->llvm_end_block;
|
||||
}
|
||||
else {
|
||||
if (i == br_count)
|
||||
default_llvm_block = target_block->llvm_entry_block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create switch IR */
|
||||
if (!(value_switch = LLVMBuildSwitch(comp_ctx->builder, value_cmp,
|
||||
default_llvm_block, br_count))) {
|
||||
aot_set_last_error("llvm build switch failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add each case for switch IR */
|
||||
for (i = 0; i < br_count; i++) {
|
||||
value_case = I32_CONST(i);
|
||||
CHECK_LLVM_CONST(value_case);
|
||||
target_block = get_target_block(func_ctx, br_depths[i]);
|
||||
if (!target_block)
|
||||
return false;
|
||||
target_llvm_block = target_block->block_type != BLOCK_TYPE_LOOP
|
||||
? target_block->llvm_end_block
|
||||
: target_block->llvm_entry_block;
|
||||
LLVMAddCase(value_switch, value_case, target_llvm_block);
|
||||
}
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
}
|
||||
else {
|
||||
/* Compare value is constant, create br IR */
|
||||
depth_idx = (uint32)LLVMConstIntGetZExtValue(value_cmp);
|
||||
br_depth = br_depths[br_count];
|
||||
if (depth_idx < br_count) {
|
||||
br_depth = br_depths[depth_idx];
|
||||
}
|
||||
return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
|
||||
}
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block_func = func_ctx->block_stack.block_list_head;
|
||||
LLVMValueRef value;
|
||||
|
||||
bh_assert(block_func);
|
||||
if (block_func->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block_func->return_type);
|
||||
LLVMBuildRet(comp_ctx->builder, value);
|
||||
}
|
||||
else
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_unreachable(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE,
|
||||
false, NULL, NULL))
|
||||
return false;
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
}
|
||||
60
core/iwasm/compilation/aot_emit_control.h
Normal file
60
core/iwasm/compilation/aot_emit_control.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_CONTROL_H_
|
||||
#define _AOT_EMIT_CONTROL_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip, uint8 *frame_ip_end,
|
||||
uint32 block_type, uint32 block_ret_type);
|
||||
|
||||
bool
|
||||
aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 br_depth, uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 br_depth, uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 *br_depths, uint32 br_count,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_unreachable(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_CONTROL_H_ */
|
||||
|
||||
432
core/iwasm/compilation/aot_emit_conversion.c
Normal file
432
core/iwasm/compilation/aot_emit_conversion.c
Normal file
@ -0,0 +1,432 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_conversion.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "aot_emit_numberic.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef operand, LLVMTypeRef dest_type,
|
||||
LLVMValueRef min_value, LLVMValueRef max_value,
|
||||
char *name, bool sign)
|
||||
{
|
||||
LLVMBasicBlockRef check_nan_succ, check_overflow_succ;
|
||||
LLVMValueRef is_less, is_greater, res;
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
|
||||
operand, operand, "fcmp_is_nan"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(check_nan_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_nan_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_nan_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
true, res, check_nan_succ)))
|
||||
goto fail;
|
||||
|
||||
if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
|
||||
min_value, "fcmp_min_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
|
||||
max_value, "fcmp_max_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(res = LLVMBuildOr(comp_ctx->builder, is_less, is_greater, "is_overflow"))) {
|
||||
aot_set_last_error("llvm build logic and failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check if float value out of range */
|
||||
if (!(check_overflow_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_overflow_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_overflow_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
|
||||
true, res, check_overflow_succ)))
|
||||
goto fail;
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
|
||||
else
|
||||
res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dest_type == I32_TYPE)
|
||||
PUSH_I32(res);
|
||||
else if (dest_type == I64_TYPE)
|
||||
PUSH_I64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (!(res = LLVMBuildTrunc(comp_ctx->builder, value, I32_TYPE, "i32_wrap_i64"))) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
||||
POP_F32(value);
|
||||
|
||||
if (sign) {
|
||||
min_value = F32_CONST(-2147483904.0f);
|
||||
max_value = F32_CONST(2147483648.0f);
|
||||
}
|
||||
else {
|
||||
min_value = F32_CONST(-1.0f);
|
||||
max_value = F32_CONST(4294967296.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
||||
POP_F64(value);
|
||||
|
||||
if (sign) {
|
||||
min_value = F64_CONST(-2147483649.0);
|
||||
max_value = F64_CONST(2147483648.0);
|
||||
}
|
||||
else {
|
||||
min_value = F64_CONST(-1.0);
|
||||
max_value = F64_CONST(4294967296.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildSExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_s");
|
||||
else
|
||||
res = LLVMBuildZExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_u");
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
||||
POP_F32(value);
|
||||
|
||||
if (sign) {
|
||||
min_value = F32_CONST(-9223373136366403584.0f);
|
||||
max_value = F32_CONST(9223372036854775808.0f);
|
||||
}
|
||||
else {
|
||||
min_value = F32_CONST(-1.0f);
|
||||
max_value = F32_CONST(18446744073709551616.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
||||
POP_F64(value);
|
||||
|
||||
if (sign) {
|
||||
min_value = F64_CONST(-9223372036854777856.0);
|
||||
max_value = F64_CONST(9223372036854775808.0);
|
||||
}
|
||||
else {
|
||||
min_value = F64_CONST(-1.0);
|
||||
max_value = F64_CONST(18446744073709551616.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_s");
|
||||
else
|
||||
res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_u");
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_s");
|
||||
else
|
||||
res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_u");
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_F64(value);
|
||||
|
||||
if (!(res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE, "f32_demote_f64"))) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_s");
|
||||
else
|
||||
res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_u");
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (sign)
|
||||
res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_s");
|
||||
else
|
||||
res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_u");
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value, res;
|
||||
|
||||
POP_F32(value);
|
||||
|
||||
if (!(res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE, "f64_promote_f32"))) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_F64(res);
|
||||
|
||||
/* Avoid the promote being optimized away */
|
||||
PUSH_F64(F64_CONST(1.0));
|
||||
return aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_MUL);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
POP_F64(value);
|
||||
if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
|
||||
I64_TYPE, "i64"))) {
|
||||
aot_set_last_error("llvm build fp to si failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_I64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
POP_F32(value);
|
||||
if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
|
||||
I32_TYPE, "i32"))) {
|
||||
aot_set_last_error("llvm build fp to si failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_I32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
POP_I64(value);
|
||||
if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
|
||||
F64_TYPE, "f64"))) {
|
||||
aot_set_last_error("llvm build si to fp failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_F64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
POP_I32(value);
|
||||
if (!(value = LLVMBuildBitCast(comp_ctx->builder, value,
|
||||
F32_TYPE, "f32"))) {
|
||||
aot_set_last_error("llvm build si to fp failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH_F32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
81
core/iwasm/compilation/aot_emit_conversion.h
Normal file
81
core/iwasm/compilation/aot_emit_conversion.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_CONVERSION_H_
|
||||
#define _AOT_EMIT_CONVERSION_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_CONVERSION_H_ */
|
||||
|
||||
184
core/iwasm/compilation/aot_emit_exception.c
Normal file
184
core/iwasm/compilation/aot_emit_exception.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
static char *exce_block_names[] = {
|
||||
"exce_unreachable", /* EXCE_UNREACHABLE */
|
||||
"exce_out_of_memory", /* EXCE_OUT_OF_MEMORY */
|
||||
"exce_out_of_bounds_mem_access",/* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
|
||||
"exce_integer_overflow", /* EXCE_INTEGER_OVERFLOW */
|
||||
"exce_divide_by_zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */
|
||||
"exce_invalid_convert_to_int", /* EXCE_INVALID_CONVERSION_TO_INTEGER */
|
||||
"exce_invalid_func_type_idx", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
|
||||
"exce_invalid_func_idx", /* EXCE_INVALID_FUNCTION_INDEX */
|
||||
"exce_undefined_element", /* EXCE_UNDEFINED_ELEMENT */
|
||||
"exce_uninit_element", /* EXCE_UNINITIALIZED_ELEMENT */
|
||||
"exce_call_unlinked" /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
};
|
||||
|
||||
bool
|
||||
aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int32 exception_id,
|
||||
bool is_cond_br,
|
||||
LLVMValueRef cond_br_if,
|
||||
LLVMBasicBlockRef cond_br_else_block)
|
||||
{
|
||||
LLVMBasicBlockRef exce_block;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMValueRef exce_id = I32_CONST((uint32)exception_id), func_const, func;
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef param_values[2];
|
||||
|
||||
bh_assert(exception_id >= 0 && exception_id < EXCE_NUM);
|
||||
|
||||
CHECK_LLVM_CONST(exce_id);
|
||||
|
||||
/* Create got_exception block if needed */
|
||||
if (!func_ctx->got_exception_block) {
|
||||
if (!(func_ctx->got_exception_block =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"got_exception"))) {
|
||||
aot_set_last_error("add LLVM basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder,
|
||||
func_ctx->got_exception_block);
|
||||
|
||||
/* Create exection id phi */
|
||||
if (!(func_ctx->exception_id_phi =
|
||||
LLVMBuildPhi(comp_ctx->builder,
|
||||
comp_ctx->basic_types.int32_type,
|
||||
"exception_id_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Call aot_set_exception_with_id() to throw exception */
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
/* Create function type */
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types,
|
||||
2, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
/* Create function type */
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
/* Create LLVM function with const function pointer */
|
||||
if (!(func_const =
|
||||
I64_CONST((uint64)(uintptr_t)aot_set_exception_with_id))
|
||||
|| !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Create LLVM function with external function pointer */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module,
|
||||
"aot_set_exception_with_id"))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
"aot_set_exception_with_id",
|
||||
func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the aot_set_exception_with_id() function */
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
param_values[1] = func_ctx->exception_id_phi;
|
||||
if (!LLVMBuildCall(comp_ctx->builder, func, param_values,
|
||||
2, "")) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create return IR */
|
||||
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
|
||||
if (aot_func_type->result_count) {
|
||||
switch (aot_func_type->types[aot_func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
LLVMBuildRet(comp_ctx->builder, I32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
LLVMBuildRet(comp_ctx->builder, I64_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
LLVMBuildRet(comp_ctx->builder, F32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
LLVMBuildRet(comp_ctx->builder, F64_ZERO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
}
|
||||
|
||||
/* Resume the builder position */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
}
|
||||
|
||||
/* Create exception block if needed */
|
||||
if (!(exce_block = func_ctx->exception_blocks[exception_id])) {
|
||||
if (!(func_ctx->exception_blocks[exception_id] = exce_block =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
exce_block_names[exception_id]))) {
|
||||
aot_set_last_error("add LLVM basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Move before got_exception block */
|
||||
LLVMMoveBasicBlockBefore(exce_block, func_ctx->got_exception_block);
|
||||
|
||||
/* Add phi incoming value to got_exception block */
|
||||
LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &exce_block, 1);
|
||||
|
||||
/* Jump to got exception block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, exce_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume builder position */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
|
||||
if (!is_cond_br) {
|
||||
/* not condition br, create br IR */
|
||||
if (!LLVMBuildBr(comp_ctx->builder, exce_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Create condition br */
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if,
|
||||
exce_block, cond_br_else_block)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
return false;
|
||||
}
|
||||
/* Start to translate the else block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, cond_br_else_block);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
27
core/iwasm/compilation/aot_emit_exception.h
Normal file
27
core/iwasm/compilation/aot_emit_exception.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_EXCEPTION_H_
|
||||
#define _AOT_EMIT_EXCEPTION_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int32 exception_id,
|
||||
bool is_cond_br,
|
||||
LLVMValueRef cond_br_if,
|
||||
LLVMBasicBlockRef cond_br_else_block);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_EXCEPTION_H_ */
|
||||
|
||||
548
core/iwasm/compilation/aot_emit_function.c
Normal file
548
core/iwasm/compilation/aot_emit_function.c
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_function.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "aot_emit_control.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
/* Check whether there was exception thrown, if yes, return directly */
|
||||
static bool
|
||||
check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
|
||||
LLVMBasicBlockRef block_curr, check_exce_succ;
|
||||
LLVMValueRef value, cmp;
|
||||
|
||||
/* Load the first byte of aot_module_inst->cur_exception, and check
|
||||
whether it is '\0'. If yes, no exception was thrown. */
|
||||
if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
|
||||
"exce_value"))
|
||||
|| !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
|
||||
value, I8_ZERO, "cmp"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add check exection success block */
|
||||
if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_exce_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
|
||||
|
||||
/* Create function return block if it isn't created */
|
||||
if (!func_ctx->func_return_block) {
|
||||
if (!(func_ctx->func_return_block =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"func_ret"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create return IR */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block);
|
||||
if (aot_func_type->result_count) {
|
||||
switch (aot_func_type->types[aot_func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
LLVMBuildRet(comp_ctx->builder, I32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
LLVMBuildRet(comp_ctx->builder, I64_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
LLVMBuildRet(comp_ctx->builder, F32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
LLVMBuildRet(comp_ctx->builder, F64_ZERO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
}
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
/* Create condition br */
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
|
||||
check_exce_succ, func_ctx->func_return_block)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_exce_succ);
|
||||
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;
|
||||
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;
|
||||
int32 i, j = 0, param_count;
|
||||
void *func_ptr;
|
||||
uint64 total_size;
|
||||
bool ret = false;
|
||||
|
||||
/* Check function index */
|
||||
if (func_idx >= import_func_count + func_count) {
|
||||
aot_set_last_error("Function index out of range.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get function type */
|
||||
if (func_idx < import_func_count)
|
||||
func_type = import_funcs[func_idx].func_type;
|
||||
else
|
||||
func_type = func_ctxes[func_idx - import_func_count]->
|
||||
aot_func->func_type;
|
||||
|
||||
/* Allocate memory for parameters */
|
||||
param_count = (int32)func_type->param_count;
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_values = wasm_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("Allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First parameter is exec env */
|
||||
param_values[j++] = func_ctx->exec_env;
|
||||
|
||||
/* Pop parameters from stack */
|
||||
for (i = param_count - 1; i >= 0; i--)
|
||||
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;
|
||||
|
||||
/* Initialize parameter types of the LLVM function */
|
||||
total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_types = wasm_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("Allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
param_types[j++] = comp_ctx->exec_env_type;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Load function pointer */
|
||||
if (!(value = I32_CONST(func_idx))
|
||||
|| !(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->func_ptrs,
|
||||
&value, 1, "func_ptr"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check whether import function is NULL */
|
||||
if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Throw exception if import function is NULL */
|
||||
if (!(check_func_ptr_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_func_ptr_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_func_ptr_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
true, cmp, check_func_ptr_succ)))
|
||||
goto fail;
|
||||
|
||||
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
|
||||
f_ptr_type, "func"))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, (uint32)param_count + 1,
|
||||
(func_type->result_count > 0
|
||||
? "call" : "")))) {
|
||||
aot_set_last_error("LLVM build call failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* 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]);
|
||||
|
||||
/* Check whether there was exception thrown when executing the function */
|
||||
if (!check_exception_thrown(comp_ctx, func_ctx))
|
||||
goto fail;
|
||||
|
||||
ret = true;
|
||||
fail:
|
||||
if (param_types)
|
||||
wasm_free(param_types);
|
||||
if (param_values)
|
||||
wasm_free(param_values);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 type_idx)
|
||||
{
|
||||
AOTFuncType *func_type;
|
||||
LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx;
|
||||
LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch;
|
||||
LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr;
|
||||
LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret;
|
||||
LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type,
|
||||
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";
|
||||
|
||||
/* Check function type index */
|
||||
if (type_idx >= comp_ctx->comp_data->func_type_count) {
|
||||
aot_set_last_error("type index is overflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
func_type = comp_ctx->comp_data->func_types[type_idx];
|
||||
|
||||
POP_I32(elem_idx);
|
||||
|
||||
table_size_const = I32_CONST(comp_ctx->comp_data->table_size);
|
||||
CHECK_LLVM_CONST(table_size_const);
|
||||
|
||||
/* Check if (uint32)elem index >= table size */
|
||||
if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE,
|
||||
elem_idx, table_size_const,
|
||||
"cmp_elem_idx"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Throw exception if elem index >= table size */
|
||||
if (!(check_elem_idx_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_elem_idx_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_elem_idx_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT,
|
||||
true, cmp_elem_idx, check_elem_idx_succ)))
|
||||
goto fail;
|
||||
|
||||
/* Load function index */
|
||||
if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->table_base,
|
||||
&elem_idx, 1, "table_elem"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check if func_idx == -1 */
|
||||
if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
|
||||
func_idx, I32_NEG_ONE,
|
||||
"cmp_func_idx"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Throw exception if func_idx == -1 */
|
||||
if (!(check_func_idx_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_func_idx_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_func_idx_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT,
|
||||
true, cmp_func_idx, check_func_idx_succ)))
|
||||
goto fail;
|
||||
|
||||
/* Load function type index */
|
||||
if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->func_type_indexes,
|
||||
&func_idx, 1,
|
||||
"ftype_idx_ptr"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr,
|
||||
"ftype_idx"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Call aot_is_type_equal() to check whether function type match */
|
||||
param_types_tmp[0] = INT8_PTR_TYPE;
|
||||
param_types_tmp[1] = I32_TYPE;
|
||||
param_types_tmp[2] = I32_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
/* Create function type */
|
||||
if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp,
|
||||
3, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
/* Create function type */
|
||||
if (!(f_ptr_type = LLVMPointerType(f_type, 0))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
goto fail;
|
||||
}
|
||||
/* Create LLVM function with const function pointer */
|
||||
if (!(func_const =
|
||||
I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
|
||||
|| !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Create LLVM function with external function pointer */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the aot_is_type_equal() function */
|
||||
param_values_tmp[0] = func_ctx->aot_inst;
|
||||
param_values_tmp[1] = I32_CONST(type_idx);
|
||||
param_values_tmp[2] = ftype_idx;
|
||||
|
||||
CHECK_LLVM_CONST(param_values_tmp[1]);
|
||||
|
||||
if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values_tmp, 3,
|
||||
"is_ftype_match"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
|
||||
is_ftype_match, I8_ZERO,
|
||||
"is_ftype_mismatch"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(check_ftype_idx_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_ftype_idx_success"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_ftype_idx_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX,
|
||||
true, is_ftype_mismatch, check_ftype_idx_succ)))
|
||||
goto fail;
|
||||
|
||||
/* Load function pointer */
|
||||
if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
|
||||
&func_idx, 1, "func_ptr"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check whether import function is NULL */
|
||||
if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
|
||||
aot_set_last_error("llvm build is null 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_func_ptr, check_func_ptr_succ)))
|
||||
goto fail;
|
||||
|
||||
/* Initialize parameter types of the LLVM function */
|
||||
param_count = (int32)func_type->param_count;
|
||||
total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_types = wasm_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("Allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
param_types[j++] = comp_ctx->exec_env_type;
|
||||
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 (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
|
||||
f_ptr_type, "func"))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Allocate memory for parameters */
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_values = wasm_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("Allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* First parameter is exec env */
|
||||
j = 0;
|
||||
param_values[j++] = func_ctx->exec_env;
|
||||
|
||||
/* Pop parameters from stack */
|
||||
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.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (func_type->result_count > 0)
|
||||
PUSH(value_ret, func_type->types[func_type->param_count]);
|
||||
|
||||
/* Check whether there was exception thrown when executing the function */
|
||||
if (!check_exception_thrown(comp_ctx, func_ctx))
|
||||
goto fail;
|
||||
|
||||
ret = true;
|
||||
|
||||
fail:
|
||||
if (param_values)
|
||||
wasm_free(param_values);
|
||||
if (param_types)
|
||||
wasm_free(param_types);
|
||||
return ret;
|
||||
}
|
||||
|
||||
28
core/iwasm/compilation/aot_emit_function.h
Normal file
28
core/iwasm/compilation/aot_emit_function.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_FUNCTION_H_
|
||||
#define _AOT_EMIT_FUNCTION_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 func_idx, uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 type_idx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_FUNCTION_H_ */
|
||||
|
||||
662
core/iwasm/compilation/aot_emit_memory.c
Normal file
662
core/iwasm/compilation/aot_emit_memory.c
Normal file
@ -0,0 +1,662 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_memory.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
#define BUILD_ICMP(op, left, right, res, name) do { \
|
||||
if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \
|
||||
left, right, name))) { \
|
||||
aot_set_last_error("llvm build icmp failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_OP(Op, left, right, res, name) do { \
|
||||
if (!(res = LLVMBuild##Op(comp_ctx->builder, \
|
||||
left, right, name))) { \
|
||||
aot_set_last_error("llvm build " #Op " fail."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_COND_BR(cmp_val, then_block, else_block) do { \
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cmp_val, \
|
||||
then_block, else_block)) { \
|
||||
aot_set_last_error("llvm build cond br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
aot_set_last_error("llvm add basic block failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SET_BUILD_POS(block) \
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block)
|
||||
|
||||
static LLVMValueRef
|
||||
check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 offset, uint32 bytes)
|
||||
{
|
||||
LLVMValueRef offset_const = I32_CONST(offset);
|
||||
LLVMValueRef size_const = I32_CONST(bytes);
|
||||
LLVMValueRef addr, maddr, moffset;
|
||||
LLVMValueRef cmp, phi;
|
||||
LLVMValueRef mem_base_addr, mem_data_size;
|
||||
LLVMValueRef heap_base_addr, heap_base_offset;
|
||||
LLVMValueRef mem_offset_max = NULL, heap_offset_max = NULL;
|
||||
LLVMBasicBlockRef check_mem_space, check_heap_space, check_succ;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
|
||||
CHECK_LLVM_CONST(offset_const);
|
||||
CHECK_LLVM_CONST(size_const);
|
||||
|
||||
heap_base_addr = func_ctx->heap_base_addr;
|
||||
heap_base_offset = func_ctx->heap_base_offset;
|
||||
|
||||
POP_I32(addr);
|
||||
BUILD_OP(Add, offset_const, addr, moffset, "moffset");
|
||||
|
||||
/* return addres directly if constant offset and inside memory space */
|
||||
if (LLVMIsConstant(moffset)) {
|
||||
uint32 memory_offset = (uint32)LLVMConstIntGetZExtValue(moffset);
|
||||
uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count;
|
||||
if (init_page_count > 0
|
||||
&& memory_offset <= NumBytesPerPage * init_page_count - bytes) {
|
||||
/* inside memory space */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_base_addr,
|
||||
"mem_base"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_base_addr = func_ctx->mem_base_addr;
|
||||
}
|
||||
|
||||
/* maddr = mem_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
mem_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
return maddr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(check_heap_space, "check_heap_space");
|
||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_heap_space, block_curr);
|
||||
LLVMMoveBasicBlockAfter(check_succ, check_heap_space);
|
||||
|
||||
/* Add return maddress phi for check_succ block */
|
||||
SET_BUILD_POS(check_succ);
|
||||
if (!(phi = LLVMBuildPhi(comp_ctx->builder,
|
||||
INT8_PTR_TYPE, "maddr_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(block_curr);
|
||||
|
||||
/* Get memory data size */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_data_size = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_data_size,
|
||||
"mem_data_size"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_data_size = func_ctx->mem_data_size;
|
||||
}
|
||||
|
||||
if (comp_ctx->comp_data->mem_init_page_count == 0) {
|
||||
ADD_BASIC_BLOCK(check_mem_space, "check_mem_space");
|
||||
LLVMMoveBasicBlockAfter(check_mem_space, block_curr);
|
||||
|
||||
/* if mem_data_size is zero, check heap space */
|
||||
BUILD_ICMP(LLVMIntEQ, mem_data_size, I32_ZERO, cmp,
|
||||
"cmp_mem_data_size");
|
||||
BUILD_COND_BR(cmp, check_heap_space, check_mem_space);
|
||||
SET_BUILD_POS(check_mem_space);
|
||||
}
|
||||
|
||||
/* Get memory base address */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_base_addr,
|
||||
"mem_base"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_base_addr = func_ctx->mem_base_addr;
|
||||
}
|
||||
|
||||
/* maddr = mem_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(phi, &maddr, &block_curr, 1);
|
||||
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
/* mem_offset_max = mem_data_size - bytes to load/read */
|
||||
if (!(mem_offset_max = LLVMBuildSub(comp_ctx->builder,
|
||||
mem_data_size, size_const,
|
||||
"mem_offset_max"))) {
|
||||
aot_set_last_error("llvm build sub failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bytes == 1)
|
||||
mem_offset_max = func_ctx->mem_bound_1_byte;
|
||||
else if (bytes == 2)
|
||||
mem_offset_max = func_ctx->mem_bound_2_bytes;
|
||||
else if (bytes == 4)
|
||||
mem_offset_max = func_ctx->mem_bound_4_bytes;
|
||||
else if (bytes == 8)
|
||||
mem_offset_max = func_ctx->mem_bound_8_bytes;
|
||||
}
|
||||
|
||||
/* in linear memory if (uint32)moffset <= (uint32)mem_offset_max,
|
||||
else check heap space */
|
||||
BUILD_ICMP(LLVMIntULE, moffset, mem_offset_max, cmp, "cmp_mem_offset");
|
||||
|
||||
/* Create condtion br */
|
||||
BUILD_COND_BR(cmp, check_succ, check_heap_space);
|
||||
|
||||
/* Start to translate the check_heap_space block */
|
||||
SET_BUILD_POS(check_heap_space);
|
||||
|
||||
/* moffset -= heap_base_offset */
|
||||
if (!(moffset = LLVMBuildSub(comp_ctx->builder,
|
||||
moffset, heap_base_offset,
|
||||
"moffset_to_heap"))) {
|
||||
aot_set_last_error("llvm build sub failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* maddr = heap_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, heap_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(phi, &maddr, &block_curr, 1);
|
||||
|
||||
/* heap space base addr and size is unchanged,
|
||||
the heap boundary is unchanged also. */
|
||||
if (bytes == 1)
|
||||
heap_offset_max = func_ctx->heap_bound_1_byte;
|
||||
else if (bytes == 2)
|
||||
heap_offset_max = func_ctx->heap_bound_2_bytes;
|
||||
else if (bytes == 4)
|
||||
heap_offset_max = func_ctx->heap_bound_4_bytes;
|
||||
else if (bytes == 8)
|
||||
heap_offset_max = func_ctx->heap_bound_8_bytes;
|
||||
|
||||
/* in heap space if (uint32)moffset <= (uint32)heap_offset_max,
|
||||
else throw exception */
|
||||
BUILD_ICMP(LLVMIntUGT, moffset, heap_offset_max, cmp, "cmp_heap_offset");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
true, cmp, check_succ))
|
||||
goto fail;
|
||||
|
||||
SET_BUILD_POS(check_succ);
|
||||
return phi;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define BUILD_PTR_CAST(ptr_type) do { \
|
||||
if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr,\
|
||||
ptr_type, "data_ptr"))) {\
|
||||
aot_set_last_error("llvm build bit cast failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_LOAD() do { \
|
||||
if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, \
|
||||
"data"))) { \
|
||||
aot_set_last_error("llvm build load failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_TRUNC(data_type) do { \
|
||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, \
|
||||
data_type, "val_trunc"))){ \
|
||||
aot_set_last_error("llvm build trunc failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_STORE() do { \
|
||||
if (!LLVMBuildStore(comp_ctx->builder, value, maddr)) { \
|
||||
aot_set_last_error("llvm build store failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_SIGN_EXT(dst_type) do { \
|
||||
if (!(value = LLVMBuildSExt(comp_ctx->builder, value, \
|
||||
dst_type, "data_s_ext"))) { \
|
||||
aot_set_last_error("llvm build sign ext failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_ZERO_EXT(dst_type) do { \
|
||||
if (!(value = LLVMBuildZExt(comp_ctx->builder, value, \
|
||||
dst_type, "data_z_ext"))) { \
|
||||
aot_set_last_error("llvm build zero ext failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign)
|
||||
{
|
||||
LLVMValueRef maddr, value = NULL;
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
|
||||
return false;
|
||||
|
||||
switch (bytes) {
|
||||
case 4:
|
||||
BUILD_PTR_CAST(INT32_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
if (bytes == 2)
|
||||
BUILD_PTR_CAST(INT16_PTR_TYPE);
|
||||
else
|
||||
BUILD_PTR_CAST(INT8_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
if (sign)
|
||||
BUILD_SIGN_EXT(I32_TYPE);
|
||||
else
|
||||
BUILD_ZERO_EXT(I32_TYPE);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
PUSH_I32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign)
|
||||
{
|
||||
LLVMValueRef maddr, value = NULL;
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
|
||||
return false;
|
||||
|
||||
switch (bytes) {
|
||||
case 8:
|
||||
BUILD_PTR_CAST(INT64_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
break;
|
||||
case 4:
|
||||
case 2:
|
||||
case 1:
|
||||
if (bytes == 4)
|
||||
BUILD_PTR_CAST(INT32_PTR_TYPE);
|
||||
else if (bytes == 2)
|
||||
BUILD_PTR_CAST(INT16_PTR_TYPE);
|
||||
else
|
||||
BUILD_PTR_CAST(INT8_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
if (sign)
|
||||
BUILD_SIGN_EXT(I64_TYPE);
|
||||
else
|
||||
BUILD_ZERO_EXT(I64_TYPE);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
PUSH_I64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
|
||||
return false;
|
||||
|
||||
BUILD_PTR_CAST(F32_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
PUSH_F32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
|
||||
return false;
|
||||
|
||||
BUILD_PTR_CAST(F64_PTR_TYPE);
|
||||
BUILD_LOAD();
|
||||
PUSH_F64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
|
||||
return false;
|
||||
|
||||
switch (bytes) {
|
||||
case 4:
|
||||
BUILD_PTR_CAST(INT32_PTR_TYPE);
|
||||
break;
|
||||
case 2:
|
||||
BUILD_PTR_CAST(INT16_PTR_TYPE);
|
||||
BUILD_TRUNC(INT16_TYPE);
|
||||
break;
|
||||
case 1:
|
||||
BUILD_PTR_CAST(INT8_PTR_TYPE);
|
||||
BUILD_TRUNC(INT8_TYPE);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
BUILD_STORE();
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
|
||||
return false;
|
||||
|
||||
switch (bytes) {
|
||||
case 8:
|
||||
BUILD_PTR_CAST(INT64_PTR_TYPE);
|
||||
break;
|
||||
case 4:
|
||||
BUILD_PTR_CAST(INT32_PTR_TYPE);
|
||||
BUILD_TRUNC(I32_TYPE);
|
||||
break;
|
||||
case 2:
|
||||
BUILD_PTR_CAST(INT16_PTR_TYPE);
|
||||
BUILD_TRUNC(INT16_TYPE);
|
||||
break;
|
||||
case 1:
|
||||
BUILD_PTR_CAST(INT8_PTR_TYPE);
|
||||
BUILD_TRUNC(INT8_TYPE);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
BUILD_STORE();
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
POP_F32(value);
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
|
||||
return false;
|
||||
|
||||
BUILD_PTR_CAST(F32_PTR_TYPE);
|
||||
BUILD_STORE();
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset)
|
||||
{
|
||||
LLVMValueRef maddr, value;
|
||||
|
||||
POP_F64(value);
|
||||
|
||||
if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
|
||||
return false;
|
||||
|
||||
BUILD_PTR_CAST(F64_PTR_TYPE);
|
||||
BUILD_STORE();
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
get_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
uint32 offset = offsetof(AOTModuleInstance, mem_cur_page_count);
|
||||
LLVMValueRef mem_size_offset, mem_size_ptr, mem_size;
|
||||
|
||||
/* mem_size_offset = aot_inst + offset */
|
||||
mem_size_offset = I32_CONST(offset);
|
||||
CHECK_LLVM_CONST(mem_size_offset);
|
||||
if (!(mem_size_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->aot_inst,
|
||||
&mem_size_offset, 1,
|
||||
"mem_size_ptr_tmp"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* cast to int32* */
|
||||
if (!(mem_size_ptr = LLVMBuildBitCast(comp_ctx->builder, mem_size_ptr,
|
||||
INT32_PTR_TYPE, "mem_size_ptr"))) {
|
||||
aot_set_last_error("llvm build bitcast failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* load memory size, or current page count */
|
||||
if (!(mem_size = LLVMBuildLoad(comp_ctx->builder,
|
||||
mem_size_ptr, "mem_size"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mem_size;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
|
||||
|
||||
if (mem_size)
|
||||
PUSH_I32(mem_size);
|
||||
return mem_size ? true : false;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
|
||||
LLVMValueRef delta, param_values[2], ret_value, func, value;
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
|
||||
if (!mem_size)
|
||||
return false;
|
||||
|
||||
POP_I32(delta);
|
||||
|
||||
/* Function type of wasm_runtime_enlarge_memory() */
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_enlarge_memory))
|
||||
|| !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *func_name = "wasm_runtime_enlarge_memory";
|
||||
/* AOT mode, delcare the function */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
func_name, func_type))) {
|
||||
aot_set_last_error("llvm add function failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call function wasm_runtime_enlarge_memory() */
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
param_values[1] = delta;
|
||||
if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
|
||||
param_values, 2, "call"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* convert call result from i8 to i1 */
|
||||
if (!(ret_value = LLVMBuildIntCast(comp_ctx->builder, ret_value,
|
||||
INT1_TYPE, "mem_grow_ret"))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ret_value = ret_value == true ? delta : pre_page_count */
|
||||
if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value,
|
||||
mem_size, I32_NEG_ONE,
|
||||
"mem_grow_ret"))) {
|
||||
aot_set_last_error("llvm build select failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I32(ret_value);
|
||||
|
||||
/* To be simple, call wasm_runtime_set_exception() no matter
|
||||
enlarge success or not */
|
||||
param_types[1] = VOID_PTR_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_set_exception))
|
||||
|| !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *func_name = "wasm_runtime_set_exception";
|
||||
/* AOT mode, delcare the function */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
func_name, func_type))) {
|
||||
aot_set_last_error("llvm add function failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call function wasm_runtime_set_exception(aot_inst, NULL) */
|
||||
param_values[1] = LLVMConstNull(VOID_PTR_TYPE);
|
||||
CHECK_LLVM_CONST(param_values[1]);
|
||||
if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
58
core/iwasm/compilation/aot_emit_memory.h
Normal file
58
core/iwasm/compilation/aot_emit_memory.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_MEMORY_H_
|
||||
#define _AOT_EMIT_MEMORY_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_MEMORY_H_ */
|
||||
|
||||
1175
core/iwasm/compilation/aot_emit_numberic.c
Normal file
1175
core/iwasm/compilation/aot_emit_numberic.c
Normal file
File diff suppressed because it is too large
Load Diff
84
core/iwasm/compilation/aot_emit_numberic.h
Normal file
84
core/iwasm/compilation/aot_emit_numberic.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_NUMBERIC_H_
|
||||
#define _AOT_EMIT_NUMBERIC_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntArithmetic arith_op, uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntArithmetic arith_op, uint8 **p_frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntBitwise bitwise_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntBitwise bitwise_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatMath math_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatMath math_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_f64_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_NUMBERIC_H_ */
|
||||
|
||||
102
core/iwasm/compilation/aot_emit_parametric.c
Normal file
102
core/iwasm/compilation/aot_emit_parametric.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_parametric.h"
|
||||
|
||||
static bool
|
||||
pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef *p_value,
|
||||
bool is_32, uint8 *p_type)
|
||||
{
|
||||
AOTValue *aot_value;
|
||||
uint8 type;
|
||||
|
||||
if (!func_ctx->block_stack.block_list_end) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return false;
|
||||
}
|
||||
if (!func_ctx->block_stack.block_list_end->value_stack.value_list_end) {
|
||||
aot_set_last_error("WASM data stack underflow.");
|
||||
return false;
|
||||
}
|
||||
|
||||
aot_value = aot_value_stack_pop
|
||||
(&func_ctx->block_stack.block_list_end->value_stack);
|
||||
type = aot_value->type;
|
||||
|
||||
if (aot_value->type == VALUE_TYPE_I1) {
|
||||
if (!(aot_value->value =
|
||||
LLVMBuildZExt(comp_ctx->builder, aot_value->value,
|
||||
I32_TYPE, "val_s_ext"))) {
|
||||
aot_set_last_error("llvm build sign ext failed.");
|
||||
return false;
|
||||
}
|
||||
type = aot_value->type = VALUE_TYPE_I32;
|
||||
}
|
||||
|
||||
if (p_type != NULL) {
|
||||
*p_type = aot_value->type;
|
||||
}
|
||||
if (p_value != NULL) {
|
||||
*p_value = aot_value->value;
|
||||
}
|
||||
|
||||
wasm_free(aot_value);
|
||||
|
||||
if ((is_32
|
||||
&& (type != VALUE_TYPE_I32 && type != VALUE_TYPE_F32))
|
||||
|| (!is_32
|
||||
&& (type != VALUE_TYPE_I64 && type != VALUE_TYPE_F64))) {
|
||||
aot_set_last_error("invalid WASM stack data type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool is_drop_32)
|
||||
{
|
||||
if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, NULL, is_drop_32, NULL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool is_select_32)
|
||||
{
|
||||
LLVMValueRef val1, val2, cond, selected;
|
||||
uint8 val1_type, val2_type;
|
||||
|
||||
POP_COND(cond);
|
||||
|
||||
if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, &val2, is_select_32, &val2_type)
|
||||
|| !pop_value_from_wasm_stack(comp_ctx, func_ctx, &val1, is_select_32, &val1_type))
|
||||
return false;
|
||||
|
||||
if (val1_type != val2_type) {
|
||||
aot_set_last_error("invalid stack values with different type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(selected = LLVMBuildSelect(comp_ctx->builder,
|
||||
cond, val1, val2,
|
||||
"select"))) {
|
||||
aot_set_last_error("llvm build select failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH(selected, val1_type);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
29
core/iwasm/compilation/aot_emit_parametric.h
Normal file
29
core/iwasm/compilation/aot_emit_parametric.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_PARAMETRIC_H_
|
||||
#define _AOT_EMIT_PARAMETRIC_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool is_drop_32);
|
||||
|
||||
bool
|
||||
aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool is_select_32);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_PARAMETRIC_H_ */
|
||||
|
||||
193
core/iwasm/compilation/aot_emit_variable.c
Normal file
193
core/iwasm/compilation/aot_emit_variable.c
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_variable.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
#define CHECK_LOCAL(idx) do { \
|
||||
if (idx >= func_ctx->aot_func->func_type->param_count \
|
||||
+ func_ctx->aot_func->local_count) { \
|
||||
aot_set_last_error("local index out of range"); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static uint8
|
||||
get_local_type(AOTFuncContext *func_ctx, uint32 local_idx)
|
||||
{
|
||||
AOTFunc *aot_func = func_ctx->aot_func;
|
||||
uint32 param_count = aot_func->func_type->param_count;
|
||||
return local_idx < param_count
|
||||
? aot_func->func_type->types[local_idx]
|
||||
: aot_func->local_types[local_idx - param_count];
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx)
|
||||
{
|
||||
char name[32];
|
||||
LLVMValueRef value;
|
||||
|
||||
CHECK_LOCAL(local_idx);
|
||||
|
||||
snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#");
|
||||
if (!(value = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->locals[local_idx],
|
||||
name))) {
|
||||
aot_set_last_error("llvm build load fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH(value, get_local_type(func_ctx, local_idx));
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
|
||||
CHECK_LOCAL(local_idx);
|
||||
|
||||
POP(value, get_local_type(func_ctx, local_idx));
|
||||
|
||||
if (!LLVMBuildStore(comp_ctx->builder,
|
||||
value,
|
||||
func_ctx->locals[local_idx])) {
|
||||
aot_set_last_error("llvm build store fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
uint8 type;
|
||||
|
||||
CHECK_LOCAL(local_idx);
|
||||
|
||||
type = get_local_type(func_ctx, local_idx);
|
||||
|
||||
POP(value, type);
|
||||
|
||||
if (!LLVMBuildStore(comp_ctx->builder,
|
||||
value,
|
||||
func_ctx->locals[local_idx])) {
|
||||
aot_set_last_error("llvm build store fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH(value, type);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx, bool is_set)
|
||||
{
|
||||
AOTCompData *comp_data = comp_ctx->comp_data;
|
||||
uint32 import_global_count = comp_data->import_global_count;
|
||||
uint32 global_base_offset = offsetof(AOTModuleInstance,
|
||||
global_table_heap_data.bytes);
|
||||
uint32 global_offset;
|
||||
uint8 global_type;
|
||||
LLVMValueRef offset, global_ptr, global;
|
||||
LLVMTypeRef ptr_type = NULL;
|
||||
|
||||
bh_assert(global_idx < import_global_count + comp_data->global_count);
|
||||
|
||||
if (global_idx < import_global_count) {
|
||||
global_offset = global_base_offset
|
||||
+ comp_data->import_globals[global_idx].data_offset;
|
||||
global_type = comp_data->import_globals[global_idx].type;
|
||||
}
|
||||
else {
|
||||
global_offset = global_base_offset
|
||||
+ comp_data->globals[global_idx - import_global_count].data_offset;
|
||||
global_type =
|
||||
comp_data->globals[global_idx - import_global_count].type;
|
||||
}
|
||||
|
||||
offset = I32_CONST(global_offset);
|
||||
if (!(global_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "global_ptr_tmp"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (global_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
ptr_type = comp_ctx->basic_types.int32_ptr_type;
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
ptr_type = comp_ctx->basic_types.int64_ptr_type;
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
ptr_type = comp_ctx->basic_types.float32_ptr_type;
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
ptr_type = comp_ctx->basic_types.float64_ptr_type;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr,
|
||||
ptr_type, "global_ptr"))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_set) {
|
||||
if (!(global = LLVMBuildLoad(comp_ctx->builder,
|
||||
global_ptr, "global"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
PUSH(global, global_type);
|
||||
}
|
||||
else {
|
||||
POP(global, global_type);
|
||||
if (!LLVMBuildStore(comp_ctx->builder, global, global_ptr)) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx)
|
||||
{
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, false);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx)
|
||||
{
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, true);
|
||||
}
|
||||
|
||||
40
core/iwasm/compilation/aot_emit_variable.h
Normal file
40
core/iwasm/compilation/aot_emit_variable.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_VARIABLE_H_
|
||||
#define _AOT_EMIT_VARIABLE_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 local_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EMIT_VARIABLE_H_ */
|
||||
|
||||
1230
core/iwasm/compilation/aot_llvm.c
Normal file
1230
core/iwasm/compilation/aot_llvm.c
Normal file
File diff suppressed because it is too large
Load Diff
270
core/iwasm/compilation/aot_llvm.h
Normal file
270
core/iwasm/compilation/aot_llvm.h
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_LLVM_H_
|
||||
#define _AOT_LLVM_H_
|
||||
|
||||
#include "aot.h"
|
||||
#include "llvm-c/Types.h"
|
||||
#include "llvm-c/Target.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/Object.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Analysis.h"
|
||||
#include "llvm-c/Transforms/Scalar.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Value in the WASM operation stack, each stack element
|
||||
* is an LLVM value
|
||||
*/
|
||||
typedef struct AOTValue {
|
||||
struct AOTValue *next;
|
||||
struct AOTValue *prev;
|
||||
LLVMValueRef value;
|
||||
/* VALUE_TYPE_I32/I64/F32/F64/VOID */
|
||||
uint8 type;
|
||||
} AOTValue;
|
||||
|
||||
/**
|
||||
* Value stack, represents stack elements in a WASM block
|
||||
*/
|
||||
typedef struct AOTValueStack {
|
||||
AOTValue *value_list_head;
|
||||
AOTValue *value_list_end;
|
||||
} AOTValueStack;
|
||||
|
||||
typedef struct AOTBlock {
|
||||
struct AOTBlock *next;
|
||||
struct AOTBlock *prev;
|
||||
|
||||
/* Block index */
|
||||
uint32 block_index;
|
||||
/* BLOCK_TYPE_BLOCK/LOOP/IF/FUNCTION */
|
||||
uint32 block_type;
|
||||
/* VALUE_TYPE_I32/I64/F32/F64/VOID */
|
||||
uint8 return_type;
|
||||
/* Whether it is reachable */
|
||||
bool is_reachable;
|
||||
/* Whether skip translation of wasm else branch */
|
||||
bool skip_wasm_code_else;
|
||||
|
||||
/* code of else opcode of this block, if it is a IF block */
|
||||
uint8 *wasm_code_else;
|
||||
/* code end of this block */
|
||||
uint8 *wasm_code_end;
|
||||
|
||||
/* LLVM label points to code begin */
|
||||
LLVMBasicBlockRef llvm_entry_block;
|
||||
/* LLVM label points to code else */
|
||||
LLVMBasicBlockRef llvm_else_block;
|
||||
/* LLVM label points to code end */
|
||||
LLVMBasicBlockRef llvm_end_block;
|
||||
|
||||
/* WASM operation stack */
|
||||
AOTValueStack value_stack;
|
||||
|
||||
/* Return value of this block, a PHI node */
|
||||
LLVMValueRef return_value_phi;
|
||||
} AOTBlock;
|
||||
|
||||
/**
|
||||
* Block stack, represents WASM block stack elements
|
||||
*/
|
||||
typedef struct AOTBlockStack {
|
||||
AOTBlock *block_list_head;
|
||||
AOTBlock *block_list_end;
|
||||
/* Current block index of each block type */
|
||||
uint32 block_index[3];
|
||||
} AOTBlockStack;
|
||||
|
||||
typedef struct AOTFuncContext {
|
||||
AOTFunc *aot_func;
|
||||
LLVMValueRef func;
|
||||
AOTBlockStack block_stack;
|
||||
|
||||
LLVMValueRef exec_env;
|
||||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef table_base;
|
||||
|
||||
LLVMValueRef mem_data_size;
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef mem_bound_1_byte;
|
||||
LLVMValueRef mem_bound_2_bytes;
|
||||
LLVMValueRef mem_bound_4_bytes;
|
||||
LLVMValueRef mem_bound_8_bytes;
|
||||
|
||||
LLVMValueRef heap_base_offset;
|
||||
LLVMValueRef heap_base_addr;
|
||||
LLVMValueRef heap_data_size;
|
||||
LLVMValueRef heap_bound_1_byte;
|
||||
LLVMValueRef heap_bound_2_bytes;
|
||||
LLVMValueRef heap_bound_4_bytes;
|
||||
LLVMValueRef heap_bound_8_bytes;
|
||||
|
||||
LLVMValueRef cur_exception;
|
||||
|
||||
bool mem_space_unchanged;
|
||||
|
||||
LLVMBasicBlockRef *exception_blocks;
|
||||
LLVMBasicBlockRef got_exception_block;
|
||||
LLVMBasicBlockRef func_return_block;
|
||||
LLVMValueRef exception_id_phi;
|
||||
LLVMValueRef func_ptrs;
|
||||
LLVMValueRef func_type_indexes;
|
||||
LLVMValueRef locals[1];
|
||||
} AOTFuncContext;
|
||||
|
||||
typedef struct AOTLLVMTypes {
|
||||
LLVMTypeRef int1_type;
|
||||
LLVMTypeRef int8_type;
|
||||
LLVMTypeRef int16_type;
|
||||
LLVMTypeRef int32_type;
|
||||
LLVMTypeRef int64_type;
|
||||
LLVMTypeRef float32_type;
|
||||
LLVMTypeRef float64_type;
|
||||
LLVMTypeRef void_type;
|
||||
|
||||
LLVMTypeRef int8_ptr_type;
|
||||
LLVMTypeRef int16_ptr_type;
|
||||
LLVMTypeRef int32_ptr_type;
|
||||
LLVMTypeRef int64_ptr_type;
|
||||
LLVMTypeRef float32_ptr_type;
|
||||
LLVMTypeRef float64_ptr_type;
|
||||
LLVMTypeRef void_ptr_type;
|
||||
|
||||
LLVMTypeRef meta_data_type;
|
||||
} AOTLLVMTypes;
|
||||
|
||||
typedef struct AOTLLVMConsts {
|
||||
LLVMValueRef i8_zero;
|
||||
LLVMValueRef i32_zero;
|
||||
LLVMValueRef i64_zero;
|
||||
LLVMValueRef f32_zero;
|
||||
LLVMValueRef f64_zero;
|
||||
LLVMValueRef i32_one;
|
||||
LLVMValueRef i32_two;
|
||||
LLVMValueRef i32_four;
|
||||
LLVMValueRef i32_eight;
|
||||
LLVMValueRef i32_neg_one;
|
||||
LLVMValueRef i64_neg_one;
|
||||
LLVMValueRef i32_min;
|
||||
LLVMValueRef i64_min;
|
||||
LLVMValueRef i32_31;
|
||||
LLVMValueRef i32_32;
|
||||
LLVMValueRef i64_63;
|
||||
LLVMValueRef i64_64;
|
||||
} AOTLLVMConsts;
|
||||
|
||||
/**
|
||||
* Compiler context
|
||||
*/
|
||||
typedef struct AOTCompContext {
|
||||
AOTCompData *comp_data;
|
||||
|
||||
/* LLVM variables required to emit LLVM IR */
|
||||
LLVMContextRef context;
|
||||
LLVMModuleRef module;
|
||||
LLVMBuilderRef builder;
|
||||
LLVMTargetMachineRef target_machine;
|
||||
char *target_cpu;
|
||||
char target_arch[16];
|
||||
|
||||
/* LLVM execution engine required by JIT */
|
||||
LLVMExecutionEngineRef exec_engine;
|
||||
bool is_jit_mode;
|
||||
|
||||
/* Whether optimize the JITed code */
|
||||
bool optimize;
|
||||
|
||||
/* LLVM pass manager to optimize the JITed code */
|
||||
LLVMPassManagerRef pass_mgr;
|
||||
|
||||
/* LLVM floating-point rounding mode metadata */
|
||||
LLVMValueRef fp_rounding_mode;
|
||||
|
||||
/* LLVM floating-point exception behavior metadata */
|
||||
LLVMValueRef fp_exception_behavior;
|
||||
|
||||
/* LLVM data types */
|
||||
AOTLLVMTypes basic_types;
|
||||
LLVMTypeRef exec_env_type;
|
||||
LLVMTypeRef aot_inst_type;
|
||||
|
||||
/* LLVM const values */
|
||||
AOTLLVMConsts llvm_consts;
|
||||
|
||||
/* Function contexts */
|
||||
AOTFuncContext **func_ctxes;
|
||||
uint32 func_ctx_count;
|
||||
} AOTCompContext;
|
||||
|
||||
enum {
|
||||
AOT_FORMAT_FILE,
|
||||
AOT_OBJECT_FILE,
|
||||
AOT_LLVMIR_UNOPT_FILE,
|
||||
AOT_LLVMIR_OPT_FILE,
|
||||
};
|
||||
|
||||
typedef struct AOTCompOption{
|
||||
bool is_jit_mode;
|
||||
char *target_arch;
|
||||
char *target_abi;
|
||||
char *target_cpu;
|
||||
char *cpu_features;
|
||||
uint32 opt_level;
|
||||
uint32 output_format;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
AOTCompContext *
|
||||
aot_create_comp_context(AOTCompData *comp_data,
|
||||
aot_comp_option_t option);
|
||||
|
||||
void
|
||||
aot_destroy_comp_context(AOTCompContext *comp_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_wasm(AOTCompContext *comp_ctx);
|
||||
|
||||
uint8*
|
||||
aot_emit_elf_file(AOTCompContext *comp_ctx, uint32 *p_elf_file_size);
|
||||
|
||||
void
|
||||
aot_destroy_elf_file(uint8 *elf_file);
|
||||
|
||||
void
|
||||
aot_value_stack_push(AOTValueStack *stack, AOTValue *value);
|
||||
|
||||
AOTValue *
|
||||
aot_value_stack_pop(AOTValueStack *stack);
|
||||
|
||||
void
|
||||
aot_value_stack_destroy(AOTValueStack *stack);
|
||||
|
||||
void
|
||||
aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block);
|
||||
|
||||
AOTBlock *
|
||||
aot_block_stack_pop(AOTBlockStack *stack);
|
||||
|
||||
void
|
||||
aot_block_stack_destroy(AOTBlockStack *stack);
|
||||
|
||||
void
|
||||
aot_block_destroy(AOTBlock *block);
|
||||
|
||||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_LLVM_H_ */
|
||||
|
||||
8
core/iwasm/compilation/iwasm_compl.cmake
Normal file
8
core/iwasm/compilation/iwasm_compl.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${IWASM_COMPL_DIR})
|
||||
|
||||
file (GLOB_RECURSE source_all ${IWASM_COMPL_DIR}/*.c)
|
||||
|
||||
set (IWASM_COMPL_SOURCE ${source_all})
|
||||
|
||||
80
core/iwasm/include/aot_export.h
Normal file
80
core/iwasm/include/aot_export.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EXPORT_H
|
||||
#define _AOT_EXPORT_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AOTCompData;
|
||||
typedef struct AOTCompData *aot_comp_data_t;
|
||||
|
||||
struct AOTCompContext;
|
||||
typedef struct AOTCompContext *aot_comp_context_t;
|
||||
|
||||
aot_comp_data_t
|
||||
aot_create_comp_data(void *wasm_module);
|
||||
|
||||
void
|
||||
aot_destroy_comp_data(aot_comp_data_t comp_data);
|
||||
|
||||
enum {
|
||||
AOT_FORMAT_FILE,
|
||||
AOT_OBJECT_FILE,
|
||||
AOT_LLVMIR_UNOPT_FILE,
|
||||
AOT_LLVMIR_OPT_FILE,
|
||||
};
|
||||
|
||||
typedef struct AOTCompOption{
|
||||
bool is_jit_mode;
|
||||
char *target_arch;
|
||||
char *target_abi;
|
||||
char *target_cpu;
|
||||
char *cpu_features;
|
||||
uint32_t opt_level;
|
||||
uint32_t output_format;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
aot_comp_context_t
|
||||
aot_create_comp_context(aot_comp_data_t comp_data,
|
||||
aot_comp_option_t option);
|
||||
|
||||
void
|
||||
aot_destroy_comp_context(aot_comp_context_t comp_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_wasm(aot_comp_context_t comp_ctx);
|
||||
|
||||
bool
|
||||
aot_emit_llvm_file(aot_comp_context_t comp_ctx, const char *file_name);
|
||||
|
||||
bool
|
||||
aot_emit_object_file(aot_comp_context_t comp_ctx, const char *file_name);
|
||||
|
||||
bool
|
||||
aot_emit_aot_file(aot_comp_context_t comp_ctx,
|
||||
aot_comp_data_t comp_data,
|
||||
const char *file_name);
|
||||
|
||||
void
|
||||
aot_destroy_aot_file(uint8_t *aot_file);
|
||||
|
||||
char*
|
||||
aot_get_last_error();
|
||||
|
||||
uint32_t
|
||||
aot_get_plt_table_size();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _AOT_EXPORT_H */
|
||||
@ -14,17 +14,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Uninstantiated WASM module loaded from WASM binary file */
|
||||
struct WASMModule;
|
||||
typedef struct WASMModule *wasm_module_t;
|
||||
/* Uninstantiated WASM module loaded from WASM binary file
|
||||
or AoT binary file*/
|
||||
struct WASMModuleCommon;
|
||||
typedef struct WASMModuleCommon *wasm_module_t;
|
||||
|
||||
/* Instantiated WASM module */
|
||||
struct WASMModuleInstance;
|
||||
typedef struct WASMModuleInstance *wasm_module_inst_t;
|
||||
struct WASMModuleInstanceCommon;
|
||||
typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
|
||||
|
||||
/* Function instance */
|
||||
struct WASMFunctionInstance;
|
||||
typedef struct WASMFunctionInstance *wasm_function_inst_t;
|
||||
struct WASMFunctionInstanceCommon;
|
||||
typedef struct WASMFunctionInstanceCommon *wasm_function_inst_t;
|
||||
|
||||
/* WASM section */
|
||||
typedef struct wasm_section {
|
||||
@ -37,11 +38,11 @@ typedef struct wasm_section {
|
||||
uint32_t section_body_size;
|
||||
} wasm_section_t, *wasm_section_list_t;
|
||||
|
||||
typedef wasm_section_t aot_section_t, *aot_section_list_t;
|
||||
|
||||
/* Execution environment, e.g. stack info */
|
||||
typedef struct WASMExecEnv {
|
||||
uint8_t *stack;
|
||||
uint32_t stack_size;
|
||||
} *wasm_exec_env_t;
|
||||
struct WASMExecEnv;
|
||||
typedef struct WASMExecEnv *wasm_exec_env_t;
|
||||
|
||||
/* Package Type */
|
||||
typedef enum {
|
||||
@ -90,16 +91,17 @@ wasm_runtime_load(const uint8_t *buf, uint32_t size,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
/**
|
||||
* Load a WASM module from a specified WASM section list.
|
||||
* Load a WASM module from a specified WASM or AOT section list.
|
||||
*
|
||||
* @param section_list the section list which contains each section data
|
||||
* @param is_aot whether the section list is AOT section list
|
||||
* @param error_buf output of the exception info
|
||||
* @param error_buf_size the size of the exception string
|
||||
*
|
||||
* @return return WASM module loaded, NULL if failed
|
||||
*/
|
||||
wasm_module_t
|
||||
wasm_runtime_load_from_sections(wasm_section_list_t section_list,
|
||||
wasm_runtime_load_from_sections(wasm_section_list_t section_list, bool is_aot,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
/**
|
||||
@ -110,14 +112,12 @@ wasm_runtime_load_from_sections(wasm_section_list_t section_list,
|
||||
void
|
||||
wasm_runtime_unload(wasm_module_t module);
|
||||
|
||||
#if WASM_ENABLE_WASI != 0
|
||||
void
|
||||
wasm_runtime_set_wasi_args(wasm_module_t module,
|
||||
const char *dir_list[], uint32_t dir_count,
|
||||
const char *map_dir_list[], uint32_t map_dir_count,
|
||||
const char *env[], uint32_t env_count,
|
||||
char *argv[], int argc);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Instantiate a WASM module.
|
||||
@ -150,31 +150,11 @@ wasm_runtime_instantiate(const wasm_module_t module,
|
||||
void
|
||||
wasm_runtime_deinstantiate(wasm_module_inst_t module_inst);
|
||||
|
||||
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
|
||||
bool
|
||||
wasm_runtime_set_ext_memory(wasm_module_inst_t module_inst,
|
||||
uint8_t *ext_mem_data, uint32_t ext_mem_size,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
#endif
|
||||
wasm_runtime_is_wasi_mode(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* Load WASM module instance from AOT file.
|
||||
*
|
||||
* @param aot_file the AOT file of a WASM module
|
||||
* @param aot_file_size the AOT file size
|
||||
* @param heap_size the default heap size of the module instance, a heap will
|
||||
* be created besides the app memory space. Both wasm app and native
|
||||
* function can allocate memory from the heap. If heap_size is 0, the
|
||||
* default heap size will be used.
|
||||
* @param error_buf buffer to output the error info if failed
|
||||
* @param error_buf_size the size of the error buffer
|
||||
*
|
||||
* @return the instantiated WASM module instance, NULL if failed
|
||||
*/
|
||||
wasm_module_inst_t
|
||||
wasm_runtime_load_aot(uint8_t *aot_file, uint32_t aot_file_size,
|
||||
uint32_t heap_size,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
wasm_function_inst_t
|
||||
wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* Lookup an exported function in the WASM module instance.
|
||||
@ -184,22 +164,23 @@ wasm_runtime_load_aot(uint8_t *aot_file, uint32_t aot_file_size,
|
||||
* @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"
|
||||
*
|
||||
* @return the function instance found, if the module instance is loaded from
|
||||
* the AOT file, the return value is the function pointer
|
||||
* @return the function instance found
|
||||
*/
|
||||
wasm_function_inst_t
|
||||
wasm_runtime_lookup_function(const wasm_module_inst_t module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
/**
|
||||
* Create execution environment.
|
||||
* Create execution environment for a WASM module instance.
|
||||
*
|
||||
* @param module_inst the module instance
|
||||
* @param stack_size the stack size to execute a WASM function
|
||||
*
|
||||
* @return the execution environment
|
||||
*/
|
||||
wasm_exec_env_t
|
||||
wasm_runtime_create_exec_env(uint32_t stack_size);
|
||||
wasm_runtime_create_exec_env(wasm_module_inst_t module_inst,
|
||||
uint32_t stack_size);
|
||||
|
||||
/**
|
||||
* Destroy the execution environment.
|
||||
@ -207,17 +188,24 @@ wasm_runtime_create_exec_env(uint32_t stack_size);
|
||||
* @param env the execution environment to destroy
|
||||
*/
|
||||
void
|
||||
wasm_runtime_destroy_exec_env(wasm_exec_env_t env);
|
||||
wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
|
||||
|
||||
/**
|
||||
* Get WASM module instance from execution environment
|
||||
*
|
||||
* @param exec_env the execution environment to retrieve
|
||||
*
|
||||
* @return the WASM module instance
|
||||
*/
|
||||
wasm_module_inst_t
|
||||
wasm_runtime_get_module_inst(wasm_exec_env_t exec_env);
|
||||
|
||||
/**
|
||||
* Call the given WASM function of a WASM module instance with
|
||||
* arguments (bytecode and AoT).
|
||||
*
|
||||
* @param module_inst the WASM module instance which the function belongs to
|
||||
* @param exec_env the execution environment to call the function. If the module
|
||||
* instance is created by AoT mode, it is ignored and just set it to NULL.
|
||||
* If the module instance is created by bytecode mode and it is NULL,
|
||||
* a temporary env object will be created
|
||||
* @param exec_env the execution environment to call the function
|
||||
* which must be created from wasm_create_exec_env()
|
||||
* @param function the function to be called
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments. If the function method has return value,
|
||||
@ -229,11 +217,40 @@ wasm_runtime_destroy_exec_env(wasm_exec_env_t env);
|
||||
* the caller can call wasm_runtime_get_exception to get exception info.
|
||||
*/
|
||||
bool
|
||||
wasm_runtime_call_wasm(wasm_module_inst_t module_inst,
|
||||
wasm_exec_env_t exec_env,
|
||||
wasm_runtime_call_wasm(wasm_exec_env_t exec_env,
|
||||
wasm_function_inst_t function,
|
||||
uint32_t argc, uint32_t argv[]);
|
||||
|
||||
/**
|
||||
* Find the unique main function from a WASM module instance
|
||||
* and execute that function.
|
||||
*
|
||||
* @param module_inst the WASM module instance
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments array
|
||||
*
|
||||
* @return true if the main function is called, false otherwise and exception will be thrown,
|
||||
* the caller can call wasm_runtime_get_exception to get exception info.
|
||||
*/
|
||||
bool
|
||||
wasm_application_execute_main(wasm_module_inst_t module_inst,
|
||||
int32_t argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Find the specified function in argv[0] from a WASM module instance
|
||||
* and execute that function.
|
||||
*
|
||||
* @param module_inst the WASM module instance
|
||||
* @param name the name of the function to execute
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments array
|
||||
*
|
||||
* @return true if the specified function is called, false otherwise and exception will be thrown,
|
||||
* the caller can call wasm_runtime_get_exception to get exception info.
|
||||
*/
|
||||
bool
|
||||
wasm_application_execute_func(wasm_module_inst_t module_inst,
|
||||
const char *name, int32_t argc, char *argv[]);
|
||||
/**
|
||||
* Get exception info of the WASM module instance.
|
||||
*
|
||||
@ -241,7 +258,7 @@ wasm_runtime_call_wasm(wasm_module_inst_t module_inst,
|
||||
*
|
||||
* @return the exception string
|
||||
*/
|
||||
const char*
|
||||
const char *
|
||||
wasm_runtime_get_exception(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
@ -268,7 +285,7 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst,
|
||||
*
|
||||
* @return the custom data (NULL if not set yet)
|
||||
*/
|
||||
void*
|
||||
void *
|
||||
wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
@ -367,7 +384,7 @@ wasm_runtime_validate_native_addr(wasm_module_inst_t module_inst,
|
||||
*
|
||||
* @return the native address converted
|
||||
*/
|
||||
void *
|
||||
void*
|
||||
wasm_runtime_addr_app_to_native(wasm_module_inst_t module_inst,
|
||||
int32_t app_offset);
|
||||
|
||||
13
core/iwasm/interpreter/iwasm_interp.cmake
Normal file
13
core/iwasm/interpreter/iwasm_interp.cmake
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
set (IWASM_INTERP_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
add_definitions (-DWASM_ENABLE_INTERP=1)
|
||||
|
||||
include_directories(${IWASM_INTERP_DIR})
|
||||
|
||||
file (GLOB_RECURSE source_all ${IWASM_INTERP_DIR}/*.c)
|
||||
|
||||
set (IWASM_INTERP_SOURCE ${source_all})
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
#define _WASM_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "wasm_hashmap.h"
|
||||
#include "wasm_assert.h"
|
||||
#include "bh_hashmap.h"
|
||||
#include "bh_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -19,7 +19,9 @@ extern "C" {
|
||||
#define VALUE_TYPE_I64 0X7E
|
||||
#define VALUE_TYPE_F32 0x7D
|
||||
#define VALUE_TYPE_F64 0x7C
|
||||
#define VALUE_TYPE_VOID 0x00
|
||||
#define VALUE_TYPE_VOID 0x40
|
||||
/* Used by AOT */
|
||||
#define VALUE_TYPE_I1 0x41
|
||||
|
||||
/* Table Element Type */
|
||||
#define TABLE_ELEM_TYPE_ANY_FUNC 0x70
|
||||
@ -171,6 +173,11 @@ typedef struct WASMFunction {
|
||||
uint8 *local_types;
|
||||
uint32 max_stack_cell_num;
|
||||
uint32 max_block_num;
|
||||
/* Whether function has opcode memory.grow */
|
||||
bool has_op_memory_grow;
|
||||
/* Whether function has opcode call or
|
||||
call_indirect */
|
||||
bool has_op_func_call;
|
||||
uint32 code_size;
|
||||
uint8 *code;
|
||||
} WASMFunction;
|
||||
@ -210,7 +217,7 @@ typedef struct BlockAddr {
|
||||
#define BLOCK_ADDR_CACHE_SIZE 64
|
||||
#define BLOCK_ADDR_CONFLICT_SIZE 4
|
||||
|
||||
#if WASM_ENABLE_WASI != 0
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
typedef struct WASIArguments {
|
||||
const char **dir_list;
|
||||
uint32 dir_count;
|
||||
@ -224,6 +231,13 @@ typedef struct WASIArguments {
|
||||
#endif
|
||||
|
||||
typedef struct WASMModule {
|
||||
/* Module type, for module loaded from WASM bytecode binary,
|
||||
this field is Wasm_Module_Bytecode;
|
||||
for module loaded from AOT file, this field is
|
||||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModule structure. */
|
||||
uint32 module_type;
|
||||
|
||||
uint32 type_count;
|
||||
uint32 import_count;
|
||||
uint32 function_count;
|
||||
@ -255,10 +269,14 @@ typedef struct WASMModule {
|
||||
WASMDataSeg **data_segments;
|
||||
uint32 start_function;
|
||||
|
||||
/* Whether there is possible memory grow, e.g.
|
||||
memory.grow opcode or call enlargeMemory */
|
||||
bool possible_memory_grow;
|
||||
|
||||
HashMap *const_str_set;
|
||||
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
|
||||
|
||||
#if WASM_ENABLE_WASI != 0
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIArguments wasi_args;
|
||||
bool is_wasi_module;
|
||||
#endif
|
||||
@ -272,16 +290,6 @@ typedef struct WASMBranchBlock {
|
||||
uint32 *frame_sp;
|
||||
} WASMBranchBlock;
|
||||
|
||||
typedef struct WASMSection {
|
||||
struct WASMSection *next;
|
||||
/* section type */
|
||||
int section_type;
|
||||
/* section body, not include type and size */
|
||||
const uint8_t *section_body;
|
||||
/* section body size */
|
||||
uint32_t section_body_size;
|
||||
} WASMSection;
|
||||
|
||||
/* Execution environment, e.g. stack info */
|
||||
/**
|
||||
* Align an unsigned value on a alignment boundary.
|
||||
@ -337,7 +345,7 @@ wasm_value_type_size(uint8 value_type)
|
||||
case VALUE_TYPE_F64:
|
||||
return sizeof(int64);
|
||||
default:
|
||||
wasm_assert(0);
|
||||
bh_assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -353,7 +361,7 @@ wasm_value_type_cell_num(uint8 value_type)
|
||||
case VALUE_TYPE_F64:
|
||||
return 2;
|
||||
default:
|
||||
wasm_assert(0);
|
||||
bh_assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -4,12 +4,12 @@
|
||||
*/
|
||||
|
||||
#include "wasm_interp.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_log.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
|
||||
typedef int32 CellType_I32;
|
||||
typedef int64 CellType_I64;
|
||||
@ -224,24 +224,6 @@ LOAD_I16(void *addr)
|
||||
|
||||
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
|
||||
|
||||
#if WASM_ENABLE_EXT_MEMORY_SPACE != 0
|
||||
#define CHECK_EXT_MEMORY_SPACE() \
|
||||
else if (module->ext_mem_data \
|
||||
&& module->ext_mem_base_offset <= offset1 \
|
||||
&& offset1 < module->ext_mem_base_offset \
|
||||
+ module->ext_mem_size) { \
|
||||
/* If offset1 is in valid range, maddr must also be in valid range, \
|
||||
no need to check it again. */ \
|
||||
maddr = module->ext_mem_data \
|
||||
+ (offset1 - module->ext_mem_base_offset); \
|
||||
if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > \
|
||||
module->ext_mem_data_end) \
|
||||
goto out_of_bounds; \
|
||||
}
|
||||
#else
|
||||
#define CHECK_EXT_MEMORY_SPACE()
|
||||
#endif
|
||||
|
||||
#define CHECK_MEMORY_OVERFLOW() do { \
|
||||
uint32 offset1 = offset + addr; \
|
||||
/* if (flags != 2) \
|
||||
@ -265,7 +247,6 @@ LOAD_I16(void *addr)
|
||||
if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->heap_data_end) \
|
||||
goto out_of_bounds; \
|
||||
} \
|
||||
CHECK_EXT_MEMORY_SPACE() \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
@ -442,7 +423,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
} while (0)
|
||||
|
||||
#define PUSH_CSP(type, ret_type, start, else_, end) do {\
|
||||
wasm_assert(frame_csp < frame->csp_boundary); \
|
||||
bh_assert(frame_csp < frame->csp_boundary); \
|
||||
frame_csp->block_type = type; \
|
||||
frame_csp->return_type = ret_type; \
|
||||
frame_csp->start_addr = start; \
|
||||
@ -460,7 +441,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
#define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp))
|
||||
|
||||
#define POP_CSP_CHECK_OVERFLOW(n) do { \
|
||||
wasm_assert(frame_csp - n >= frame->csp_bottom); \
|
||||
bh_assert(frame_csp - n >= frame->csp_bottom); \
|
||||
} while (0)
|
||||
|
||||
#define POP_CSP() do { \
|
||||
@ -566,7 +547,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
cur_func = frame->function; \
|
||||
prev_frame = frame->prev_frame; \
|
||||
frame_ip = frame->ip; \
|
||||
frame_ip_end = wasm_runtime_get_func_code_end(cur_func); \
|
||||
frame_ip_end = wasm_get_func_code_end(cur_func); \
|
||||
frame_lp = frame->lp; \
|
||||
frame_sp = frame->sp; \
|
||||
frame_csp = frame->csp; \
|
||||
@ -650,6 +631,22 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) do { \
|
||||
frame_sp -= sizeof(src_type2)/sizeof(uint32); \
|
||||
*(src_type1*)(frame_sp - sizeof(src_type1)/sizeof(uint32)) operation##= \
|
||||
(*(src_type2*)(frame_sp) % 32); \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) do { \
|
||||
src_type1 val1; \
|
||||
src_type2 val2; \
|
||||
frame_sp -= 2; \
|
||||
val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \
|
||||
val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \
|
||||
val1 operation##= (val2 % 64); \
|
||||
PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \
|
||||
} while (0)
|
||||
|
||||
#define DEF_OP_MATH(src_type, src_op_type, method) do { \
|
||||
src_type val; \
|
||||
val = POP_##src_op_type(); \
|
||||
@ -660,12 +657,11 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
min_cond, max_cond) do { \
|
||||
src_type value = POP_##src_op_type(); \
|
||||
if (isnan(value)) { \
|
||||
wasm_runtime_set_exception(module, \
|
||||
"invalid conversion to integer"); \
|
||||
wasm_set_exception(module, "invalid conversion to integer"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
else if (value min_cond || value max_cond) { \
|
||||
wasm_runtime_set_exception(module, "integer overflow"); \
|
||||
wasm_set_exception(module, "integer overflow"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
PUSH_##dst_op_type(((dst_type)value)); \
|
||||
@ -680,7 +676,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||
#define GET_LOCAL_INDEX_AND_TYPE() do { \
|
||||
uint32 param_count = cur_func->param_count; \
|
||||
read_leb_uint32(frame_ip, frame_ip_end, local_idx); \
|
||||
wasm_assert(local_idx < param_count + cur_func->local_count); \
|
||||
bh_assert(local_idx < param_count + cur_func->local_count); \
|
||||
if (local_idx < param_count) \
|
||||
local_type = cur_func->param_types[local_idx]; \
|
||||
else \
|
||||
@ -735,28 +731,29 @@ word_copy(uint32 *dest, uint32 *src, unsigned num)
|
||||
}
|
||||
|
||||
static inline WASMInterpFrame*
|
||||
ALLOC_FRAME(WASMThread *self, uint32 size, WASMInterpFrame *prev_frame)
|
||||
ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMInterpFrame *frame = wasm_thread_alloc_wasm_frame(self, size);
|
||||
WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size);
|
||||
|
||||
if (frame)
|
||||
frame->prev_frame = prev_frame;
|
||||
else {
|
||||
wasm_runtime_set_exception(self->module_inst,
|
||||
"WASM interp failed: stack overflow.");
|
||||
wasm_set_exception((WASMModuleInstance*)exec_env->module_inst,
|
||||
"WASM interp failed: stack overflow.");
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static inline void
|
||||
FREE_FRAME(WASMThread *self, WASMInterpFrame *frame)
|
||||
FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame)
|
||||
{
|
||||
wasm_thread_free_wasm_frame(self, frame);
|
||||
wasm_exec_env_free_wasm_frame(exec_env, frame);
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_interp_call_func_native(WASMThread *self,
|
||||
wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
@ -765,15 +762,16 @@ wasm_interp_call_func_native(WASMThread *self,
|
||||
uint32 argv_ret[2];
|
||||
bool ret;
|
||||
|
||||
if (!(frame = ALLOC_FRAME
|
||||
(self, wasm_interp_interp_frame_size(local_cell_num), prev_frame)))
|
||||
if (!(frame = ALLOC_FRAME(exec_env,
|
||||
wasm_interp_interp_frame_size(local_cell_num),
|
||||
prev_frame)))
|
||||
return;
|
||||
|
||||
frame->function = cur_func;
|
||||
frame->ip = NULL;
|
||||
frame->sp = frame->lp + local_cell_num;
|
||||
|
||||
wasm_thread_set_cur_frame (self, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
if (!cur_func->u.func_import->func_ptr_linked) {
|
||||
char buf[128];
|
||||
@ -781,13 +779,13 @@ wasm_interp_call_func_native(WASMThread *self,
|
||||
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_runtime_set_exception(self->module_inst, buf);
|
||||
wasm_set_exception((WASMModuleInstance*)module_inst, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked,
|
||||
cur_func->u.func_import->func_type,
|
||||
self->module_inst,
|
||||
exec_env,
|
||||
frame->lp, cur_func->param_cell_num, argv_ret);
|
||||
|
||||
if (!ret)
|
||||
@ -803,8 +801,8 @@ wasm_interp_call_func_native(WASMThread *self,
|
||||
prev_frame->sp += 2;
|
||||
}
|
||||
|
||||
FREE_FRAME(self, frame);
|
||||
wasm_thread_set_cur_frame(self, prev_frame);
|
||||
FREE_FRAME(exec_env, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
@ -821,11 +819,11 @@ wasm_interp_call_func_native(WASMThread *self,
|
||||
#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
|
||||
|
||||
static void
|
||||
wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMModuleInstance *module = self->module_inst;
|
||||
WASMMemoryInstance *memory = module->default_memory;
|
||||
uint32 memory_data_size = memory
|
||||
? NumBytesPerPage * memory->cur_page_count : 0;
|
||||
@ -873,7 +871,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
#endif
|
||||
/* control instructions */
|
||||
HANDLE_OP (WASM_OP_UNREACHABLE):
|
||||
wasm_runtime_set_exception(module, "unreachable");
|
||||
wasm_set_exception(module, "unreachable");
|
||||
goto got_exception;
|
||||
|
||||
HANDLE_OP (WASM_OP_NOP):
|
||||
@ -887,7 +885,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
BLOCK_TYPE_BLOCK,
|
||||
&else_addr, &end_addr,
|
||||
NULL, 0)) {
|
||||
wasm_runtime_set_exception(module, "find block address failed");
|
||||
wasm_set_exception(module, "find block address failed");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -902,7 +900,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
BLOCK_TYPE_LOOP,
|
||||
&else_addr, &end_addr,
|
||||
NULL, 0)) {
|
||||
wasm_runtime_set_exception(module, "find block address failed");
|
||||
wasm_set_exception(module, "find block address failed");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -917,7 +915,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
BLOCK_TYPE_IF,
|
||||
&else_addr, &end_addr,
|
||||
NULL, 0)) {
|
||||
wasm_runtime_set_exception(module, "find block address failed");
|
||||
wasm_set_exception(module, "find block address failed");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -976,9 +974,8 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
uint64 total_size = sizeof(uint32) * (uint64)count;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(depths = wasm_malloc((uint32)total_size))) {
|
||||
wasm_runtime_set_exception(module,
|
||||
"WASM interp failed: "
|
||||
"allocate memory failed.");
|
||||
wasm_set_exception(module,
|
||||
"WASM interp failed: allocate memory failed.");
|
||||
goto got_exception;
|
||||
}
|
||||
}
|
||||
@ -1006,7 +1003,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
HANDLE_OP (WASM_OP_CALL):
|
||||
read_leb_uint32(frame_ip, frame_ip_end, fidx);
|
||||
wasm_assert(fidx < module->function_count);
|
||||
bh_assert(fidx < module->function_count);
|
||||
cur_func = module->functions + fidx;
|
||||
goto call_func_from_interp;
|
||||
|
||||
@ -1016,7 +1013,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, tidx);
|
||||
if (tidx >= module->module->type_count) {
|
||||
wasm_runtime_set_exception(module, "type index is overflow");
|
||||
wasm_set_exception(module, "type index is overflow");
|
||||
goto got_exception;
|
||||
}
|
||||
cur_type = module->module->types[tidx];
|
||||
@ -1026,13 +1023,13 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
val = POP_I32();
|
||||
|
||||
if (val < 0 || val >= (int32)table->cur_size) {
|
||||
wasm_runtime_set_exception(module, "undefined element");
|
||||
wasm_set_exception(module, "undefined element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32*)table->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
wasm_runtime_set_exception(module, "uninitialized element");
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -1043,7 +1040,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
if (!wasm_type_equal(cur_type, cur_func_type)) {
|
||||
wasm_runtime_set_exception(module, "indirect call type mismatch");
|
||||
wasm_set_exception(module, "indirect call type mismatch");
|
||||
goto got_exception;
|
||||
}
|
||||
goto call_func_from_interp;
|
||||
@ -1052,8 +1049,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
/* parametric instructions */
|
||||
HANDLE_OP (WASM_OP_DROP):
|
||||
{
|
||||
wasm_runtime_set_exception(module,
|
||||
"WASM interp failed: unsupported opcode.");
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -1071,8 +1067,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
HANDLE_OP (WASM_OP_SELECT):
|
||||
{
|
||||
wasm_runtime_set_exception(module,
|
||||
"WASM interp failed: unsupported opcode.");
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
@ -1114,8 +1109,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
PUSH_I64(LOCAL_I64(local_idx));
|
||||
break;
|
||||
default:
|
||||
wasm_runtime_set_exception(module,
|
||||
"invalid local type");
|
||||
wasm_set_exception(module, "invalid local type");
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
@ -1142,8 +1136,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
SET_LOCAL_F64(local_idx, POP_F64());
|
||||
break;
|
||||
default:
|
||||
wasm_runtime_set_exception(module,
|
||||
"invalid local type");
|
||||
wasm_set_exception(module, "invalid local type");
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
@ -1170,7 +1163,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
SET_LOCAL_F64(local_idx, GET_F64_FROM_ADDR(frame_sp - 2));
|
||||
break;
|
||||
default:
|
||||
wasm_runtime_set_exception(module, "invalid local type");
|
||||
wasm_set_exception(module, "invalid local type");
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
@ -1184,7 +1177,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
|
||||
wasm_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
|
||||
@ -1202,7 +1195,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
PUSH_F64(GET_F64_FROM_ADDR((uint32*)global_addr));
|
||||
break;
|
||||
default:
|
||||
wasm_runtime_set_exception(module, "invalid global type");
|
||||
wasm_set_exception(module, "invalid global type");
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
@ -1216,7 +1209,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
|
||||
wasm_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
|
||||
@ -1234,7 +1227,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
PUT_F64_TO_ADDR((uint32*)global_addr, POP_F64());
|
||||
break;
|
||||
default:
|
||||
wasm_runtime_set_exception(module, "invalid global type");
|
||||
wasm_set_exception(module, "invalid global type");
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
@ -1438,12 +1431,12 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
read_leb_uint32(frame_ip, frame_ip_end, reserved);
|
||||
delta = (uint32)POP_I32();
|
||||
|
||||
if (!wasm_runtime_enlarge_memory(module, delta)) {
|
||||
if (!wasm_enlarge_memory(module, delta)) {
|
||||
/* fail to memory.grow, return -1 */
|
||||
PUSH_I32(-1);
|
||||
if (wasm_runtime_get_exception(module)) {
|
||||
bh_printf("%s\n", wasm_runtime_get_exception(module));
|
||||
wasm_runtime_set_exception(module, NULL);
|
||||
if (wasm_get_exception(module)) {
|
||||
bh_printf("%s\n", wasm_get_exception(module));
|
||||
wasm_set_exception(module, NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1657,11 +1650,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = POP_I32();
|
||||
a = POP_I32();
|
||||
if (a == (int32)0x80000000 && b == -1) {
|
||||
wasm_runtime_set_exception(module, "integer overflow");
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
goto got_exception;
|
||||
}
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I32(a / b);
|
||||
@ -1675,7 +1668,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = (uint32)POP_I32();
|
||||
a = (uint32)POP_I32();
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I32(a / b);
|
||||
@ -1693,7 +1686,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I32(a % b);
|
||||
@ -1707,7 +1700,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = (uint32)POP_I32();
|
||||
a = (uint32)POP_I32();
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I32(a % b);
|
||||
@ -1727,16 +1720,34 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_SHL):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC(uint32, uint32, I32, <<);
|
||||
#else
|
||||
DEF_OP_NUMERIC2(uint32, uint32, I32, <<);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_SHR_S):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC(int32, uint32, I32, >>);
|
||||
#else
|
||||
DEF_OP_NUMERIC2(int32, uint32, I32, >>);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_SHR_U):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC(uint32, uint32, I32, >>);
|
||||
#else
|
||||
DEF_OP_NUMERIC2(uint32, uint32, I32, >>);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I32_ROTL):
|
||||
{
|
||||
@ -1790,11 +1801,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = POP_I64();
|
||||
a = POP_I64();
|
||||
if (a == (int64)0x8000000000000000LL && b == -1) {
|
||||
wasm_runtime_set_exception(module, "integer overflow");
|
||||
wasm_set_exception(module, "integer overflow");
|
||||
goto got_exception;
|
||||
}
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I64(a / b);
|
||||
@ -1808,7 +1819,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = (uint64)POP_I64();
|
||||
a = (uint64)POP_I64();
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I64(a / b);
|
||||
@ -1826,7 +1837,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I64(a % b);
|
||||
@ -1840,7 +1851,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
b = (uint64)POP_I64();
|
||||
a = (uint64)POP_I64();
|
||||
if (b == 0) {
|
||||
wasm_runtime_set_exception(module, "integer divide by zero");
|
||||
wasm_set_exception(module, "integer divide by zero");
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_I64(a % b);
|
||||
@ -1860,16 +1871,34 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP_END ();
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_SHL):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC_64(uint64, uint64, I64, <<);
|
||||
#else
|
||||
DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_SHR_S):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC_64(int64, uint64, I64, >>);
|
||||
#else
|
||||
DEF_OP_NUMERIC2_64(int64, uint64, I64, >>);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_SHR_U):
|
||||
{
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32)
|
||||
DEF_OP_NUMERIC_64(uint64, uint64, I64, >>);
|
||||
#else
|
||||
DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>);
|
||||
#endif
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_I64_ROTL):
|
||||
{
|
||||
@ -1898,12 +1927,12 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
HANDLE_OP (WASM_OP_F32_NEG):
|
||||
{
|
||||
int32 i32 = frame_sp[-1];
|
||||
int32 i32 = (int32)frame_sp[-1];
|
||||
int32 sign_bit = i32 & (1 << 31);
|
||||
if (sign_bit)
|
||||
frame_sp[-1] = i32 & ~(1 << 31);
|
||||
else
|
||||
frame_sp[-1] = i32 | (1 << 31);
|
||||
frame_sp[-1] = (uint32)(i32 | (1 << 31));
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
@ -1993,11 +2022,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP (WASM_OP_F64_NEG):
|
||||
{
|
||||
int64 i64 = GET_I64_FROM_ADDR(frame_sp - 2);
|
||||
int64 sign_bit = i64 & (((uint64)1) << 63);
|
||||
int64 sign_bit = i64 & (((int64)1) << 63);
|
||||
if (sign_bit)
|
||||
PUT_I64_TO_ADDR(frame_sp - 2, (i64 & ~(((uint64)1) << 63)));
|
||||
PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 & ~(((uint64)1) << 63)));
|
||||
else
|
||||
PUT_I64_TO_ADDR(frame_sp - 2, (i64 | (((uint64)1) << 63)));
|
||||
PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 | (((uint64)1) << 63)));
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
@ -2200,8 +2229,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES == 0
|
||||
default:
|
||||
wasm_runtime_set_exception(module,
|
||||
"WASM interp failed: unsupported opcode.");
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
@ -2229,8 +2257,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x26):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x27):
|
||||
{
|
||||
wasm_runtime_set_exception(module,
|
||||
"WASM interp failed: unsupported opcode.");
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
@ -2244,7 +2271,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
call_func_from_interp:
|
||||
/* Only do the copy when it's called from interpreter. */
|
||||
{
|
||||
WASMInterpFrame *outs_area = wasm_thread_wasm_stack_top(self);
|
||||
WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env);
|
||||
POP(cur_func->param_cell_num);
|
||||
SYNC_ALL_TO_FRAME();
|
||||
word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num);
|
||||
@ -2254,13 +2281,13 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
call_func_from_entry:
|
||||
{
|
||||
if (cur_func->is_import_func) {
|
||||
wasm_interp_call_func_native(self, cur_func, prev_frame);
|
||||
wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame);
|
||||
prev_frame = frame->prev_frame;
|
||||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
|
||||
memory = module->default_memory;
|
||||
if (wasm_runtime_get_exception(module))
|
||||
if (wasm_get_exception(module))
|
||||
goto got_exception;
|
||||
}
|
||||
else {
|
||||
@ -2275,21 +2302,20 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
+ (uint64)cur_wasm_func->max_stack_cell_num
|
||||
+ ((uint64)cur_wasm_func->max_block_num) * sizeof(WASMBranchBlock) / 4;
|
||||
if (all_cell_num >= UINT32_MAX) {
|
||||
wasm_runtime_set_exception(self->module_inst,
|
||||
"WASM interp failed: stack overflow.");
|
||||
wasm_set_exception(module, "WASM interp failed: stack overflow.");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num);
|
||||
if (!(frame = ALLOC_FRAME(self, frame_size, prev_frame))) {
|
||||
if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) {
|
||||
frame = prev_frame;
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* Initialize the interpreter context. */
|
||||
frame->function = cur_func;
|
||||
frame_ip = wasm_runtime_get_func_code(cur_func);
|
||||
frame_ip_end = wasm_runtime_get_func_code_end(cur_func);
|
||||
frame_ip = wasm_get_func_code(cur_func);
|
||||
frame_ip_end = wasm_get_func_code_end(cur_func);
|
||||
frame_lp = frame->lp;
|
||||
|
||||
frame_sp = frame->sp_bottom = frame_lp + cur_func->param_cell_num
|
||||
@ -2310,15 +2336,15 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
PUSH_CSP(BLOCK_TYPE_FUNCTION, ret_type,
|
||||
frame_ip, NULL, frame_ip_end - 1);
|
||||
|
||||
wasm_thread_set_cur_frame(self, (WASMRuntimeFrame*)frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame);
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
return_func:
|
||||
{
|
||||
FREE_FRAME(self, frame);
|
||||
wasm_thread_set_cur_frame(self, (WASMRuntimeFrame*)prev_frame);
|
||||
FREE_FRAME(exec_env, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)prev_frame);
|
||||
|
||||
if (!prev_frame->ip)
|
||||
/* Called from native. */
|
||||
@ -2329,7 +2355,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
}
|
||||
|
||||
out_of_bounds:
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
wasm_set_exception(module, "out of bounds memory access");
|
||||
|
||||
got_exception:
|
||||
if (depths && depths != depth_buf) {
|
||||
@ -2348,11 +2374,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
|
||||
|
||||
void
|
||||
wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function,
|
||||
uint32 argc, uint32 argv[])
|
||||
{
|
||||
WASMThread *self = &module_inst->main_tlr;
|
||||
WASMRuntimeFrame *prev_frame = wasm_thread_get_cur_frame(self);
|
||||
WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
|
||||
WASMInterpFrame *frame, *outs_area;
|
||||
|
||||
/* Allocate sufficient cells for all kinds of return values. */
|
||||
@ -2366,16 +2392,16 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
snprintf(buf, sizeof(buf),
|
||||
"invalid argument count %d, expected %d",
|
||||
argc, function->param_cell_num);
|
||||
wasm_runtime_set_exception(self->module_inst, buf);
|
||||
wasm_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: check stack overflow. */
|
||||
|
||||
if (!(frame = ALLOC_FRAME(self, frame_size, (WASMInterpFrame*)prev_frame)))
|
||||
if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame)))
|
||||
return;
|
||||
|
||||
outs_area = wasm_thread_wasm_stack_top(self);
|
||||
outs_area = wasm_exec_env_wasm_stack_top(exec_env);
|
||||
frame->function = NULL;
|
||||
frame->ip = NULL;
|
||||
/* There is no local variable. */
|
||||
@ -2384,19 +2410,19 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
if (argc > 0)
|
||||
word_copy(outs_area->lp, argv, argc);
|
||||
|
||||
wasm_thread_set_cur_frame(self, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
if (function->is_import_func)
|
||||
wasm_interp_call_func_native(self, function, frame);
|
||||
wasm_interp_call_func_native(module_inst, exec_env, function, frame);
|
||||
else
|
||||
wasm_interp_call_func_bytecode(self, function, frame);
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
|
||||
|
||||
/* Output the return value to the caller */
|
||||
if (!wasm_runtime_get_exception(self->module_inst)) {
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
for (i = 0; i < function->ret_cell_num; i++)
|
||||
argv[i] = *(frame->sp + i - function->ret_cell_num);
|
||||
}
|
||||
|
||||
wasm_thread_set_cur_frame(self, prev_frame);
|
||||
FREE_FRAME(self, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||
FREE_FRAME(exec_env, frame);
|
||||
}
|
||||
@ -14,6 +14,7 @@ extern "C" {
|
||||
|
||||
struct WASMModuleInstance;
|
||||
struct WASMFunctionInstance;
|
||||
struct WASMExecEnv;
|
||||
|
||||
typedef struct WASMInterpFrame {
|
||||
/* The frame of the caller that are calling the current function. */
|
||||
@ -61,6 +62,7 @@ wasm_interp_interp_frame_size(unsigned all_cell_num)
|
||||
|
||||
void
|
||||
wasm_interp_call_wasm(struct WASMModuleInstance *module_inst,
|
||||
struct WASMExecEnv *exec_env,
|
||||
struct WASMFunctionInstance *function,
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
@ -4,14 +4,13 @@
|
||||
*/
|
||||
|
||||
#include "wasm_loader.h"
|
||||
#include "bh_common.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_log.h"
|
||||
#include "wasm.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "wasm_dlfcn.h"
|
||||
#include "bh_common.h"
|
||||
#include "../common/wasm_native.h"
|
||||
|
||||
/* Read a value of given type from the address pointed to by the given
|
||||
pointer and increase the pointer to the position just after the
|
||||
@ -55,14 +54,13 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
|
||||
uint64 byte;
|
||||
|
||||
while (true) {
|
||||
/* Check if the byte count exteeds the max byte count allowed */
|
||||
if (bcnt + 1 > (maxbits + 6) / 7) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: "
|
||||
"integer representation too long");
|
||||
return false;
|
||||
}
|
||||
/* Check buffer */
|
||||
|
||||
CHECK_BUF(buf, buf_end, *p_offset + 1);
|
||||
byte = buf[*p_offset];
|
||||
*p_offset += 1;
|
||||
@ -178,7 +176,7 @@ check_utf8_str(const uint8* str, uint32 len)
|
||||
the count of leading '1' denotes the total byte count */
|
||||
n_bytes = 0;
|
||||
while ((chr & 0x80) != 0) {
|
||||
chr <<= 1;
|
||||
chr = (uint8)(chr << 1);
|
||||
n_bytes++;
|
||||
}
|
||||
|
||||
@ -223,12 +221,12 @@ const_str_set_insert(const uint8 *str, uint32 len, WASMModule *module,
|
||||
bh_memcpy_s(c_str, len + 1, str, len);
|
||||
c_str[len] = '\0';
|
||||
|
||||
if ((value = wasm_hash_map_find(set, c_str))) {
|
||||
if ((value = bh_hash_map_find(set, c_str))) {
|
||||
wasm_free(c_str);
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!wasm_hash_map_insert(set, c_str, c_str)) {
|
||||
if (!bh_hash_map_insert(set, c_str, c_str)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: "
|
||||
"insert string to hash map failed.");
|
||||
@ -389,7 +387,7 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
/* 0x70 */
|
||||
table->elem_type = read_uint8(p);
|
||||
wasm_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
|
||||
bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
|
||||
read_leb_uint32(p, p_end, table->flags);
|
||||
read_leb_uint32(p, p_end, table->init_size);
|
||||
if (table->flags & 1)
|
||||
@ -435,7 +433,7 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
/* 0x70 */
|
||||
table->elem_type = read_uint8(p);
|
||||
wasm_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
|
||||
bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
|
||||
read_leb_uint32(p, p_end, table->flags);
|
||||
read_leb_uint32(p, p_end, table->init_size);
|
||||
if (table->flags & 1)
|
||||
@ -476,14 +474,26 @@ resolve_sym(const char *module_name, const char *field_name)
|
||||
{
|
||||
void *sym;
|
||||
|
||||
if (strcmp(module_name, "env") != 0)
|
||||
return NULL;
|
||||
|
||||
if (field_name[0] == '_'
|
||||
&& (sym = wasm_dlsym(NULL, field_name + 1)))
|
||||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
if ((sym = wasm_native_lookup_libc_builtin_func(module_name,
|
||||
field_name)))
|
||||
return sym;
|
||||
#endif
|
||||
|
||||
if ((sym = wasm_dlsym(NULL, field_name)))
|
||||
#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;
|
||||
@ -622,7 +632,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
kind = read_uint8(p);
|
||||
switch (kind) {
|
||||
case IMPORT_KIND_FUNC: /* import function */
|
||||
wasm_assert(import_functions);
|
||||
bh_assert(import_functions);
|
||||
import = import_functions++;
|
||||
read_leb_uint32(p, p_end, type_index);
|
||||
if (type_index >= module->type_count) {
|
||||
@ -633,17 +643,22 @@ 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 =
|
||||
wasm_native_func_lookup(module_name, field_name))
|
||||
&& !(import->u.function.func_ptr_linked =
|
||||
resolve_sym(module_name, field_name))) {
|
||||
#ifndef BUILD_AOT_COMPILER /* Output warning except running aot compiler */
|
||||
LOG_WARNING("warning: fail to link import function (%s, %s)\n",
|
||||
module_name, field_name);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case IMPORT_KIND_TABLE: /* import table */
|
||||
wasm_assert(import_tables);
|
||||
bh_assert(import_tables);
|
||||
import = import_tables++;
|
||||
if (!load_table_import(&p, p_end, &import->u.table,
|
||||
error_buf, error_buf_size))
|
||||
@ -655,7 +670,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
break;
|
||||
|
||||
case IMPORT_KIND_MEMORY: /* import memory */
|
||||
wasm_assert(import_memories);
|
||||
bh_assert(import_memories);
|
||||
import = import_memories++;
|
||||
if (!load_memory_import(&p, p_end, &import->u.memory,
|
||||
error_buf, error_buf_size))
|
||||
@ -668,7 +683,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
break;
|
||||
|
||||
case IMPORT_KIND_GLOBAL: /* import global */
|
||||
wasm_assert(import_globals);
|
||||
bh_assert(import_globals);
|
||||
import = import_globals++;
|
||||
CHECK_BUF(p, p_end, 2);
|
||||
import->u.global.type = read_uint8(p);
|
||||
@ -680,8 +695,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
return false;
|
||||
}
|
||||
import->u.global.is_mutable = mutable & 1 ? true : false;
|
||||
if (!(wasm_native_global_lookup(module_name, field_name,
|
||||
&import->u.global))) {
|
||||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
if (!(wasm_native_lookup_libc_builtin_global(
|
||||
module_name, field_name,
|
||||
&import->u.global))) {
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size,
|
||||
"Load import section failed: "
|
||||
@ -689,6 +706,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
module_name, field_name);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -702,7 +720,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
import->u.names.field_name = field_name;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_WASI != 0
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
import = module->import_functions;
|
||||
for (i = 0; i < module->import_function_count; i++, import++) {
|
||||
if (!strcmp(import->u.names.module_name, "wasi_unstable")) {
|
||||
@ -874,7 +892,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
WASMTable *table;
|
||||
|
||||
read_leb_uint32(p, p_end, table_count);
|
||||
wasm_assert(table_count == 1);
|
||||
bh_assert(table_count == 1);
|
||||
|
||||
if (table_count) {
|
||||
if (table_count > 1) {
|
||||
@ -920,7 +938,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
WASMMemory *memory;
|
||||
|
||||
read_leb_uint32(p, p_end, memory_count);
|
||||
wasm_assert(memory_count == 1);
|
||||
bh_assert(memory_count == 1);
|
||||
|
||||
if (memory_count) {
|
||||
if (memory_count > 1) {
|
||||
@ -1452,15 +1470,21 @@ create_module(char *error_buf, uint32 error_buf_size)
|
||||
|
||||
memset(module, 0, sizeof(WASMModule));
|
||||
|
||||
module->module_type = Wasm_Module_Bytecode;
|
||||
|
||||
/* Set start_function to -1, means no start function */
|
||||
module->start_function = (uint32)-1;
|
||||
|
||||
if (!(module->const_str_set = wasm_hash_map_create(32, false,
|
||||
if (!(module->const_str_set = bh_hash_map_create(32, false,
|
||||
(HashFunc)wasm_string_hash,
|
||||
(KeyEqualFunc)wasm_string_equal,
|
||||
NULL,
|
||||
wasm_loader_free)))
|
||||
wasm_loader_free))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"WASM module load failed: "
|
||||
"create const string set failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return module;
|
||||
|
||||
@ -1507,7 +1531,7 @@ create_sections(const uint8 *buf, uint32 size,
|
||||
uint8 section_type, last_section_type = (uint8)-1;
|
||||
uint32 section_size;
|
||||
|
||||
wasm_assert(!*p_section_list);
|
||||
bh_assert(!*p_section_list);
|
||||
|
||||
p += 8;
|
||||
while (p < p_end) {
|
||||
@ -1635,14 +1659,17 @@ wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_bu
|
||||
|
||||
memset(module, 0, sizeof(WASMModule));
|
||||
|
||||
module->module_type = Wasm_Module_Bytecode;
|
||||
|
||||
/* Set start_function to -1, means no start function */
|
||||
module->start_function = (uint32)-1;
|
||||
|
||||
if (!(module->const_str_set = wasm_hash_map_create(32, false,
|
||||
(HashFunc)wasm_string_hash,
|
||||
(KeyEqualFunc)wasm_string_equal,
|
||||
NULL,
|
||||
wasm_loader_free)))
|
||||
if (!(module->const_str_set =
|
||||
bh_hash_map_create(32, false,
|
||||
(HashFunc)wasm_string_hash,
|
||||
(KeyEqualFunc)wasm_string_equal,
|
||||
NULL,
|
||||
wasm_loader_free)))
|
||||
goto fail;
|
||||
|
||||
if (!load(buf, size, module, error_buf, error_buf_size))
|
||||
@ -1712,30 +1739,11 @@ wasm_loader_unload(WASMModule *module)
|
||||
}
|
||||
|
||||
if (module->const_str_set)
|
||||
wasm_hash_map_destroy(module->const_str_set);
|
||||
bh_hash_map_destroy(module->const_str_set);
|
||||
|
||||
wasm_free(module);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_WASI != 0
|
||||
void
|
||||
wasm_runtime_set_wasi_args(WASMModule *module,
|
||||
const char *dir_list[], uint32 dir_count,
|
||||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
const char *env_list[], uint32 env_count,
|
||||
const char *argv[], uint32 argc)
|
||||
{
|
||||
module->wasi_args.dir_list = dir_list;
|
||||
module->wasi_args.dir_count = dir_count;
|
||||
module->wasi_args.map_dir_list = map_dir_list;
|
||||
module->wasi_args.map_dir_count = map_dir_count;
|
||||
module->wasi_args.env = env_list;
|
||||
module->wasi_args.env_count = env_count;
|
||||
module->wasi_args.argv = argv;
|
||||
module->wasi_args.argc = argc;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
wasm_loader_find_block_addr(WASMModule *module,
|
||||
const uint8 *start_addr,
|
||||
@ -2083,7 +2091,7 @@ static void*
|
||||
memory_realloc(void *mem_old, uint32 size_old, uint32 size_new)
|
||||
{
|
||||
uint8 *mem_new;
|
||||
wasm_assert(size_new > size_old);
|
||||
bh_assert(size_new > size_old);
|
||||
if ((mem_new = wasm_malloc(size_new))) {
|
||||
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
||||
memset(mem_new + size_old, 0, size_new - size_old);
|
||||
@ -2252,6 +2260,8 @@ push_type(uint8 type, uint8 **p_frame_ref_bottom,
|
||||
stack_cell_num++;
|
||||
if (stack_cell_num > max_stack_cell_num)
|
||||
max_stack_cell_num = stack_cell_num;
|
||||
goto handle_i32_f32;
|
||||
handle_i32_f32:
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
if (!check_stack_push(p_frame_ref_bottom, p_frame_ref_boundary,
|
||||
@ -2672,6 +2682,8 @@ handle_next_reachable_block:
|
||||
|
||||
if (func_type->result_count)
|
||||
PUSH_TYPE(func_type->types[func_type->param_count]);
|
||||
|
||||
func->has_op_func_call = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2716,6 +2728,8 @@ handle_next_reachable_block:
|
||||
}
|
||||
|
||||
PUSH_TYPE(func_type->types[func_type->param_count]);
|
||||
|
||||
func->has_op_func_call = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2939,6 +2953,9 @@ handle_next_reachable_block:
|
||||
}
|
||||
POP_I32();
|
||||
PUSH_I32();
|
||||
|
||||
func->has_op_memory_grow = true;
|
||||
module->possible_memory_grow = true;
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CONST:
|
||||
@ -6,7 +6,8 @@
|
||||
#define _WASM_LOADER_H
|
||||
|
||||
#include "wasm.h"
|
||||
#include "wasm_hashmap.h"
|
||||
#include "bh_hashmap.h"
|
||||
#include "../common/wasm_runtime_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
File diff suppressed because it is too large
Load Diff
272
core/iwasm/interpreter/wasm_runtime.h
Normal file
272
core/iwasm/interpreter/wasm_runtime.h
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_RUNTIME_H
|
||||
#define _WASM_RUNTIME_H
|
||||
|
||||
#include "wasm.h"
|
||||
#include "bh_hashmap.h"
|
||||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct WASMMemoryInstance {
|
||||
/* Current page count */
|
||||
uint32 cur_page_count;
|
||||
/* Maximum page count */
|
||||
uint32 max_page_count;
|
||||
|
||||
/* Heap data base address */
|
||||
uint8 *heap_data;
|
||||
/* Heap data end address */
|
||||
uint8 *heap_data_end;
|
||||
/* The heap created */
|
||||
void *heap_handle;
|
||||
/* Heap base offset of wasm app */
|
||||
int32 heap_base_offset;
|
||||
|
||||
/* Memory data */
|
||||
uint8 *memory_data;
|
||||
/* Global data of global instances */
|
||||
uint8 *global_data;
|
||||
uint32 global_data_size;
|
||||
|
||||
/* End address of memory */
|
||||
uint8 *end_addr;
|
||||
|
||||
/* Base address, the layout is:
|
||||
thunk_argv data + thunk arg offsets +
|
||||
memory data + global data
|
||||
memory data init size is: NumBytesPerPage * cur_page_count
|
||||
global data size is calculated in module instantiating
|
||||
Note: when memory is re-allocated, the thunk argv data, thunk
|
||||
argv offsets and memory data must be copied to new memory also.
|
||||
*/
|
||||
uint8 base_addr[1];
|
||||
} WASMMemoryInstance;
|
||||
|
||||
typedef struct WASMTableInstance {
|
||||
/* The element type, TABLE_ELEM_TYPE_ANY_FUNC currently */
|
||||
uint8 elem_type;
|
||||
/* Current size */
|
||||
uint32 cur_size;
|
||||
/* Maximum size */
|
||||
uint32 max_size;
|
||||
/* Base address */
|
||||
uint8 base_addr[1];
|
||||
} WASMTableInstance;
|
||||
|
||||
typedef struct WASMGlobalInstance {
|
||||
/* value type, VALUE_TYPE_I32/I64/F32/F64 */
|
||||
uint8 type;
|
||||
/* mutable or constant */
|
||||
bool is_mutable;
|
||||
/* data offset to base_addr of WASMMemoryInstance */
|
||||
uint32 data_offset;
|
||||
/* initial value */
|
||||
WASMValue initial_value;
|
||||
} WASMGlobalInstance;
|
||||
|
||||
typedef struct WASMFunctionInstance {
|
||||
/* whether it is import function or WASM function */
|
||||
bool is_import_func;
|
||||
/* parameter count */
|
||||
uint16 param_count;
|
||||
/* local variable count, 0 for import function */
|
||||
uint16 local_count;
|
||||
/* cell num of parameters */
|
||||
uint16 param_cell_num;
|
||||
/* cell num of return type */
|
||||
uint16 ret_cell_num;
|
||||
/* cell num of local variables, 0 for import function */
|
||||
uint16 local_cell_num;
|
||||
uint16 *local_offsets;
|
||||
/* parameter types */
|
||||
uint8 *param_types;
|
||||
/* local types, NULL for import function */
|
||||
uint8 *local_types;
|
||||
union {
|
||||
WASMFunctionImport *func_import;
|
||||
WASMFunction *func;
|
||||
} u;
|
||||
} WASMFunctionInstance;
|
||||
|
||||
typedef struct WASMExportFuncInstance {
|
||||
char *name;
|
||||
WASMFunctionInstance *function;
|
||||
} WASMExportFuncInstance;
|
||||
|
||||
typedef struct WASMModuleInstance {
|
||||
/* Module instance type, for module instance loaded from
|
||||
WASM bytecode binary, this field is Wasm_Module_Bytecode;
|
||||
for module instance loaded from AOT file, this field is
|
||||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModuleInstance structure. */
|
||||
uint32 module_type;
|
||||
|
||||
uint32 memory_count;
|
||||
uint32 table_count;
|
||||
uint32 global_count;
|
||||
uint32 function_count;
|
||||
uint32 export_func_count;
|
||||
|
||||
WASMMemoryInstance **memories;
|
||||
WASMTableInstance **tables;
|
||||
WASMGlobalInstance *globals;
|
||||
WASMFunctionInstance *functions;
|
||||
WASMExportFuncInstance *export_functions;
|
||||
|
||||
WASMMemoryInstance *default_memory;
|
||||
WASMTableInstance *default_table;
|
||||
|
||||
WASMFunctionInstance *start_function;
|
||||
|
||||
WASMModule *module;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
|
||||
uint32 DYNAMICTOP_PTR_offset;
|
||||
uint32 temp_ret;
|
||||
uint32 llvm_stack;
|
||||
|
||||
/* Default WASM stack size of threads of this Module instance. */
|
||||
uint32 default_wasm_stack_size;
|
||||
|
||||
/* The exception buffer of wasm interpreter for current thread. */
|
||||
char cur_exception[128];
|
||||
|
||||
/* The custom data that can be set/get by
|
||||
* wasm_set_custom_data/wasm_get_custom_data */
|
||||
void *custom_data;
|
||||
|
||||
/* Main exec env */
|
||||
WASMExecEnv *main_exec_env;
|
||||
} WASMModuleInstance;
|
||||
|
||||
struct WASMInterpFrame;
|
||||
typedef struct WASMInterpFrame WASMRuntimeFrame;
|
||||
|
||||
/**
|
||||
* Return the code block of a function.
|
||||
*
|
||||
* @param func the WASM function instance
|
||||
*
|
||||
* @return the code block of the function
|
||||
*/
|
||||
static inline uint8*
|
||||
wasm_get_func_code(WASMFunctionInstance *func)
|
||||
{
|
||||
return func->is_import_func ? NULL : func->u.func->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the code block end of a function.
|
||||
*
|
||||
* @param func the WASM function instance
|
||||
*
|
||||
* @return the code block end of the function
|
||||
*/
|
||||
static inline uint8*
|
||||
wasm_get_func_code_end(WASMFunctionInstance *func)
|
||||
{
|
||||
return func->is_import_func
|
||||
? NULL : func->u.func->code + func->u.func->code_size;
|
||||
}
|
||||
|
||||
WASMModule *
|
||||
wasm_load(const uint8 *buf, uint32 size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
WASMModule *
|
||||
wasm_load_from_sections(WASMSection *section_list,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
void
|
||||
wasm_unload(WASMModule *module);
|
||||
|
||||
WASMModuleInstance *
|
||||
wasm_instantiate(WASMModule *module,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
void
|
||||
wasm_deinstantiate(WASMModuleInstance *module_inst);
|
||||
|
||||
WASMFunctionInstance *
|
||||
wasm_lookup_function(const WASMModuleInstance *module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
bool
|
||||
wasm_call_function(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
||||
WASMFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
void
|
||||
wasm_set_exception(WASMModuleInstance *module, const char *exception);
|
||||
|
||||
const char*
|
||||
wasm_get_exception(WASMModuleInstance *module);
|
||||
|
||||
int32
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size);
|
||||
|
||||
void
|
||||
wasm_module_free(WASMModuleInstance *module_inst, int32 ptr);
|
||||
|
||||
int32
|
||||
wasm_module_dup_data(WASMModuleInstance *module_inst,
|
||||
const char *src, uint32 size);
|
||||
|
||||
bool
|
||||
wasm_validate_app_addr(WASMModuleInstance *module_inst,
|
||||
int32 app_offset, uint32 size);
|
||||
|
||||
bool
|
||||
wasm_validate_app_str_addr(WASMModuleInstance *module_inst,
|
||||
int32 app_offset);
|
||||
|
||||
bool
|
||||
wasm_validate_native_addr(WASMModuleInstance *module_inst,
|
||||
void *native_ptr, uint32 size);
|
||||
|
||||
void *
|
||||
wasm_addr_app_to_native(WASMModuleInstance *module_inst,
|
||||
int32 app_offset);
|
||||
|
||||
int32
|
||||
wasm_addr_native_to_app(WASMModuleInstance *module_inst,
|
||||
void *native_ptr);
|
||||
|
||||
bool
|
||||
wasm_get_app_addr_range(WASMModuleInstance *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset);
|
||||
|
||||
bool
|
||||
wasm_get_native_addr_range(WASMModuleInstance *module_inst,
|
||||
uint8_t *native_ptr,
|
||||
uint8_t **p_native_start_addr,
|
||||
uint8_t **p_native_end_addr);
|
||||
|
||||
bool
|
||||
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_RUNTIME_H */
|
||||
|
||||
8
core/iwasm/lib/3rdparty/LICENCE.txt
vendored
8
core/iwasm/lib/3rdparty/LICENCE.txt
vendored
@ -1,8 +0,0 @@
|
||||
MIT licence
|
||||
Copyright (c) 2016 Gábor Kiss-Vámosi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
495
core/iwasm/lib/3rdparty/lv_conf.h
vendored
495
core/iwasm/lib/3rdparty/lv_conf.h
vendored
@ -1,495 +0,0 @@
|
||||
/**
|
||||
* @file lv_conf.h
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER
|
||||
*/
|
||||
|
||||
#if 1 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
/* clang-format off */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*====================
|
||||
Graphical settings
|
||||
*====================*/
|
||||
|
||||
/* Maximal horizontal and vertical resolution to support by the library.*/
|
||||
#define LV_HOR_RES_MAX (320)
|
||||
#define LV_VER_RES_MAX (240)
|
||||
|
||||
/* Color depth:
|
||||
* - 1: 1 byte per pixel
|
||||
* - 8: RGB233
|
||||
* - 16: RGB565
|
||||
* - 32: ARGB8888
|
||||
*/
|
||||
#define LV_COLOR_DEPTH 32
|
||||
|
||||
/* Swap the 2 bytes of RGB565 color.
|
||||
* Useful if the display has a 8 bit interface (e.g. SPI)*/
|
||||
#define LV_COLOR_16_SWAP 0
|
||||
|
||||
/* 1: Enable screen transparency.
|
||||
* Useful for OSD or other overlapping GUIs.
|
||||
* Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/
|
||||
#define LV_COLOR_SCREEN_TRANSP 0
|
||||
|
||||
/*Images pixels with this color will not be drawn (with chroma keying)*/
|
||||
#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/
|
||||
|
||||
/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
|
||||
#define LV_ANTIALIAS 1
|
||||
|
||||
/* Default display refresh period.
|
||||
* Can be changed in the display driver (`lv_disp_drv_t`).*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||
|
||||
/* Dot Per Inch: used to initialize default sizes.
|
||||
* E.g. a button with width = LV_DPI / 2 -> half inch wide
|
||||
* (Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||
#define LV_DPI 100 /*[px]*/
|
||||
|
||||
/* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */
|
||||
typedef int16_t lv_coord_t;
|
||||
|
||||
/*=========================
|
||||
Memory manager settings
|
||||
*=========================*/
|
||||
|
||||
/* LittelvGL's internal memory manager's settings.
|
||||
* The graphical objects and other related data are stored here. */
|
||||
|
||||
/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */
|
||||
#define LV_MEM_CUSTOM 1
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
|
||||
# define LV_MEM_SIZE (128U * 1024U)
|
||||
|
||||
/* Complier prefix for a big array declaration */
|
||||
# define LV_MEM_ATTR
|
||||
|
||||
/* Set an address for the memory pool instead of allocating it as an array.
|
||||
* Can be in external SRAM too. */
|
||||
# define LV_MEM_ADR 0
|
||||
|
||||
/* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */
|
||||
# define LV_MEM_AUTO_DEFRAG 1
|
||||
#else /*LV_MEM_CUSTOM*/
|
||||
# define LV_MEM_CUSTOM_INCLUDE "bh_memory.h" /*Header for the dynamic memory function*/
|
||||
# define LV_MEM_CUSTOM_ALLOC bh_malloc /*Wrapper to malloc*/
|
||||
# define LV_MEM_CUSTOM_FREE bh_free /*Wrapper to free*/
|
||||
#endif /*LV_MEM_CUSTOM*/
|
||||
|
||||
/* Garbage Collector settings
|
||||
* Used if lvgl is binded to higher level language and the memory is managed by that language */
|
||||
#define LV_ENABLE_GC 0
|
||||
#if LV_ENABLE_GC != 0
|
||||
# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||
# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/
|
||||
# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*=======================
|
||||
Input device settings
|
||||
*=======================*/
|
||||
|
||||
/* Input device default settings.
|
||||
* Can be changed in the Input device driver (`lv_indev_drv_t`)*/
|
||||
|
||||
/* Input device read period in milliseconds */
|
||||
#define LV_INDEV_DEF_READ_PERIOD 30
|
||||
|
||||
/* Drag threshold in pixels */
|
||||
#define LV_INDEV_DEF_DRAG_LIMIT 10
|
||||
|
||||
/* Drag throw slow-down in [%]. Greater value -> faster slow-down */
|
||||
#define LV_INDEV_DEF_DRAG_THROW 20
|
||||
|
||||
/* Long press time in milliseconds.
|
||||
* Time to send `LV_EVENT_LONG_PRESSSED`) */
|
||||
#define LV_INDEV_DEF_LONG_PRESS_TIME 400
|
||||
|
||||
/* Repeated trigger period in long press [ms]
|
||||
* Time between `LV_EVENT_LONG_PRESSED_REPEAT */
|
||||
#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100
|
||||
|
||||
/*==================
|
||||
* Feature usage
|
||||
*==================*/
|
||||
|
||||
/*1: Enable the Animations */
|
||||
#define LV_USE_ANIMATION 1
|
||||
#if LV_USE_ANIMATION
|
||||
|
||||
/*Declare the type of the user data of animations (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_anim_user_data_t;
|
||||
|
||||
#endif
|
||||
|
||||
/* 1: Enable shadow drawing*/
|
||||
#define LV_USE_SHADOW 1
|
||||
|
||||
/* 1: Enable object groups (for keyboard/encoder navigation) */
|
||||
#define LV_USE_GROUP 0
|
||||
#if LV_USE_GROUP
|
||||
typedef void * lv_group_user_data_t;
|
||||
#endif /*LV_USE_GROUP*/
|
||||
|
||||
/* 1: Enable GPU interface*/
|
||||
#define LV_USE_GPU 1
|
||||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
#define LV_USE_FILESYSTEM 1
|
||||
#if LV_USE_FILESYSTEM
|
||||
/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_fs_drv_user_data_t;
|
||||
#endif
|
||||
|
||||
/*1: Add a `user_data` to drivers and objects*/
|
||||
#define LV_USE_USER_DATA 0
|
||||
|
||||
/*========================
|
||||
* Image decoder and cache
|
||||
*========================*/
|
||||
|
||||
/* 1: Enable indexed (palette) images */
|
||||
#define LV_IMG_CF_INDEXED 1
|
||||
|
||||
/* 1: Enable alpha indexed images */
|
||||
#define LV_IMG_CF_ALPHA 1
|
||||
|
||||
/* Default image cache size. Image caching keeps the images opened.
|
||||
* If only the built-in image formats are used there is no real advantage of caching.
|
||||
* (I.e. no new image decoder is added)
|
||||
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
* However the opened images might consume additional RAM.
|
||||
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */
|
||||
#define LV_IMG_CACHE_DEF_SIZE 1
|
||||
|
||||
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_img_decoder_user_data_t;
|
||||
|
||||
/*=====================
|
||||
* Compiler settings
|
||||
*====================*/
|
||||
/* Define a custom attribute to `lv_tick_inc` function */
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/* Define a custom attribute to `lv_task_handler` function */
|
||||
#define LV_ATTRIBUTE_TASK_HANDLER
|
||||
|
||||
/* With size optimization (-Os) the compiler might not align data to
|
||||
* 4 or 8 byte boundary. This alignment will be explicitly applied where needed.
|
||||
* E.g. __attribute__((aligned(4))) */
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/* Attribute to mark large constant arrays for example
|
||||
* font's bitmaps */
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*===================
|
||||
* HAL settings
|
||||
*==================*/
|
||||
|
||||
/* 1: use a custom tick source.
|
||||
* It removes the need to manually update the tick with `lv_tick_inc`) */
|
||||
#define LV_TICK_CUSTOM 1
|
||||
#if LV_TICK_CUSTOM == 1
|
||||
#define LV_TICK_CUSTOM_INCLUDE "bh_time.h" /*Header for the sys time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (_bh_time_get_boot_millisecond()) /*Expression evaluating to current systime in ms*/
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/
|
||||
typedef void * lv_indev_drv_user_data_t; /*Type of user data in the input device driver*/
|
||||
|
||||
/*================
|
||||
* Log settings
|
||||
*===============*/
|
||||
|
||||
/*1: Enable the log module*/
|
||||
#define LV_USE_LOG 1
|
||||
#if LV_USE_LOG
|
||||
/* How important log should be added:
|
||||
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
|
||||
* LV_LOG_LEVEL_INFO Log important events
|
||||
* LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem
|
||||
* LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||
* LV_LOG_LEVEL_NONE Do not log anything
|
||||
*/
|
||||
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/* 1: Print the log with 'printf';
|
||||
* 0: user need to register a callback with `lv_log_register_print`*/
|
||||
# define LV_LOG_PRINTF 1
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*================
|
||||
* THEME USAGE
|
||||
*================*/
|
||||
#define LV_THEME_LIVE_UPDATE 1 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/
|
||||
|
||||
#define LV_USE_THEME_TEMPL 1 /*Just for test*/
|
||||
#define LV_USE_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/
|
||||
#define LV_USE_THEME_ALIEN 1 /*Dark futuristic theme*/
|
||||
#define LV_USE_THEME_NIGHT 1 /*Dark elegant theme*/
|
||||
#define LV_USE_THEME_MONO 1 /*Mono color theme for monochrome displays*/
|
||||
#define LV_USE_THEME_MATERIAL 1 /*Flat theme with bold colors and light shadows*/
|
||||
#define LV_USE_THEME_ZEN 1 /*Peaceful, mainly light theme */
|
||||
#define LV_USE_THEME_NEMO 1 /*Water-like theme based on the movie "Finding Nemo"*/
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel.
|
||||
* The symbols are available via `LV_SYMBOL_...` defines
|
||||
* More info about fonts: https://docs.littlevgl.com/#Fonts
|
||||
* To create a new font go to: https://littlevgl.com/ttf-font-to-c-array
|
||||
*/
|
||||
|
||||
/* Robot fonts with bpp = 4
|
||||
* https://fonts.google.com/specimen/Roboto */
|
||||
#define LV_FONT_ROBOTO_12 1
|
||||
#define LV_FONT_ROBOTO_16 1
|
||||
#define LV_FONT_ROBOTO_22 1
|
||||
#define LV_FONT_ROBOTO_28 1
|
||||
|
||||
/*Pixel perfect monospace font
|
||||
* http://pelulamu.net/unscii/ */
|
||||
#define LV_FONT_UNSCII_8 1
|
||||
|
||||
/* Optionally declare your custom fonts here.
|
||||
* You can use these fonts as default font too
|
||||
* and they will be available globally. E.g.
|
||||
* #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \
|
||||
* LV_FONT_DECLARE(my_font_2)
|
||||
*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font from the built-in fonts*/
|
||||
#define LV_FONT_DEFAULT &lv_font_roboto_16
|
||||
|
||||
/* Enable it if you have fonts with a lot of characters.
|
||||
* The limit depends on the font size, font face and bpp
|
||||
* but with > 10,000 characters if you see issues probably you need to enable it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 1
|
||||
|
||||
/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_font_user_data_t;
|
||||
|
||||
/*=================
|
||||
* Text settings
|
||||
*=================*/
|
||||
|
||||
/* Select a character encoding for strings.
|
||||
* Your IDE or editor should have the same character encoding
|
||||
* - LV_TXT_ENC_UTF8
|
||||
* - LV_TXT_ENC_ASCII
|
||||
* */
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/*===================
|
||||
* LV_OBJ SETTINGS
|
||||
*==================*/
|
||||
|
||||
/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_obj_user_data_t;
|
||||
|
||||
/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/
|
||||
#define LV_USE_OBJ_REALIGN 1
|
||||
|
||||
/* Enable to make the object clickable on a larger area.
|
||||
* LV_EXT_CLICK_AREA_OFF or 0: Disable this feature
|
||||
* LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px)
|
||||
* LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px)
|
||||
*/
|
||||
#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_FULL
|
||||
|
||||
/*==================
|
||||
* LV OBJ X USAGE
|
||||
*================*/
|
||||
/*
|
||||
* Documentation of the object types: https://docs.littlevgl.com/#Object-types
|
||||
*/
|
||||
|
||||
/*Arc (dependencies: -)*/
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
/*Bar (dependencies: -)*/
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
/*Button (dependencies: lv_cont*/
|
||||
#define LV_USE_BTN 1
|
||||
#if LV_USE_BTN != 0
|
||||
/*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/
|
||||
# define LV_BTN_INK_EFFECT 1
|
||||
#endif
|
||||
|
||||
/*Button matrix (dependencies: -)*/
|
||||
#define LV_USE_BTNM 1
|
||||
|
||||
/*Calendar (dependencies: -)*/
|
||||
#define LV_USE_CALENDAR 1
|
||||
|
||||
/*Canvas (dependencies: lv_img)*/
|
||||
#define LV_USE_CANVAS 1
|
||||
|
||||
/*Check box (dependencies: lv_btn, lv_label)*/
|
||||
#define LV_USE_CB 1
|
||||
|
||||
/*Chart (dependencies: -)*/
|
||||
#define LV_USE_CHART 1
|
||||
#if LV_USE_CHART
|
||||
# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20
|
||||
#endif
|
||||
|
||||
/*Container (dependencies: -*/
|
||||
#define LV_USE_CONT 1
|
||||
|
||||
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
|
||||
#define LV_USE_DDLIST 1
|
||||
#if LV_USE_DDLIST != 0
|
||||
/*Open and close default animation time [ms] (0: no animation)*/
|
||||
# define LV_DDLIST_DEF_ANIM_TIME 200
|
||||
#endif
|
||||
|
||||
/*Gauge (dependencies:lv_bar, lv_lmeter)*/
|
||||
#define LV_USE_GAUGE 1
|
||||
|
||||
/*Image (dependencies: lv_label*/
|
||||
#define LV_USE_IMG 1
|
||||
|
||||
/*Image Button (dependencies: lv_btn*/
|
||||
#define LV_USE_IMGBTN 1
|
||||
#if LV_USE_IMGBTN
|
||||
/*1: The imgbtn requires left, mid and right parts and the width can be set freely*/
|
||||
# define LV_IMGBTN_TILED 0
|
||||
#endif
|
||||
|
||||
/*Keyboard (dependencies: lv_btnm)*/
|
||||
#define LV_USE_KB 1
|
||||
|
||||
/*Label (dependencies: -*/
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL != 0
|
||||
/*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/
|
||||
# define LV_LABEL_DEF_SCROLL_SPEED 25
|
||||
|
||||
/* Waiting period at beginning/end of animation cycle */
|
||||
# define LV_LABEL_WAIT_CHAR_COUNT 3
|
||||
|
||||
/*Enable selecting text of the label */
|
||||
# define LV_LABEL_TEXT_SEL 1
|
||||
|
||||
/*Store extra some info in labels (12 bytes) to speed up drawing of very long texts*/
|
||||
# define LV_LABEL_LONG_TXT_HINT 0
|
||||
#endif
|
||||
|
||||
/*LED (dependencies: -)*/
|
||||
#define LV_USE_LED 1
|
||||
|
||||
/*Line (dependencies: -*/
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/
|
||||
#define LV_USE_LIST 1
|
||||
#if LV_USE_LIST != 0
|
||||
/*Default animation time of focusing to a list element [ms] (0: no animation) */
|
||||
# define LV_LIST_DEF_ANIM_TIME 100
|
||||
#endif
|
||||
|
||||
/*Line meter (dependencies: *;)*/
|
||||
#define LV_USE_LMETER 1
|
||||
|
||||
/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
|
||||
#define LV_USE_MBOX 1
|
||||
|
||||
/*Page (dependencies: lv_cont)*/
|
||||
#define LV_USE_PAGE 1
|
||||
#if LV_USE_PAGE != 0
|
||||
/*Focus default animation time [ms] (0: no animation)*/
|
||||
# define LV_PAGE_DEF_ANIM_TIME 400
|
||||
#endif
|
||||
|
||||
/*Preload (dependencies: lv_arc, lv_anim)*/
|
||||
#define LV_USE_PRELOAD 1
|
||||
#if LV_USE_PRELOAD != 0
|
||||
# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
|
||||
# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
|
||||
# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC
|
||||
#endif
|
||||
|
||||
/*Roller (dependencies: lv_ddlist)*/
|
||||
#define LV_USE_ROLLER 1
|
||||
#if LV_USE_ROLLER != 0
|
||||
/*Focus animation time [ms] (0: no animation)*/
|
||||
# define LV_ROLLER_DEF_ANIM_TIME 200
|
||||
|
||||
/*Number of extra "pages" when the roller is infinite*/
|
||||
# define LV_ROLLER_INF_PAGES 7
|
||||
#endif
|
||||
|
||||
/*Slider (dependencies: lv_bar)*/
|
||||
#define LV_USE_SLIDER 1
|
||||
|
||||
/*Spinbox (dependencies: lv_ta)*/
|
||||
#define LV_USE_SPINBOX 1
|
||||
|
||||
/*Switch (dependencies: lv_slider)*/
|
||||
#define LV_USE_SW 1
|
||||
|
||||
/*Text area (dependencies: lv_label, lv_page)*/
|
||||
#define LV_USE_TA 1
|
||||
#if LV_USE_TA != 0
|
||||
# define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/
|
||||
# define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
/*Table (dependencies: lv_label)*/
|
||||
#define LV_USE_TABLE 1
|
||||
#if LV_USE_TABLE
|
||||
# define LV_TABLE_COL_MAX 12
|
||||
#endif
|
||||
|
||||
/*Tab (dependencies: lv_page, lv_btnm)*/
|
||||
#define LV_USE_TABVIEW 1
|
||||
# if LV_USE_TABVIEW != 0
|
||||
/*Time of slide animation [ms] (0: no animation)*/
|
||||
# define LV_TABVIEW_DEF_ANIM_TIME 300
|
||||
#endif
|
||||
|
||||
/*Tileview (dependencies: lv_page) */
|
||||
#define LV_USE_TILEVIEW 1
|
||||
#if LV_USE_TILEVIEW
|
||||
/*Time of slide animation [ms] (0: no animation)*/
|
||||
# define LV_TILEVIEW_DEF_ANIM_TIME 300
|
||||
#endif
|
||||
|
||||
/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/
|
||||
#define LV_USE_WIN 1
|
||||
|
||||
/*==================
|
||||
* Non-user section
|
||||
*==================*/
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
/*Be sure every define has a default value*/
|
||||
#include "lvgl/src/lv_conf_checker.h"
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
||||
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
static bool is_little_endian()
|
||||
{
|
||||
long i = 0x01020304;
|
||||
unsigned char* c = (unsigned char*) &i;
|
||||
return (*c == 0x04) ? true : false;
|
||||
}
|
||||
|
||||
static void swap32(uint8* pData)
|
||||
{
|
||||
uint8 value = *pData;
|
||||
*pData = *(pData + 3);
|
||||
*(pData + 3) = value;
|
||||
|
||||
value = *(pData + 1);
|
||||
*(pData + 1) = *(pData + 2);
|
||||
*(pData + 2) = value;
|
||||
}
|
||||
|
||||
static void swap16(uint8* pData)
|
||||
{
|
||||
uint8 value = *pData;
|
||||
*(pData) = *(pData + 1);
|
||||
*(pData + 1) = value;
|
||||
}
|
||||
|
||||
uint32 htonl(uint32 value)
|
||||
{
|
||||
uint32 ret;
|
||||
if (is_little_endian()) {
|
||||
ret = value;
|
||||
swap32((uint8*) &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32 ntohl(uint32 value)
|
||||
{
|
||||
return htonl(value);
|
||||
}
|
||||
|
||||
uint16 htons(uint16 value)
|
||||
{
|
||||
uint16 ret;
|
||||
if (is_little_endian()) {
|
||||
ret = value;
|
||||
swap16((uint8 *)&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16 ntohs(uint16 value)
|
||||
{
|
||||
return htons(value);
|
||||
}
|
||||
|
||||
char *wa_strdup(const char *s)
|
||||
{
|
||||
char *s1 = NULL;
|
||||
if (s && (s1 = wa_malloc(strlen(s) + 1)))
|
||||
memcpy(s1, s, strlen(s) + 1);
|
||||
return s1;
|
||||
}
|
||||
|
||||
#define RSIZE_MAX 0x7FFFFFFF
|
||||
int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n)
|
||||
{
|
||||
char *dest = (char*) s1;
|
||||
char *src = (char*) s2;
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s1 == NULL || s1max > RSIZE_MAX) {
|
||||
return -1;
|
||||
}
|
||||
if (s2 == NULL || n > s1max) {
|
||||
memset(dest, 0, s1max);
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, src, n);
|
||||
return 0;
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
|
||||
#define DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL ((void*) 0)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
// all wasm-app<->native shared source files should use wa_malloc/wa_free.
|
||||
// they will be mapped to different implementations in each side
|
||||
#ifndef wa_malloc
|
||||
#define wa_malloc malloc
|
||||
#endif
|
||||
|
||||
#ifndef wa_free
|
||||
#define wa_free free
|
||||
#endif
|
||||
|
||||
char *wa_strdup(const char *s);
|
||||
|
||||
uint32 htonl(uint32 value);
|
||||
uint32 ntohl(uint32 value);
|
||||
uint16 htons(uint16 value);
|
||||
uint16 ntohs(uint16 value);
|
||||
|
||||
int
|
||||
b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n);
|
||||
|
||||
#endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */
|
||||
@ -1,348 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "attr_container.h"
|
||||
#include "request.h"
|
||||
#include "shared_utils.h"
|
||||
#include "wasm_app.h"
|
||||
#include "req_resp_api.h"
|
||||
#include "timer_api.h"
|
||||
|
||||
#define TRANSACTION_TIMEOUT_MS 5000
|
||||
|
||||
typedef enum {
|
||||
Reg_Event, Reg_Request
|
||||
} reg_type_t;
|
||||
|
||||
typedef struct _res_register {
|
||||
struct _res_register *next;
|
||||
const char * url;
|
||||
reg_type_t reg_type;
|
||||
void (*request_handler)(request_t *);
|
||||
} res_register_t;
|
||||
|
||||
typedef struct transaction {
|
||||
struct transaction *next;
|
||||
int mid;
|
||||
unsigned int time; /* start time */
|
||||
response_handler_f handler;
|
||||
void *user_data;
|
||||
} transaction_t;
|
||||
|
||||
static res_register_t * g_resources = NULL;
|
||||
|
||||
static transaction_t *g_transactions = NULL;
|
||||
|
||||
static user_timer_t g_trans_timer = NULL;
|
||||
|
||||
static transaction_t *transaction_find(int mid)
|
||||
{
|
||||
transaction_t *t = g_transactions;
|
||||
|
||||
while (t) {
|
||||
if (t->mid == mid)
|
||||
return t;
|
||||
t = t->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* new transaction is added to the tail of the list, so the list
|
||||
* is sorted by expiry time naturally.
|
||||
*/
|
||||
static void transaction_add(transaction_t *trans)
|
||||
{
|
||||
transaction_t *t;
|
||||
|
||||
if (g_transactions == NULL) {
|
||||
g_transactions = trans;
|
||||
return;
|
||||
}
|
||||
|
||||
t = g_transactions;
|
||||
while (t) {
|
||||
if (t->next == NULL) {
|
||||
t->next = trans;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void transaction_remove(transaction_t *trans)
|
||||
{
|
||||
transaction_t *prev = NULL, *current = g_transactions;
|
||||
|
||||
while (current) {
|
||||
if (current == trans) {
|
||||
if (prev == NULL) {
|
||||
g_transactions = current->next;
|
||||
free(current);
|
||||
return;
|
||||
}
|
||||
prev->next = current->next;
|
||||
free(current);
|
||||
return;
|
||||
}
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_event_type(request_t * req)
|
||||
{
|
||||
return req->action == COAP_EVENT;
|
||||
}
|
||||
|
||||
static bool register_url_handler(const char *url,
|
||||
request_handler_f request_handler, reg_type_t reg_type)
|
||||
{
|
||||
res_register_t * r = g_resources;
|
||||
|
||||
while (r) {
|
||||
if (reg_type == r->reg_type && strcmp(r->url, url) == 0) {
|
||||
r->request_handler = request_handler;
|
||||
return true;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
|
||||
r = (res_register_t *) malloc(sizeof(res_register_t));
|
||||
if (r == NULL)
|
||||
return false;
|
||||
|
||||
memset(r, 0, sizeof(*r));
|
||||
|
||||
r->url = strdup(url);
|
||||
if (!r->url) {
|
||||
free(r);
|
||||
return false;
|
||||
}
|
||||
|
||||
r->request_handler = request_handler;
|
||||
r->reg_type = reg_type;
|
||||
r->next = g_resources;
|
||||
g_resources = r;
|
||||
|
||||
// tell app mgr to route this url to me
|
||||
if (reg_type == Reg_Request)
|
||||
wasm_register_resource(url);
|
||||
else
|
||||
wasm_sub_event(url);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool api_register_resource_handler(const char *url,
|
||||
request_handler_f request_handler)
|
||||
{
|
||||
return register_url_handler(url, request_handler, Reg_Request);
|
||||
}
|
||||
|
||||
static void transaction_timeout_handler(user_timer_t timer)
|
||||
{
|
||||
transaction_t *cur, *expired = NULL;
|
||||
unsigned int elpased_ms, now = wasm_get_sys_tick_ms();
|
||||
|
||||
/*
|
||||
* Since he transaction list is sorted by expiry time naturally,
|
||||
* we can easily get all expired transactions.
|
||||
* */
|
||||
cur = g_transactions;
|
||||
while (cur) {
|
||||
if (now < cur->time)
|
||||
elpased_ms = now + (0xFFFFFFFF - cur->time) + 1;
|
||||
else
|
||||
elpased_ms = now - cur->time;
|
||||
|
||||
if (elpased_ms >= TRANSACTION_TIMEOUT_MS) {
|
||||
g_transactions = cur->next;
|
||||
cur->next = expired;
|
||||
expired = cur;
|
||||
cur = g_transactions;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* call each transaction's handler with response set to NULL */
|
||||
cur = expired;
|
||||
while (cur) {
|
||||
transaction_t *tmp = cur;
|
||||
cur->handler(NULL, cur->user_data);
|
||||
cur = cur->next;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the transaction list is not empty, restart the timer according
|
||||
* to the first transaction. Otherwise, stop the timer.
|
||||
*/
|
||||
if (g_transactions != NULL) {
|
||||
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
|
||||
if (now < g_transactions->time) {
|
||||
elpased_ms = now + (0xFFFFFFFF - g_transactions->time) + 1;
|
||||
} else {
|
||||
elpased_ms = now - g_transactions->time;
|
||||
}
|
||||
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
||||
api_timer_restart(g_trans_timer, ms_to_expiry);
|
||||
} else {
|
||||
api_timer_cancel(g_trans_timer);
|
||||
g_trans_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
wasm_post_request(buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* APIs for the native layers to callback for request/response arrived to this app
|
||||
*
|
||||
*/
|
||||
|
||||
void on_response(char * buffer, int size)
|
||||
{
|
||||
response_t response[1];
|
||||
transaction_t *trans;
|
||||
|
||||
if (NULL == unpack_response(buffer, size, response)) {
|
||||
printf("unpack response failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((trans = transaction_find(response->mid)) == NULL) {
|
||||
printf("cannot find the transaction\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the 1st transaction get response:
|
||||
* 1. If the 2nd trans exist, restart the timer according to its expiry time;
|
||||
* 2. Otherwise, stop the timer since there is no more transactions;
|
||||
*/
|
||||
if (trans == g_transactions) {
|
||||
if (trans->next != NULL) {
|
||||
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
|
||||
if (now < trans->next->time) {
|
||||
elpased_ms = now + (0xFFFFFFFF - trans->next->time) + 1;
|
||||
} else {
|
||||
elpased_ms = now - trans->next->time;
|
||||
}
|
||||
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
||||
api_timer_restart(g_trans_timer, ms_to_expiry);
|
||||
} else {
|
||||
api_timer_cancel(g_trans_timer);
|
||||
g_trans_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
trans->handler(response, trans->user_data);
|
||||
transaction_remove(trans);
|
||||
}
|
||||
|
||||
void on_request(char *buffer, int size)
|
||||
{
|
||||
request_t request[1];
|
||||
bool is_event;
|
||||
res_register_t *r = g_resources;
|
||||
|
||||
if (NULL == unpack_request(buffer, size, request)) {
|
||||
printf("unpack request failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
is_event = is_event_type(request);
|
||||
|
||||
while (r) {
|
||||
if ((is_event && r->reg_type == Reg_Event)
|
||||
|| (!is_event && r->reg_type == Reg_Request)) {
|
||||
if (check_url_start(request->url, strlen(request->url), r->url)
|
||||
> 0) {
|
||||
r->request_handler(request);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
r = r->next;
|
||||
}
|
||||
|
||||
printf("on_request: exit. no service handler\n");
|
||||
}
|
||||
|
||||
void api_response_send(response_t *response)
|
||||
{
|
||||
int size;
|
||||
char * buffer = pack_response(response, &size);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
wasm_response_send(buffer, size);
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
|
||||
/// event api
|
||||
|
||||
bool api_publish_event(const char *url, int fmt, void *payload, int payload_len)
|
||||
{
|
||||
int size;
|
||||
request_t request[1];
|
||||
init_request(request, (char *)url, COAP_EVENT, fmt, payload, payload_len);
|
||||
char * buffer = pack_request(request, &size);
|
||||
if (buffer == NULL)
|
||||
return false;
|
||||
wasm_post_request(buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool api_subscribe_event(const char * url, request_handler_f handler)
|
||||
{
|
||||
return register_url_handler(url, handler, Reg_Event);
|
||||
}
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AEE_REQUEST_H_
|
||||
#define _AEE_REQUEST_H_
|
||||
|
||||
#include "shared_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @typedef request_handler_f
|
||||
*
|
||||
* @brief Define the signature of callback function for API
|
||||
* api_register_resource_handler() to handle request or for API
|
||||
* api_subscribe_event() to handle event.
|
||||
*
|
||||
* @param request pointer of the request to be handled
|
||||
*
|
||||
* @see api_register_resource_handler
|
||||
* @see api_subscribe_event
|
||||
*/
|
||||
typedef void (*request_handler_f)(request_t *request);
|
||||
|
||||
/**
|
||||
* @typedef response_handler_f
|
||||
*
|
||||
* @brief Define the signature of callback function for API
|
||||
* api_send_request() to handle response of a request.
|
||||
*
|
||||
* @param response pointer of the response to be handled
|
||||
* @param user_data user data associated with the request which is set when
|
||||
* calling api_send_request().
|
||||
*
|
||||
* @see api_send_request
|
||||
*/
|
||||
typedef void (*response_handler_f)(response_t *response, void *user_data);
|
||||
|
||||
|
||||
/*
|
||||
*****************
|
||||
* Request APIs
|
||||
*****************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Register resource.
|
||||
*
|
||||
* @param url url of the resource
|
||||
* @param handler callback function to handle the request to the resource
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool api_register_resource_handler(const char *url, request_handler_f handler);
|
||||
|
||||
/**
|
||||
* @brief Send request asynchronously.
|
||||
*
|
||||
* @param request pointer of the request to be sent
|
||||
* @param response_handler callback function to handle the response
|
||||
* @param user_data user data
|
||||
*/
|
||||
void api_send_request(request_t * request, response_handler_f response_handler,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* @brief Send response.
|
||||
*
|
||||
* @param response pointer of the response to be sent
|
||||
*
|
||||
* @par
|
||||
* @code
|
||||
* void res1_handler(request_t *request)
|
||||
* {
|
||||
* response_t response[1];
|
||||
* make_response_for_request(request, response);
|
||||
* set_response(response, DELETED_2_02, 0, NULL, 0);
|
||||
* api_response_send(response);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
void api_response_send(response_t *response);
|
||||
|
||||
|
||||
/*
|
||||
*****************
|
||||
* Event APIs
|
||||
*****************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Publish an event.
|
||||
*
|
||||
* @param url url of the event
|
||||
* @param fmt format of the event payload
|
||||
* @param payload payload of the event
|
||||
* @param payload_len length in bytes of the event payload
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool api_publish_event(const char *url, int fmt, void *payload,
|
||||
int payload_len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Subscribe an event.
|
||||
*
|
||||
* @param url url of the event
|
||||
* @param handler callback function to handle the event.
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool api_subscribe_event(const char * url, request_handler_f handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "timer_wasm_app.h"
|
||||
#include "timer_api.h"
|
||||
|
||||
#if 1
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#define printf (...)
|
||||
#endif
|
||||
|
||||
struct user_timer {
|
||||
struct user_timer * next;
|
||||
int timer_id;
|
||||
void (*user_timer_callback)(user_timer_t);
|
||||
};
|
||||
|
||||
struct user_timer * g_timers = NULL;
|
||||
|
||||
user_timer_t api_timer_create(int interval, bool is_period, bool auto_start,
|
||||
on_user_timer_update_f on_timer_update)
|
||||
{
|
||||
|
||||
int timer_id = wasm_create_timer(interval, is_period, auto_start);
|
||||
|
||||
//TODO
|
||||
struct user_timer * timer = (struct user_timer *) malloc(
|
||||
sizeof(struct user_timer));
|
||||
if (timer == NULL) {
|
||||
// TODO: remove the timer_id
|
||||
printf("### api_timer_create malloc faild!!! \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(timer, 0, sizeof(*timer));
|
||||
timer->timer_id = timer_id;
|
||||
timer->user_timer_callback = on_timer_update;
|
||||
|
||||
if (g_timers == NULL)
|
||||
g_timers = timer;
|
||||
else {
|
||||
timer->next = g_timers;
|
||||
g_timers = timer;
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
void api_timer_cancel(user_timer_t timer)
|
||||
{
|
||||
user_timer_t t = g_timers, prev = NULL;
|
||||
|
||||
wasm_timer_cancel(timer->timer_id);
|
||||
|
||||
while (t) {
|
||||
if (t == timer) {
|
||||
if (prev == NULL) {
|
||||
g_timers = t->next;
|
||||
free(t);
|
||||
} else {
|
||||
prev->next = t->next;
|
||||
free(t);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
prev = t;
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void api_timer_restart(user_timer_t timer, int interval)
|
||||
{
|
||||
wasm_timer_restart(timer->timer_id, interval);
|
||||
}
|
||||
|
||||
void on_timer_callback(int timer_id)
|
||||
{
|
||||
struct user_timer * t = g_timers;
|
||||
|
||||
while (t) {
|
||||
if (t->timer_id == timer_id) {
|
||||
t->user_timer_callback(t);
|
||||
break;
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AEE_TIMER_H_
|
||||
#define _AEE_TIMER_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* board producer define user_timer */
|
||||
struct user_timer;
|
||||
typedef struct user_timer * user_timer_t;
|
||||
|
||||
/**
|
||||
* @typedef on_user_timer_update_f
|
||||
*
|
||||
* @brief Define the signature of callback function for API api_timer_create().
|
||||
*
|
||||
* @param timer the timer
|
||||
*
|
||||
* @see api_timer_create
|
||||
*/
|
||||
typedef void (*on_user_timer_update_f)(user_timer_t timer);
|
||||
|
||||
/*
|
||||
*****************
|
||||
* Timer APIs
|
||||
*****************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Create timer.
|
||||
*
|
||||
* @param interval timer interval
|
||||
* @param is_period whether the timer is periodic
|
||||
* @param auto_start whether start the timer immediately after created
|
||||
* @param on_timer_update callback function called when timer expired
|
||||
*
|
||||
* @return the timer created if success, NULL otherwise
|
||||
*/
|
||||
user_timer_t api_timer_create(int interval, bool is_period, bool auto_start,
|
||||
on_user_timer_update_f on_timer_update);
|
||||
|
||||
/**
|
||||
* @brief Cancel timer.
|
||||
*
|
||||
* @param timer the timer to cancel
|
||||
*/
|
||||
void api_timer_cancel(user_timer_t timer);
|
||||
|
||||
/**
|
||||
* @brief Restart timer.
|
||||
*
|
||||
* @param timer the timer to cancel
|
||||
* @param interval the timer interval
|
||||
*/
|
||||
void api_timer_restart(user_timer_t timer, int interval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
#ifndef _LIB_AEE_H_
|
||||
#define _LIB_AEE_H_
|
||||
|
||||
#include "shared_utils.h"
|
||||
#include "attr_container.h"
|
||||
#include "request.h"
|
||||
#include "sensor.h"
|
||||
#include "connection.h"
|
||||
#include "timer_wasm_app.h"
|
||||
|
||||
#if ENABLE_WGL != 0
|
||||
#include "wgl.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CoAP request method codes */
|
||||
typedef enum {
|
||||
COAP_GET = 1,
|
||||
COAP_POST,
|
||||
COAP_PUT,
|
||||
COAP_DELETE,
|
||||
COAP_EVENT = (COAP_DELETE + 2)
|
||||
} coap_method_t;
|
||||
|
||||
/* CoAP response codes */
|
||||
typedef enum {
|
||||
NO_ERROR = 0,
|
||||
|
||||
CREATED_2_01 = 65, /* CREATED */
|
||||
DELETED_2_02 = 66, /* DELETED */
|
||||
VALID_2_03 = 67, /* NOT_MODIFIED */
|
||||
CHANGED_2_04 = 68, /* CHANGED */
|
||||
CONTENT_2_05 = 69, /* OK */
|
||||
CONTINUE_2_31 = 95, /* CONTINUE */
|
||||
|
||||
BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */
|
||||
UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */
|
||||
BAD_OPTION_4_02 = 130, /* BAD_OPTION */
|
||||
FORBIDDEN_4_03 = 131, /* FORBIDDEN */
|
||||
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
||||
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
||||
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
||||
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
||||
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
||||
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
||||
|
||||
INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */
|
||||
NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */
|
||||
BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */
|
||||
SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */
|
||||
GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */
|
||||
PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */
|
||||
|
||||
/* Erbium errors */
|
||||
MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR,
|
||||
|
||||
/* Erbium hooks */
|
||||
MANUAL_RESPONSE, PING_RESPONSE
|
||||
} coap_status_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _LIB_AEE_H_ */
|
||||
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "connection.h"
|
||||
#include "connection_api.h"
|
||||
|
||||
/* Raw connection structure */
|
||||
typedef struct _connection {
|
||||
/* Next connection */
|
||||
struct _connection *next;
|
||||
|
||||
/* Handle of the connection */
|
||||
uint32 handle;
|
||||
|
||||
/* Callback function called when event on this connection occurs */
|
||||
on_connection_event_f on_event;
|
||||
|
||||
/* User data */
|
||||
void *user_data;
|
||||
} connection_t;
|
||||
|
||||
/* Raw connections list */
|
||||
static connection_t *g_conns = NULL;
|
||||
|
||||
connection_t *api_open_connection(const char *name,
|
||||
attr_container_t *args,
|
||||
on_connection_event_f on_event,
|
||||
void *user_data)
|
||||
{
|
||||
connection_t *conn;
|
||||
char *args_buffer = (char *)args;
|
||||
uint32 handle, args_len = attr_container_get_serialize_length(args);
|
||||
|
||||
handle = wasm_open_connection(name, args_buffer, args_len);
|
||||
if (handle == -1)
|
||||
return NULL;
|
||||
|
||||
conn = (connection_t *)malloc(sizeof(*conn));
|
||||
if (conn == NULL) {
|
||||
wasm_close_connection(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(conn, 0, sizeof(*conn));
|
||||
conn->handle = handle;
|
||||
conn->on_event = on_event;
|
||||
conn->user_data = user_data;
|
||||
|
||||
if (g_conns != NULL) {
|
||||
conn->next = g_conns;
|
||||
g_conns = conn;
|
||||
} else {
|
||||
g_conns = conn;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
void api_close_connection(connection_t *c)
|
||||
{
|
||||
connection_t *conn = g_conns, *prev = NULL;
|
||||
|
||||
while (conn) {
|
||||
if (conn == c) {
|
||||
wasm_close_connection(c->handle);
|
||||
if (prev != NULL)
|
||||
prev->next = conn->next;
|
||||
else
|
||||
g_conns = conn->next;
|
||||
free(conn);
|
||||
return;
|
||||
} else {
|
||||
prev = conn;
|
||||
conn = conn->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int api_send_on_connection(connection_t *conn, const char *data, uint32 len)
|
||||
{
|
||||
return wasm_send_on_connection(conn->handle, data, len);
|
||||
}
|
||||
|
||||
bool api_config_connection(connection_t *conn, attr_container_t *cfg)
|
||||
{
|
||||
char *cfg_buffer = (char *)cfg;
|
||||
uint32 cfg_len = attr_container_get_serialize_length(cfg);
|
||||
|
||||
return wasm_config_connection(conn->handle, cfg_buffer, cfg_len);
|
||||
}
|
||||
|
||||
void on_connection_data(uint32 handle, char *buffer, uint32 len)
|
||||
{
|
||||
connection_t *conn = g_conns;
|
||||
|
||||
while (conn != NULL) {
|
||||
if (conn->handle == handle) {
|
||||
if (len == 0) {
|
||||
conn->on_event(conn,
|
||||
CONN_EVENT_TYPE_DISCONNECT,
|
||||
NULL,
|
||||
0,
|
||||
conn->user_data);
|
||||
} else {
|
||||
conn->on_event(conn,
|
||||
CONN_EVENT_TYPE_DATA,
|
||||
buffer,
|
||||
len,
|
||||
conn->user_data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
conn = conn->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _CONNECTION_H_
|
||||
#define _CONNECTION_H_
|
||||
|
||||
#include "attr_container.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _connection;
|
||||
typedef struct _connection connection_t;
|
||||
|
||||
/* Connection event type */
|
||||
typedef enum {
|
||||
/* Data is received */
|
||||
CONN_EVENT_TYPE_DATA = 1,
|
||||
/* Connection is disconnected */
|
||||
CONN_EVENT_TYPE_DISCONNECT
|
||||
} conn_event_type_t;
|
||||
|
||||
/*
|
||||
* @typedef on_connection_event_f
|
||||
*
|
||||
* @param conn the connection that the event belongs to
|
||||
* @param type event type
|
||||
* @param data the data received for CONN_EVENT_TYPE_DATA event
|
||||
* @param len length of the data in byte
|
||||
* @param user_data user data
|
||||
*/
|
||||
typedef void (*on_connection_event_f)(connection_t *conn,
|
||||
conn_event_type_t type,
|
||||
const char *data,
|
||||
uint32 len,
|
||||
void *user_data);
|
||||
|
||||
/*
|
||||
*****************
|
||||
* Connection API's
|
||||
*****************
|
||||
*/
|
||||
|
||||
/*
|
||||
* @brief Open a connection.
|
||||
*
|
||||
* @param name name of the connection, "TCP", "UDP" or "UART"
|
||||
* @param args connection arguments, such as: ip:127.0.0.1, port:8888
|
||||
* @param on_event callback function called when event occurs
|
||||
* @param user_data user data
|
||||
*
|
||||
* @return the connection or NULL means fail
|
||||
*/
|
||||
connection_t *api_open_connection(const char *name,
|
||||
attr_container_t *args,
|
||||
on_connection_event_f on_event,
|
||||
void *user_data);
|
||||
|
||||
/*
|
||||
* @brief Close a connection.
|
||||
*
|
||||
* @param conn connection
|
||||
*/
|
||||
void api_close_connection(connection_t *conn);
|
||||
|
||||
/*
|
||||
* Send data to the connection in non-blocking manner which returns immediately
|
||||
*
|
||||
* @param conn the connection
|
||||
* @param data data buffer to be sent
|
||||
* @param len length of the data in byte
|
||||
*
|
||||
* @return actual length sent, or -1 if fail(maybe underlying buffer is full)
|
||||
*/
|
||||
int api_send_on_connection(connection_t *conn, const char *data, uint32 len);
|
||||
|
||||
/*
|
||||
* @brief Configure connection.
|
||||
*
|
||||
* @param conn the connection
|
||||
* @param cfg configurations
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool api_config_connection(connection_t *conn, attr_container_t *cfg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,8 +0,0 @@
|
||||
MIT licence
|
||||
Copyright (c) 2016 Gábor Kiss-Vámosi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_BTN_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_BTN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Possible states of a button.
|
||||
* It can be used not only by buttons but other button-like objects too*/
|
||||
enum {
|
||||
/**Released*/
|
||||
WGL_BTN_STATE_REL,
|
||||
|
||||
/**Pressed*/
|
||||
WGL_BTN_STATE_PR,
|
||||
|
||||
/**Toggled released*/
|
||||
WGL_BTN_STATE_TGL_REL,
|
||||
|
||||
/**Toggled pressed*/
|
||||
WGL_BTN_STATE_TGL_PR,
|
||||
|
||||
/**Inactive*/
|
||||
WGL_BTN_STATE_INA,
|
||||
|
||||
/**Number of states*/
|
||||
_WGL_BTN_STATE_NUM,
|
||||
};
|
||||
typedef uint8_t wgl_btn_state_t;
|
||||
|
||||
/**Styles*/
|
||||
enum {
|
||||
/** Release style */
|
||||
WGL_BTN_STYLE_REL,
|
||||
|
||||
/**Pressed style*/
|
||||
WGL_BTN_STYLE_PR,
|
||||
|
||||
/** Toggle released style*/
|
||||
WGL_BTN_STYLE_TGL_REL,
|
||||
|
||||
/** Toggle pressed style */
|
||||
WGL_BTN_STYLE_TGL_PR,
|
||||
|
||||
/** Inactive style*/
|
||||
WGL_BTN_STYLE_INA,
|
||||
};
|
||||
typedef uint8_t wgl_btn_style_t;
|
||||
|
||||
|
||||
/* Create a button */
|
||||
wgl_obj_t wgl_btn_create(wgl_obj_t par, wgl_obj_t copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Enable the toggled states. On release the button will change from/to toggled state.
|
||||
* @param btn pointer to a button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
void wgl_btn_set_toggle(wgl_obj_t btn, bool tgl);
|
||||
|
||||
/**
|
||||
* Set the state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param state the new state of the button (from wgl_btn_state_t enum)
|
||||
*/
|
||||
void wgl_btn_set_state(wgl_obj_t btn, wgl_btn_state_t state);
|
||||
|
||||
/**
|
||||
* Toggle the state of the button (ON->OFF, OFF->ON)
|
||||
* @param btn pointer to a button object
|
||||
*/
|
||||
void wgl_btn_toggle(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Set time of the ink effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void wgl_btn_set_ink_in_time(wgl_obj_t btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void wgl_btn_set_ink_wait_time(wgl_obj_t btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set time of the ink out effect (animate to the released state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void wgl_btn_set_ink_out_time(wgl_obj_t btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set a style of a button.
|
||||
* @param btn pointer to button object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
//void wgl_btn_set_style(wgl_obj_t btn, wgl_btn_style_t type, const wgl_style_t * style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return the state of the button (from wgl_btn_state_t enum)
|
||||
*/
|
||||
wgl_btn_state_t wgl_btn_get_state(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return true: toggle enabled, false: disabled
|
||||
*/
|
||||
bool wgl_btn_get_toggle(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Get time of the ink in effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t wgl_btn_get_ink_in_time(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Get the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t wgl_btn_get_ink_wait_time(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Get time of the ink out effect (animate to the releases state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t wgl_btn_get_ink_out_time(wgl_obj_t btn);
|
||||
|
||||
/**
|
||||
* Get style of a button.
|
||||
* @param btn pointer to button object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
//const wgl_style_t * wgl_btn_get_style(const wgl_obj_t btn, wgl_btn_style_t type);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_BTN_H */
|
||||
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_CB_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_CB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Checkbox styles. */
|
||||
enum {
|
||||
WGL_CB_STYLE_BG, /**< Style of object background. */
|
||||
WGL_CB_STYLE_BOX_REL, /**< Style of box (released). */
|
||||
WGL_CB_STYLE_BOX_PR, /**< Style of box (pressed). */
|
||||
WGL_CB_STYLE_BOX_TGL_REL, /**< Style of box (released but checked). */
|
||||
WGL_CB_STYLE_BOX_TGL_PR, /**< Style of box (pressed and checked). */
|
||||
WGL_CB_STYLE_BOX_INA, /**< Style of disabled box */
|
||||
};
|
||||
typedef uint8_t wgl_cb_style_t;
|
||||
|
||||
|
||||
/**
|
||||
* Create a check box objects
|
||||
* @param par pointer to an object, it will be the parent of the new check box
|
||||
* @param copy pointer to a check box object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created check box
|
||||
*/
|
||||
wgl_obj_t wgl_cb_create(wgl_obj_t par, const wgl_obj_t copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of a check box. `txt` will be copied and may be deallocated
|
||||
* after this function returns.
|
||||
* @param cb pointer to a check box
|
||||
* @param txt the text of the check box. NULL to refresh with the current text.
|
||||
*/
|
||||
void wgl_cb_set_text(wgl_obj_t cb, const char * txt);
|
||||
|
||||
/**
|
||||
* Set the text of a check box. `txt` must not be deallocated during the life
|
||||
* of this checkbox.
|
||||
* @param cb pointer to a check box
|
||||
* @param txt the text of the check box. NULL to refresh with the current text.
|
||||
*/
|
||||
void wgl_cb_set_static_text(wgl_obj_t cb, const char * txt);
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
|
||||
/**
|
||||
* Get the length of the text of a check box
|
||||
* @param label the check box object
|
||||
* @return the length of the text of the check box
|
||||
*/
|
||||
unsigned int wgl_cb_get_text_length(wgl_obj_t cb);
|
||||
|
||||
/**
|
||||
* Get the text of a check box
|
||||
* @param label the check box object
|
||||
* @param buffer buffer to save the text
|
||||
* @param buffer_len length of the buffer
|
||||
* @return the text of the check box, note that the text will be truncated if buffer is not long enough
|
||||
*/
|
||||
char *wgl_cb_get_text(wgl_obj_t cb, char *buffer, int buffer_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_CB_H */
|
||||
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_LABEL_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_LABEL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Long mode behaviors. Used in 'wgl_label_ext_t' */
|
||||
enum {
|
||||
WGL_LABEL_LONG_EXPAND, /**< Expand the object size to the text size*/
|
||||
WGL_LABEL_LONG_BREAK, /**< Keep the object width, break the too long lines and expand the object
|
||||
height*/
|
||||
WGL_LABEL_LONG_DOT, /**< Keep the size and write dots at the end if the text is too long*/
|
||||
WGL_LABEL_LONG_SROLL, /**< Keep the size and roll the text back and forth*/
|
||||
WGL_LABEL_LONG_SROLL_CIRC, /**< Keep the size and roll the text circularly*/
|
||||
WGL_LABEL_LONG_CROP, /**< Keep the size and crop the text out of it*/
|
||||
};
|
||||
typedef uint8_t wgl_label_long_mode_t;
|
||||
|
||||
/** Label align policy*/
|
||||
enum {
|
||||
WGL_LABEL_ALIGN_LEFT, /**< Align text to left */
|
||||
WGL_LABEL_ALIGN_CENTER, /**< Align text to center */
|
||||
WGL_LABEL_ALIGN_RIGHT, /**< Align text to right */
|
||||
};
|
||||
typedef uint8_t wgl_label_align_t;
|
||||
|
||||
/** Label styles*/
|
||||
enum {
|
||||
WGL_LABEL_STYLE_MAIN,
|
||||
};
|
||||
typedef uint8_t wgl_label_style_t;
|
||||
|
||||
/* Create a label */
|
||||
wgl_obj_t wgl_label_create(wgl_obj_t par, wgl_obj_t copy);
|
||||
|
||||
/* Set text for the label */
|
||||
void wgl_label_set_text(wgl_obj_t label, const char * text);
|
||||
|
||||
/**
|
||||
* Get the length of the text of a label
|
||||
* @param label the label object
|
||||
* @return the length of the text of the label
|
||||
*/
|
||||
unsigned int wgl_label_get_text_length(wgl_obj_t label);
|
||||
|
||||
/**
|
||||
* Get the text of a label
|
||||
* @param label the label object
|
||||
* @param buffer buffer to save the text
|
||||
* @param buffer_len length of the buffer
|
||||
* @return the text of the label, note that the text will be truncated if buffer is not long enough
|
||||
*/
|
||||
char *wgl_label_get_text(wgl_obj_t label, char *buffer, int buffer_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_LABEL_H */
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_LIST_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** List styles. */
|
||||
enum {
|
||||
WGL_LIST_STYLE_BG, /**< List background style */
|
||||
WGL_LIST_STYLE_SCRL, /**< List scrollable area style. */
|
||||
WGL_LIST_STYLE_SB, /**< List scrollbar style. */
|
||||
WGL_LIST_STYLE_EDGE_FLASH, /**< List edge flash style. */
|
||||
WGL_LIST_STYLE_BTN_REL, /**< Same meaning as the ordinary button styles. */
|
||||
WGL_LIST_STYLE_BTN_PR,
|
||||
WGL_LIST_STYLE_BTN_TGL_REL,
|
||||
WGL_LIST_STYLE_BTN_TGL_PR,
|
||||
WGL_LIST_STYLE_BTN_INA,
|
||||
};
|
||||
typedef uint8_t wgl_list_style_t;
|
||||
|
||||
|
||||
/**
|
||||
* Create a list objects
|
||||
* @param par pointer to an object, it will be the parent of the new list
|
||||
* @param copy pointer to a list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created list
|
||||
*/
|
||||
wgl_obj_t wgl_list_create(wgl_obj_t par, wgl_obj_t copy);
|
||||
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a list element to the list
|
||||
* @param list pointer to list object
|
||||
* @param img_fn file name of an image before the text (NULL if unused)
|
||||
* @param txt text of the list element (NULL if unused)
|
||||
* @return pointer to the new list element which can be customized (a button)
|
||||
*/
|
||||
wgl_obj_t wgl_list_add_btn(wgl_obj_t list, const void * img_src, const char * txt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_LIST_H */
|
||||
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_OBJ_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void * wgl_obj_t;
|
||||
|
||||
enum {
|
||||
WGL_EVENT_PRESSED, /**< The object has been pressed*/
|
||||
WGL_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/
|
||||
WGL_EVENT_PRESS_LOST, /**< User is still pressing but slid cursor/finger off of the object */
|
||||
WGL_EVENT_SHORT_CLICKED, /**< User pressed object for a short period of time, then released it. Not called if dragged. */
|
||||
WGL_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `WGL_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/
|
||||
WGL_EVENT_LONG_PRESSED_REPEAT, /**< Called after `WGL_INDEV_LONG_PRESS_TIME` in every
|
||||
`WGL_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/
|
||||
WGL_EVENT_CLICKED, /**< Called on release if not dragged (regardless to long press)*/
|
||||
WGL_EVENT_RELEASED, /**< Called in every cases when the object has been released*/
|
||||
WGL_EVENT_DRAG_BEGIN,
|
||||
WGL_EVENT_DRAG_END,
|
||||
WGL_EVENT_DRAG_THROW_BEGIN,
|
||||
WGL_EVENT_KEY,
|
||||
WGL_EVENT_FOCUSED,
|
||||
WGL_EVENT_DEFOCUSED,
|
||||
WGL_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved) */
|
||||
WGL_EVENT_INSERT,
|
||||
WGL_EVENT_REFRESH,
|
||||
WGL_EVENT_APPLY, /**< "Ok", "Apply" or similar specific button has clicked*/
|
||||
WGL_EVENT_CANCEL, /**< "Close", "Cancel" or similar specific button has clicked*/
|
||||
WGL_EVENT_DELETE, /**< Object is being deleted */
|
||||
};
|
||||
typedef uint8_t wgl_event_t; /**< Type of event being sent to the object. */
|
||||
|
||||
|
||||
/** Object alignment. */
|
||||
enum {
|
||||
WGL_ALIGN_CENTER = 0,
|
||||
WGL_ALIGN_IN_TOP_LEFT,
|
||||
WGL_ALIGN_IN_TOP_MID,
|
||||
WGL_ALIGN_IN_TOP_RIGHT,
|
||||
WGL_ALIGN_IN_BOTTOM_LEFT,
|
||||
WGL_ALIGN_IN_BOTTOM_MID,
|
||||
WGL_ALIGN_IN_BOTTOM_RIGHT,
|
||||
WGL_ALIGN_IN_LEFT_MID,
|
||||
WGL_ALIGN_IN_RIGHT_MID,
|
||||
WGL_ALIGN_OUT_TOP_LEFT,
|
||||
WGL_ALIGN_OUT_TOP_MID,
|
||||
WGL_ALIGN_OUT_TOP_RIGHT,
|
||||
WGL_ALIGN_OUT_BOTTOM_LEFT,
|
||||
WGL_ALIGN_OUT_BOTTOM_MID,
|
||||
WGL_ALIGN_OUT_BOTTOM_RIGHT,
|
||||
WGL_ALIGN_OUT_LEFT_TOP,
|
||||
WGL_ALIGN_OUT_LEFT_MID,
|
||||
WGL_ALIGN_OUT_LEFT_BOTTOM,
|
||||
WGL_ALIGN_OUT_RIGHT_TOP,
|
||||
WGL_ALIGN_OUT_RIGHT_MID,
|
||||
WGL_ALIGN_OUT_RIGHT_BOTTOM,
|
||||
};
|
||||
typedef uint8_t wgl_align_t;
|
||||
|
||||
|
||||
enum {
|
||||
WGL_DRAG_DIR_HOR = 0x1, /**< Object can be dragged horizontally. */
|
||||
WGL_DRAG_DIR_VER = 0x2, /**< Object can be dragged vertically. */
|
||||
WGL_DRAG_DIR_ALL = 0x3, /**< Object can be dragged in all directions. */
|
||||
};
|
||||
|
||||
typedef uint8_t wgl_drag_dir_t;
|
||||
|
||||
typedef void (*wgl_event_cb_t)(wgl_obj_t obj, wgl_event_t event);
|
||||
|
||||
void wgl_obj_align(wgl_obj_t obj, wgl_obj_t base, wgl_align_t align, wgl_coord_t x_mod, wgl_coord_t y_mod);
|
||||
void wgl_obj_set_event_cb(wgl_obj_t obj, wgl_event_cb_t event_cb);
|
||||
wgl_res_t wgl_obj_del(wgl_obj_t obj);
|
||||
void wgl_obj_del_async(wgl_obj_t obj);
|
||||
void wgl_obj_clean(wgl_obj_t obj);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_OBJ_H */
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_TYPES_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* WGL error codes.
|
||||
*/
|
||||
enum {
|
||||
WGL_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action
|
||||
function or an operation was failed*/
|
||||
WGL_RES_OK, /*The object is valid (no deleted) after the action*/
|
||||
};
|
||||
typedef uint8_t wgl_res_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_TYPES_H */
|
||||
@ -1,8 +0,0 @@
|
||||
MIT licence
|
||||
Copyright (c) 2016 Gábor Kiss-Vámosi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_BTN_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_BTN_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_btn.h"
|
||||
|
||||
/** Possible states of a button.
|
||||
* It can be used not only by buttons but other button-like objects too*/
|
||||
enum {
|
||||
/**Released*/
|
||||
LV_BTN_STATE_REL,
|
||||
|
||||
/**Pressed*/
|
||||
LV_BTN_STATE_PR,
|
||||
|
||||
/**Toggled released*/
|
||||
LV_BTN_STATE_TGL_REL,
|
||||
|
||||
/**Toggled pressed*/
|
||||
LV_BTN_STATE_TGL_PR,
|
||||
|
||||
/**Inactive*/
|
||||
LV_BTN_STATE_INA,
|
||||
|
||||
/**Number of states*/
|
||||
_LV_BTN_STATE_NUM,
|
||||
};
|
||||
typedef wgl_btn_state_t lv_btn_state_t;
|
||||
|
||||
/**Styles*/
|
||||
enum {
|
||||
/** Release style */
|
||||
LV_BTN_STYLE_REL,
|
||||
|
||||
/**Pressed style*/
|
||||
LV_BTN_STYLE_PR,
|
||||
|
||||
/** Toggle released style*/
|
||||
LV_BTN_STYLE_TGL_REL,
|
||||
|
||||
/** Toggle pressed style */
|
||||
LV_BTN_STYLE_TGL_PR,
|
||||
|
||||
/** Inactive style*/
|
||||
LV_BTN_STYLE_INA,
|
||||
};
|
||||
typedef wgl_btn_style_t lv_btn_style_t;
|
||||
|
||||
|
||||
#define lv_btn_create wgl_btn_create
|
||||
#define lv_btn_set_toggle wgl_btn_set_toggle
|
||||
#define lv_btn_set_state wgl_btn_set_state
|
||||
#define lv_btn_toggle wgl_btn_toggle
|
||||
#define lv_btn_set_ink_in_time wgl_btn_set_ink_in_time
|
||||
#define lv_btn_set_ink_wait_time wgl_btn_set_ink_wait_time
|
||||
#define lv_btn_set_ink_out_time wgl_btn_set_ink_out_time
|
||||
#define lv_btn_get_state wgl_btn_get_state
|
||||
#define lv_btn_get_toggle wgl_btn_get_toggle
|
||||
#define lv_btn_get_ink_in_time wgl_btn_get_ink_in_time
|
||||
#define lv_btn_get_ink_wait_time wgl_btn_get_ink_wait_time
|
||||
#define lv_btn_get_ink_out_time wgl_btn_get_ink_out_time
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_BTN_LVGL_COMPATIBLE_H */
|
||||
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_CB_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_CB_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_cb.h"
|
||||
|
||||
/** Checkbox styles. */
|
||||
enum {
|
||||
LV_CB_STYLE_BG, /**< Style of object background. */
|
||||
LV_CB_STYLE_BOX_REL, /**< Style of box (released). */
|
||||
LV_CB_STYLE_BOX_PR, /**< Style of box (pressed). */
|
||||
LV_CB_STYLE_BOX_TGL_REL, /**< Style of box (released but checked). */
|
||||
LV_CB_STYLE_BOX_TGL_PR, /**< Style of box (pressed and checked). */
|
||||
LV_CB_STYLE_BOX_INA, /**< Style of disabled box */
|
||||
};
|
||||
typedef wgl_cb_style_t lv_cb_style_t;
|
||||
|
||||
|
||||
#define lv_cb_create wgl_cb_create
|
||||
#define lv_cb_set_text wgl_cb_set_text
|
||||
#define lv_cb_set_static_text wgl_cb_set_static_text
|
||||
#define lv_cb_get_text(cb) wgl_cb_get_text(cb, g_widget_text, 100)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_CB_LVGL_COMPATIBLE_H */
|
||||
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_LABEL_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_LABEL_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_label.h"
|
||||
|
||||
/** Long mode behaviors. Used in 'lv_label_ext_t' */
|
||||
enum {
|
||||
LV_LABEL_LONG_EXPAND, /**< Expand the object size to the text size*/
|
||||
LV_LABEL_LONG_BREAK, /**< Keep the object width, break the too long lines and expand the object
|
||||
height*/
|
||||
LV_LABEL_LONG_DOT, /**< Keep the size and write dots at the end if the text is too long*/
|
||||
LV_LABEL_LONG_SROLL, /**< Keep the size and roll the text back and forth*/
|
||||
LV_LABEL_LONG_SROLL_CIRC, /**< Keep the size and roll the text circularly*/
|
||||
LV_LABEL_LONG_CROP, /**< Keep the size and crop the text out of it*/
|
||||
};
|
||||
typedef wgl_label_long_mode_t lv_label_long_mode_t;
|
||||
|
||||
/** Label align policy*/
|
||||
enum {
|
||||
LV_LABEL_ALIGN_LEFT, /**< Align text to left */
|
||||
LV_LABEL_ALIGN_CENTER, /**< Align text to center */
|
||||
LV_LABEL_ALIGN_RIGHT, /**< Align text to right */
|
||||
};
|
||||
typedef wgl_label_align_t lv_label_align_t;
|
||||
|
||||
/** Label styles*/
|
||||
enum {
|
||||
LV_LABEL_STYLE_MAIN,
|
||||
};
|
||||
typedef wgl_label_style_t lv_label_style_t;
|
||||
|
||||
|
||||
#define lv_label_create wgl_label_create
|
||||
#define lv_label_set_text wgl_label_set_text
|
||||
#define lv_label_get_text(label) wgl_label_get_text(label, g_widget_text, 100)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_LABEL_LVGL_COMPATIBLE_H */
|
||||
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_LIST_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_LIST_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_list.h"
|
||||
|
||||
/** List styles. */
|
||||
enum {
|
||||
LV_LIST_STYLE_BG, /**< List background style */
|
||||
LV_LIST_STYLE_SCRL, /**< List scrollable area style. */
|
||||
LV_LIST_STYLE_SB, /**< List scrollbar style. */
|
||||
LV_LIST_STYLE_EDGE_FLASH, /**< List edge flash style. */
|
||||
LV_LIST_STYLE_BTN_REL, /**< Same meaning as the ordinary button styles. */
|
||||
LV_LIST_STYLE_BTN_PR,
|
||||
LV_LIST_STYLE_BTN_TGL_REL,
|
||||
LV_LIST_STYLE_BTN_TGL_PR,
|
||||
LV_LIST_STYLE_BTN_INA,
|
||||
};
|
||||
typedef wgl_list_style_t lv_list_style_t;
|
||||
|
||||
|
||||
#define lv_list_create wgl_list_create
|
||||
#define lv_list_add_btn wgl_list_add_btn
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_LIST_LVGL_COMPATIBLE_H */
|
||||
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_OBJ_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_OBJ_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_obj.h"
|
||||
|
||||
typedef void lv_obj_t;
|
||||
|
||||
enum {
|
||||
LV_EVENT_PRESSED,
|
||||
LV_EVENT_PRESSING,
|
||||
LV_EVENT_PRESS_LOST,
|
||||
LV_EVENT_SHORT_CLICKED,
|
||||
LV_EVENT_LONG_PRESSED,
|
||||
LV_EVENT_LONG_PRESSED_REPEAT,
|
||||
LV_EVENT_CLICKED,
|
||||
LV_EVENT_RELEASED,
|
||||
LV_EVENT_DRAG_BEGIN,
|
||||
LV_EVENT_DRAG_END,
|
||||
LV_EVENT_DRAG_THROW_BEGIN,
|
||||
LV_EVENT_KEY,
|
||||
LV_EVENT_FOCUSED,
|
||||
LV_EVENT_DEFOCUSED,
|
||||
LV_EVENT_VALUE_CHANGED,
|
||||
LV_EVENT_INSERT,
|
||||
LV_EVENT_REFRESH,
|
||||
LV_EVENT_APPLY,
|
||||
LV_EVENT_CANCEL,
|
||||
LV_EVENT_DELETE,
|
||||
};
|
||||
typedef wgl_event_t lv_event_t;
|
||||
|
||||
|
||||
/** Object alignment. */
|
||||
enum {
|
||||
LV_ALIGN_CENTER,
|
||||
LV_ALIGN_IN_TOP_LEFT,
|
||||
LV_ALIGN_IN_TOP_MID,
|
||||
LV_ALIGN_IN_TOP_RIGHT,
|
||||
LV_ALIGN_IN_BOTTOM_LEFT,
|
||||
LV_ALIGN_IN_BOTTOM_MID,
|
||||
LV_ALIGN_IN_BOTTOM_RIGHT,
|
||||
LV_ALIGN_IN_LEFT_MID,
|
||||
LV_ALIGN_IN_RIGHT_MID,
|
||||
LV_ALIGN_OUT_TOP_LEFT,
|
||||
LV_ALIGN_OUT_TOP_MID,
|
||||
LV_ALIGN_OUT_TOP_RIGHT,
|
||||
LV_ALIGN_OUT_BOTTOM_LEFT,
|
||||
LV_ALIGN_OUT_BOTTOM_MID,
|
||||
LV_ALIGN_OUT_BOTTOM_RIGHT,
|
||||
LV_ALIGN_OUT_LEFT_TOP,
|
||||
LV_ALIGN_OUT_LEFT_MID,
|
||||
LV_ALIGN_OUT_LEFT_BOTTOM,
|
||||
LV_ALIGN_OUT_RIGHT_TOP,
|
||||
LV_ALIGN_OUT_RIGHT_MID,
|
||||
LV_ALIGN_OUT_RIGHT_BOTTOM,
|
||||
};
|
||||
typedef wgl_align_t lv_align_t;
|
||||
|
||||
|
||||
enum {
|
||||
LV_DRAG_DIR_HOR,
|
||||
LV_DRAG_DIR_VER,
|
||||
LV_DRAG_DIR_ALL,
|
||||
};
|
||||
|
||||
typedef wgl_drag_dir_t lv_drag_dir_t;
|
||||
|
||||
|
||||
#define lv_obj_align wgl_obj_align
|
||||
#define lv_obj_set_event_cb wgl_obj_set_event_cb
|
||||
#define lv_obj_del wgl_obj_del
|
||||
#define lv_obj_del_async wgl_obj_del_async
|
||||
#define lv_obj_clean wgl_obj_clean
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_OBJ_LVGL_COMPATIBLE_H */
|
||||
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_TYPES_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_TYPES_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../inc/wgl_types.h"
|
||||
|
||||
/**
|
||||
* error codes.
|
||||
*/
|
||||
enum {
|
||||
LV_RES_INV,
|
||||
LV_RES_OK,
|
||||
};
|
||||
typedef wgl_res_t lv_res_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_TYPES_LVGL_COMPATIBLE_H */
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_LVGL_COMPATIBLE_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_LVGL_COMPATIBLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wgl_shared_utils.h" /* shared types between app and native */
|
||||
#include "lvgl-compatible/lv_types.h"
|
||||
#include "lvgl-compatible/lv_obj.h"
|
||||
#include "lvgl-compatible/lv_btn.h"
|
||||
#include "lvgl-compatible/lv_cb.h"
|
||||
#include "lvgl-compatible/lv_label.h"
|
||||
#include "lvgl-compatible/lv_list.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_LVGL_COMPATIBLE_H */
|
||||
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wgl.h"
|
||||
#include "bh_platform.h"
|
||||
#include "gui_api.h"
|
||||
|
||||
#define ARGC sizeof(argv)/sizeof(uint32)
|
||||
#define CALL_BTN_NATIVE_FUNC(id) wasm_btn_native_call(id, argv, ARGC)
|
||||
|
||||
wgl_obj_t wgl_btn_create(wgl_obj_t par, wgl_obj_t copy)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
|
||||
argv[0] = (uint32)par;
|
||||
argv[1] = (uint32)copy;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_CREATE);
|
||||
return (wgl_obj_t)argv[0];
|
||||
}
|
||||
|
||||
void wgl_btn_set_toggle(wgl_obj_t btn, bool tgl)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
argv[1] = tgl;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_SET_TOGGLE);
|
||||
}
|
||||
|
||||
void wgl_btn_set_state(wgl_obj_t btn, wgl_btn_state_t state)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
argv[1] = state;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_SET_STATE);
|
||||
}
|
||||
|
||||
void wgl_btn_toggle(wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_TOGGLE);
|
||||
}
|
||||
|
||||
void wgl_btn_set_ink_in_time(wgl_obj_t btn, uint16_t time)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
argv[1] = time;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_SET_INK_IN_TIME);
|
||||
}
|
||||
|
||||
void wgl_btn_set_ink_wait_time(wgl_obj_t btn, uint16_t time)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
argv[1] = time;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_SET_INK_WAIT_TIME);
|
||||
}
|
||||
|
||||
void wgl_btn_set_ink_out_time(wgl_obj_t btn, uint16_t time)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
argv[1] = time;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_SET_INK_OUT_TIME);
|
||||
}
|
||||
|
||||
//void wgl_btn_set_style(wgl_obj_t btn, wgl_btn_style_t type, const wgl_style_t * style)
|
||||
//{
|
||||
// //TODO: pack style
|
||||
// //wasm_btn_set_style(btn, type, style);
|
||||
//}
|
||||
//
|
||||
wgl_btn_state_t wgl_btn_get_state(const wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_GET_STATE);
|
||||
return (wgl_btn_state_t)argv[0];
|
||||
}
|
||||
|
||||
bool wgl_btn_get_toggle(const wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_GET_TOGGLE);
|
||||
return (bool)argv[0];
|
||||
}
|
||||
|
||||
uint16_t wgl_btn_get_ink_in_time(const wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_GET_INK_IN_TIME);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
uint16_t wgl_btn_get_ink_wait_time(const wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_GET_INK_WAIT_TIME);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
uint16_t wgl_btn_get_ink_out_time(const wgl_obj_t btn)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)btn;
|
||||
CALL_BTN_NATIVE_FUNC(BTN_FUNC_ID_GET_INK_OUT_TIME);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
//
|
||||
//const wgl_style_t * wgl_btn_get_style(const wgl_obj_t btn, wgl_btn_style_t type)
|
||||
//{
|
||||
// //TODO: pack style
|
||||
// //wasm_btn_get_style(btn, type);
|
||||
// return NULL;
|
||||
//}
|
||||
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wgl.h"
|
||||
#include "gui_api.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ARGC sizeof(argv)/sizeof(uint32)
|
||||
#define CALL_CB_NATIVE_FUNC(id) wasm_cb_native_call(id, argv, ARGC)
|
||||
|
||||
wgl_obj_t wgl_cb_create(wgl_obj_t par, const wgl_obj_t copy)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
|
||||
argv[0] = (uint32)par;
|
||||
argv[1] = (uint32)copy;
|
||||
CALL_CB_NATIVE_FUNC(CB_FUNC_ID_CREATE);
|
||||
return (wgl_obj_t)argv[0];
|
||||
}
|
||||
|
||||
void wgl_cb_set_text(wgl_obj_t cb, const char * txt)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)cb;
|
||||
argv[1] = (uint32)txt;
|
||||
argv[2] = strlen(txt) + 1;
|
||||
CALL_CB_NATIVE_FUNC(CB_FUNC_ID_SET_TEXT);
|
||||
}
|
||||
|
||||
void wgl_cb_set_static_text(wgl_obj_t cb, const char * txt)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)cb;
|
||||
argv[1] = (uint32)txt;
|
||||
argv[2] = strlen(txt) + 1;
|
||||
CALL_CB_NATIVE_FUNC(CB_FUNC_ID_SET_STATIC_TEXT);
|
||||
}
|
||||
|
||||
//void wgl_cb_set_style(wgl_obj_t cb, wgl_cb_style_t type, const wgl_style_t * style)
|
||||
//{
|
||||
// //TODO:
|
||||
//}
|
||||
//
|
||||
|
||||
unsigned int wgl_cb_get_text_length(wgl_obj_t cb)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)cb;
|
||||
CALL_CB_NATIVE_FUNC(CB_FUNC_ID_GET_TEXT_LENGTH);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
char *wgl_cb_get_text(wgl_obj_t cb, char *buffer, int buffer_len)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)cb;
|
||||
argv[1] = (uint32)buffer;
|
||||
argv[2] = buffer_len;
|
||||
CALL_CB_NATIVE_FUNC(CB_FUNC_ID_GET_TEXT);
|
||||
return (char *)argv[0];
|
||||
}
|
||||
|
||||
//const wgl_style_t * wgl_cb_get_style(const wgl_obj_t cb, wgl_cb_style_t type)
|
||||
//{
|
||||
// //TODO
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
|
||||
|
||||
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
|
||||
#include "wgl.h"
|
||||
#include "gui_api.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ARGC sizeof(argv)/sizeof(uint32)
|
||||
#define CALL_LABEL_NATIVE_FUNC(id) wasm_label_native_call(id, argv, ARGC)
|
||||
|
||||
wgl_obj_t wgl_label_create(wgl_obj_t par, wgl_obj_t copy)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
|
||||
argv[0] = (uint32)par;
|
||||
argv[1] = (uint32)copy;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_CREATE);
|
||||
return (wgl_obj_t)argv[0];
|
||||
}
|
||||
|
||||
void wgl_label_set_text(wgl_obj_t label, const char * text)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = (uint32)text;
|
||||
argv[2] = strlen(text) + 1;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_TEXT);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_array_text(wgl_obj_t label, const char * array, uint16_t size)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = (uint32)array;
|
||||
argv[2] = size;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_ARRAY_TEXT);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_static_text(wgl_obj_t label, const char * text)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = (uint32)text;
|
||||
argv[2] = strlen(text) + 1;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_STATIC_TEXT);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_long_mode(wgl_obj_t label, wgl_label_long_mode_t long_mode)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = long_mode;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_LONG_MODE);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_align(wgl_obj_t label, wgl_label_align_t align)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = align;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_ALIGN);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_recolor(wgl_obj_t label, bool en)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = en;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_RECOLOR);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_body_draw(wgl_obj_t label, bool en)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = en;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_BODY_DRAW);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_anim_speed(wgl_obj_t label, uint16_t anim_speed)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = anim_speed;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_ANIM_SPEED);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_text_sel_start(wgl_obj_t label, uint16_t index)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = index;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_TEXT_SEL_START);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_set_text_sel_end(wgl_obj_t label, uint16_t index)
|
||||
{
|
||||
uint32 argv[2] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = index;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_SET_TEXT_SEL_END);
|
||||
}
|
||||
|
||||
unsigned int wgl_label_get_text_length(wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_TEXT_LENGTH);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
char * wgl_label_get_text(wgl_obj_t label, char *buffer, int buffer_len)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = (uint32)buffer;
|
||||
argv[2] = buffer_len;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_TEXT);
|
||||
return (char *)argv[0];
|
||||
}
|
||||
|
||||
|
||||
wgl_label_long_mode_t wgl_label_get_long_mode(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_LONG_MODE);
|
||||
return (wgl_label_long_mode_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
wgl_label_align_t wgl_label_get_align(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_ALIGN);
|
||||
return (wgl_label_align_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
bool wgl_label_get_recolor(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_RECOLOR);
|
||||
return (bool)argv[0];
|
||||
}
|
||||
|
||||
|
||||
bool wgl_label_get_body_draw(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_BODY_DRAW);
|
||||
return (bool)argv[0];
|
||||
}
|
||||
|
||||
|
||||
uint16_t wgl_label_get_anim_speed(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_ANIM_SPEED);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_get_letter_pos(const wgl_obj_t label, uint16_t index, wgl_point_t * pos)
|
||||
{
|
||||
uint32 argv[4] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = index;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_LETTER_POS);
|
||||
pos->x = argv[2];
|
||||
pos->y = argv[3];
|
||||
}
|
||||
|
||||
|
||||
uint16_t wgl_label_get_letter_on(const wgl_obj_t label, wgl_point_t * pos)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = pos->x;
|
||||
argv[2] = pos->y;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_LETTER_POS);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
bool wgl_label_is_char_under_pos(const wgl_obj_t label, wgl_point_t * pos)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = pos->x;
|
||||
argv[2] = pos->y;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_LETTER_POS);
|
||||
return (bool)argv[0];
|
||||
}
|
||||
|
||||
|
||||
uint16_t wgl_label_get_text_sel_start(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_TEXT_SEL_START);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
uint16_t wgl_label_get_text_sel_end(const wgl_obj_t label)
|
||||
{
|
||||
uint32 argv[1] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_GET_TEXT_SEL_END);
|
||||
return (uint16_t)argv[0];
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_ins_text(wgl_obj_t label, uint32_t pos, const char * txt)
|
||||
{
|
||||
uint32 argv[4] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = pos;
|
||||
argv[2] = (uint32)txt;
|
||||
argv[3] = strlen(txt) + 1;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_INS_TEXT);
|
||||
}
|
||||
|
||||
|
||||
void wgl_label_cut_text(wgl_obj_t label, uint32_t pos, uint32_t cnt)
|
||||
{
|
||||
uint32 argv[3] = {0};
|
||||
argv[0] = (uint32)label;
|
||||
argv[1] = pos;
|
||||
argv[2] = cnt;
|
||||
CALL_LABEL_NATIVE_FUNC(LABEL_FUNC_ID_CUT_TEXT);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user