enable pthread for AoT && update AOT current version to 2 (#311)

This commit is contained in:
Xu Jun
2020-07-16 20:35:04 +08:00
committed by GitHub
parent ca938f3634
commit 32b2943369
32 changed files with 1549 additions and 584 deletions

View File

@ -344,43 +344,12 @@ fail:
return NULL;
}
static AOTExportFunc *
aot_create_export_funcs(const WASMModule *module,
uint32 export_func_count)
{
AOTExportFunc *export_funcs;
uint64 size;
uint32 i, j = 0;
/* Allocate memory */
size = sizeof(AOTExportFunc) * (uint64)export_func_count;
if (size >= UINT32_MAX
|| !(export_funcs = wasm_runtime_malloc((uint32)size))) {
aot_set_last_error("allocate memory failed.");
return NULL;
}
/* Create each export function */
for (i = 0; i < module->export_count; i++) {
if (module->exports[i].kind == EXPORT_KIND_FUNC) {
export_funcs[j].func_name = module->exports[i].name;
export_funcs[j].func_index = module->exports[i].index;
export_funcs[j].func_type =
module->functions[module->exports[i].index
- module->import_function_count]->func_type;
/* Function pointer to be linked in JIT mode */
export_funcs[j].func_ptr = NULL;
j++;
}
}
return export_funcs;
}
AOTCompData*
aot_create_comp_data(WASMModule *module)
{
AOTCompData *comp_data;
uint32 import_global_data_size = 0, global_data_size = 0, i;
uint32 import_global_data_size = 0, global_data_size = 0, i, j;
uint64 size;
/* Allocate memory */
if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
@ -390,22 +359,49 @@ aot_create_comp_data(WASMModule *module)
memset(comp_data, 0, sizeof(AOTCompData));
/* Set memory page count */
if (module->import_memory_count) {
comp_data->num_bytes_per_page =
module->import_memories[0].u.memory.num_bytes_per_page;
comp_data->mem_init_page_count =
module->import_memories[0].u.memory.init_page_count;
comp_data->mem_max_page_count =
module->import_memories[0].u.memory.max_page_count;
comp_data->memory_count = module->import_memory_count + module->memory_count;
/* TODO: create import memories */
/* Allocate memory for memory array, reserve one AOTMemory space at least */
if (!comp_data->memory_count)
comp_data->memory_count = 1;
size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
if (size >= UINT32_MAX
|| !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
aot_set_last_error("create memories array failed.\n");
goto fail;
}
else if (module->memory_count) {
comp_data->num_bytes_per_page =
module->memories[0].num_bytes_per_page;
comp_data->mem_init_page_count =
module->memories[0].init_page_count;
comp_data->mem_max_page_count =
module->memories[0].max_page_count;
memset(comp_data->memories, 0, size);
/* Set memory page count */
for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
if (i < module->import_memory_count) {
comp_data->memories[i].memory_flags =
module->import_memories[i].u.memory.flags;
comp_data->memories[i].num_bytes_per_page =
module->import_memories[i].u.memory.num_bytes_per_page;
comp_data->memories[i].mem_init_page_count =
module->import_memories[i].u.memory.init_page_count;
comp_data->memories[i].mem_max_page_count =
module->import_memories[i].u.memory.max_page_count;
comp_data->memories[i].num_bytes_per_page =
module->import_memories[i].u.memory.num_bytes_per_page;
}
else {
j = i - module->import_memory_count;
comp_data->memories[i].memory_flags =
module->memories[j].flags;
comp_data->memories[i].num_bytes_per_page =
module->memories[j].num_bytes_per_page;
comp_data->memories[i].mem_init_page_count =
module->memories[j].init_page_count;
comp_data->memories[i].mem_max_page_count =
module->memories[j].max_page_count;
comp_data->memories[i].num_bytes_per_page =
module->memories[j].num_bytes_per_page;
}
}
/* Create memory data segments */
@ -415,11 +411,39 @@ aot_create_comp_data(WASMModule *module)
aot_create_mem_init_data_list(module)))
goto fail;
/* Set table size */
if (module->import_table_count)
comp_data->table_size = module->import_tables[0].u.table.init_size;
else if (module->table_count)
comp_data->table_size = module->tables[0].init_size;
/* TODO: create import tables */
/* Create tables */
comp_data->table_count = module->import_table_count + module->table_count;
if (comp_data->table_count > 0) {
size = sizeof(AOTTable) * (uint64)comp_data->table_count;
if (size >= UINT32_MAX
|| !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
aot_set_last_error("create memories array failed.\n");
goto fail;
}
memset(comp_data->tables, 0, size);
for (i = 0; i < comp_data->table_count; i++) {
if (i < module->import_table_count) {
comp_data->tables[i].elem_type =
module->import_tables[i].u.table.elem_type;
comp_data->tables[i].table_flags =
module->import_tables[i].u.table.flags;
comp_data->tables[i].table_init_size =
module->import_tables[i].u.table.init_size;
comp_data->tables[i].table_max_size =
module->import_tables[i].u.table.max_size;
}
else {
j = i - module->import_table_count;
comp_data->tables[i].elem_type = module->tables[i].elem_type;
comp_data->tables[i].table_flags = module->tables[i].flags;
comp_data->tables[i].table_init_size = module->tables[i].init_size;
comp_data->tables[i].table_max_size = module->tables[i].max_size;
}
}
}
/* Create table data segments */
comp_data->table_init_data_count = module->table_seg_count;
@ -463,15 +487,11 @@ aot_create_comp_data(WASMModule *module)
&& !(comp_data->funcs = aot_create_funcs(module)))
goto fail;
/* Create export functions */
for (i = 0; i < module->export_count; i++)
if (module->exports[i].kind == EXPORT_KIND_FUNC)
comp_data->export_func_count++;
if (comp_data->export_func_count
&& !(comp_data->export_funcs = aot_create_export_funcs
(module, comp_data->export_func_count)))
goto fail;
/* Create llvm aux stack informations */
comp_data->llvm_aux_stack_global_index = module->llvm_aux_stack_global_index;
comp_data->llvm_aux_data_end = module->llvm_aux_data_end;
comp_data->llvm_aux_stack_bottom = module->llvm_aux_stack_bottom;
comp_data->llvm_aux_stack_size = module->llvm_aux_stack_size;
comp_data->start_func_index = module->start_function;
comp_data->wasm_module = module;
@ -490,10 +510,22 @@ aot_destroy_comp_data(AOTCompData *comp_data)
if (!comp_data)
return;
if (comp_data->import_memories)
wasm_runtime_free(comp_data->import_memories);
if (comp_data->memories)
wasm_runtime_free(comp_data->memories);
if (comp_data->mem_init_data_list)
aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
comp_data->mem_init_data_count);
if (comp_data->import_tables)
wasm_runtime_free(comp_data->import_tables);
if (comp_data->tables)
wasm_runtime_free(comp_data->tables);
if (comp_data->table_init_data_list)
aot_destroy_table_init_data_list(comp_data->table_init_data_list,
comp_data->table_init_data_count);
@ -514,9 +546,6 @@ aot_destroy_comp_data(AOTCompData *comp_data)
if (comp_data->funcs)
aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
if (comp_data->export_funcs)
wasm_runtime_free(comp_data->export_funcs);
wasm_runtime_free(comp_data);
}

View File

@ -19,6 +19,30 @@ extern "C" {
typedef InitializerExpression AOTInitExpr;
typedef WASMType AOTFuncType;
typedef WASMExport AOTExport;
/**
* Import memory
*/
typedef struct AOTImportMemory {
char *module_name;
char *memory_name;
uint32 memory_flags;
uint32 num_bytes_per_page;
uint32 mem_init_page_count;
uint32 mem_max_page_count;
} AOTImportMemory;
/**
* Memory information
*/
typedef struct AOTMemory {
/* memory info */
uint32 memory_flags;
uint32 num_bytes_per_page;
uint32 mem_init_page_count;
uint32 mem_max_page_count;
} AOTMemory;
/**
* A segment of memory init data
@ -38,10 +62,32 @@ typedef struct AOTMemInitData {
uint8 bytes[1];
} AOTMemInitData;
/**
* Import table
*/
typedef struct AOTImportTable {
char *module_name;
char *table_name;
uint32 table_flags;
uint32 table_init_size;
uint32 table_max_size;
} AOTImportTable;
/**
* Table
*/
typedef struct AOTTable {
uint32 elem_type;
uint32 table_flags;
uint32 table_init_size;
uint32 table_max_size;
} AOTTable;
/**
* A segment of table init data
*/
typedef struct AOTTableInitData {
uint32 table_index;
/* Start address of init data */
AOTInitExpr offset;
/* Function index count */
@ -110,47 +156,50 @@ typedef struct AOTFunc {
uint8 *code;
} AOTFunc;
/**
* Export function
*/
typedef struct AOTExportFunc {
char *func_name;
AOTFuncType *func_type;
/* function pointer linked */
void *func_ptr;
uint32 func_index;
} AOTExportFunc;
typedef struct AOTCompData {
/* Memory and memory init data info */
uint32 num_bytes_per_page;
uint32 mem_init_page_count;
uint32 mem_max_page_count;
/* Import memories */
uint32 import_memory_count;
AOTImportMemory *import_memories;
/* Memories */
uint32 memory_count;
AOTMemory *memories;
/* Memory init data info */
uint32 mem_init_data_count;
AOTMemInitData **mem_init_data_list;
/* Table and table init data info */
uint32 table_size;
AOTTableInitData **table_init_data_list;
/* Import tables */
uint32 import_table_count;
AOTImportTable *import_tables;
/* Tables */
uint32 table_count;
AOTTable *tables;
/* Table init data info */
uint32 table_init_data_count;
AOTTableInitData **table_init_data_list;
AOTImportGlobal *import_globals;
/* Import globals */
uint32 import_global_count;
AOTImportGlobal *import_globals;
AOTGlobal *globals;
/* Globals */
uint32 global_count;
AOTGlobal *globals;
AOTFuncType **func_types;
/* Function types */
uint32 func_type_count;
AOTFuncType **func_types;
AOTImportFunc *import_funcs;
/* Import functions */
uint32 import_func_count;
AOTImportFunc *import_funcs;
AOTFunc **funcs;
/* Functions */
uint32 func_count;
AOTExportFunc *export_funcs;
uint32 export_func_count;
AOTFunc **funcs;
uint32 start_func_index;
uint32 addr_data_size;

View File

@ -152,12 +152,30 @@ get_mem_init_data_list_size(AOTMemInitData **mem_init_data_list,
return size;
}
static uint32
get_import_memory_size(AOTCompData *comp_data)
{
/* currently we only emit import_memory_count = 0 */
return sizeof(uint32);
}
static uint32
get_memory_size(AOTCompData *comp_data)
{
/* memory_count + count * (memory_flags + num_bytes_per_page +
init_page_count + max_page_count) */
return (uint32)(sizeof(uint32)
+ comp_data->memory_count * sizeof(uint32) * 4);
}
static uint32
get_mem_info_size(AOTCompData *comp_data)
{
/* num bytes per page + init page count + max page count
+ init data count + init data list */
return (uint32)sizeof(uint32) * 4
/* import_memory_size + memory_size
+ init_data_count + init_data_list */
return get_import_memory_size(comp_data)
+ get_memory_size(comp_data)
+ (uint32)sizeof(uint32)
+ get_mem_init_data_list_size(comp_data->mem_init_data_list,
comp_data->mem_init_data_count);
}
@ -165,9 +183,10 @@ get_mem_info_size(AOTCompData *comp_data)
static uint32
get_table_init_data_size(AOTTableInitData *table_init_data)
{
/* init expr type (4 bytes) + init expr value (8 bytes)
/* table_index + init expr type (4 bytes) + init expr value (8 bytes)
+ func index count (4 bytes) + func indexes */
return (uint32)(sizeof(uint32) + sizeof(uint64) + sizeof(uint32)
return (uint32)(sizeof(uint32) + sizeof(uint32)
+ sizeof(uint64) + sizeof(uint32)
+ sizeof(uint32) * table_init_data->func_index_count);
}
@ -185,11 +204,30 @@ get_table_init_data_list_size(AOTTableInitData **table_init_data_list,
return size;
}
static uint32
get_import_table_size(AOTCompData *comp_data)
{
/* currently we only emit import_table_count = 0 */
return sizeof(uint32);
}
static uint32
get_table_size(AOTCompData *comp_data)
{
/* table_count + table_count * (elem_type + table_flags
* + init_size + max_size) */
return (uint32)(sizeof(uint32)
+ comp_data->table_count * sizeof(uint32) * 4);
}
static uint32
get_table_info_size(AOTCompData *comp_data)
{
/* table size + init data count + init data list */
return (uint32)sizeof(uint32) * 2
/* import_table size + table_size
+ init data count + init data list */
return get_import_table_size(comp_data)
+ get_table_size(comp_data)
+ (uint32)sizeof(uint32)
+ get_table_init_data_list_size(comp_data->table_init_data_list,
comp_data->table_init_data_count);
}
@ -412,23 +450,22 @@ get_func_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
}
static uint32
get_export_func_size(AOTExportFunc *export_func)
get_export_size(AOTExport *export)
{
/* export func index + export func name */
return (uint32)sizeof(uint32)
+ get_string_size(export_func->func_name);
/* export index + export kind + 1 byte padding + export name */
return (uint32)sizeof(uint32) + sizeof(uint8) + 1
+ get_string_size(export->name);
}
static uint32
get_export_funcs_size(AOTExportFunc *export_funcs,
uint32 export_func_count)
get_exports_size(AOTExport *exports, uint32 export_count)
{
AOTExportFunc *export_func = export_funcs;
AOTExport *export = exports;
uint32 size = 0, i;
for (i = 0; i < export_func_count; i++, export_func++) {
for (i = 0; i < export_count; i++, export++) {
size = align_uint(size, 4);
size += get_export_func_size(export_func);
size += get_export_size(export);
}
return size;
}
@ -436,10 +473,10 @@ get_export_funcs_size(AOTExportFunc *export_funcs,
static uint32
get_export_section_size(AOTCompData *comp_data)
{
/* export func count + export funcs */
/* export count + exports */
return (uint32)sizeof(uint32)
+ get_export_funcs_size(comp_data->export_funcs,
comp_data->export_func_count);
+ get_exports_size(comp_data->wasm_module->exports,
comp_data->wasm_module->export_count);
}
static uint32
@ -887,11 +924,24 @@ aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
*p_offset = offset = align_uint(offset, 4);
EMIT_U32(comp_data->num_bytes_per_page);
EMIT_U32(comp_data->mem_init_page_count);
EMIT_U32(comp_data->mem_max_page_count);
EMIT_U32(comp_data->mem_init_data_count);
/* Emit import memory count, only emit 0 currently.
TODO: emit the actual import memory count and
the full import memory info. */
EMIT_U32(0);
/* Emit memory count */
EMIT_U32(comp_data->memory_count);
/* Emit memory items */
for (i = 0; i < comp_data->memory_count; i++) {
EMIT_U32(comp_data->memories[i].memory_flags);
EMIT_U32(comp_data->memories[i].num_bytes_per_page);
EMIT_U32(comp_data->memories[i].mem_init_page_count);
EMIT_U32(comp_data->memories[i].mem_max_page_count);
}
/* Emit mem init data count */
EMIT_U32(comp_data->mem_init_data_count);
/* Emit mem init data items */
for (i = 0; i < comp_data->mem_init_data_count; i++) {
offset = align_uint(offset, 4);
#if WASM_ENABLE_BULK_MEMORY != 0
@ -931,11 +981,27 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
*p_offset = offset = align_uint(offset, 4);
EMIT_U32(comp_data->table_size);
EMIT_U32(comp_data->table_init_data_count);
/* Emit import table count, only emit 0 currently.
TODO: emit the actual import table count and
the full import table info. */
EMIT_U32(0);
/* Emit table count */
EMIT_U32(comp_data->table_count);
/* Emit table items */
for (i = 0; i < comp_data->table_count; i++) {
EMIT_U32(comp_data->tables[i].elem_type);
EMIT_U32(comp_data->tables[i].table_flags);
EMIT_U32(comp_data->tables[i].table_init_size);
EMIT_U32(comp_data->tables[i].table_max_size);
}
/* Emit table init data count */
EMIT_U32(comp_data->table_init_data_count);
/* Emit table init data items */
for (i = 0; i < comp_data->table_init_data_count; i++) {
offset = align_uint(offset, 4);
EMIT_U32(init_datas[i]->table_index);
EMIT_U32(init_datas[i]->offset.init_expr_type);
EMIT_U64(init_datas[i]->offset.u.i64);
EMIT_U32(init_datas[i]->func_index_count);
@ -1211,19 +1277,22 @@ aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
AOTCompData *comp_data, AOTObjectData *obj_data)
{
uint32 section_size = get_export_section_size(comp_data);
AOTExportFunc *func = comp_data->export_funcs;;
uint32 i, offset = *p_offset, export_func_count = comp_data->export_func_count;
AOTExport *export = comp_data->wasm_module->exports;
uint32 export_count = comp_data->wasm_module->export_count;
uint32 i, offset = *p_offset;
*p_offset = offset = align_uint(offset, 4);
EMIT_U32(AOT_SECTION_TYPE_EXPORT);
EMIT_U32(section_size);
EMIT_U32(export_func_count);
EMIT_U32(export_count);
for (i = 0; i < export_func_count; i++, func++) {
for (i = 0; i < export_count; i++, export++) {
offset = align_uint(offset, 4);
EMIT_U32(func->func_index);
EMIT_STR(func->func_name);
EMIT_U32(export->index);
EMIT_U8(export->kind);
EMIT_U8(0);
EMIT_STR(export->name);
}
if (offset - *p_offset != section_size + sizeof(uint32) * 2) {

View File

@ -102,6 +102,14 @@ format_block_name(char *name, uint32 name_size,
&value, &block_curr, 1); \
} while (0)
#define BUILD_ICMP(op, left, right, res, name) do { \
if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \
left, right, name))) { \
aot_set_last_error("llvm build icmp failed."); \
goto fail; \
} \
} while (0)
#define ADD_TO_PARAM_PHIS(block, value, idx) do { \
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
LLVMAddIncoming(block->param_phis[idx], \
@ -614,6 +622,99 @@ fail:
return false;
}
#if WASM_ENABLE_THREAD_MGR != 0
bool
check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
LLVMBasicBlockRef terminate_check_block, non_terminate_block;
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
LLVMBasicBlockRef terminate_block;
/* Offset of suspend_flags */
offset = I32_CONST(5);
CHECK_LLVM_CONST(offset);
if (!(terminate_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
&offset, 1, "terminate_addr"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(terminate_addr =
LLVMBuildBitCast(comp_ctx->builder,
terminate_addr,
INT32_PTR_TYPE, "terminate_addr_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (!(terminate_flags =
LLVMBuildLoad(comp_ctx->builder,
terminate_addr, "terminate_flags"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
/* Set terminate_flags memory accecc to volatile, so that the value
will always be loaded from memory rather than register */
LLVMSetVolatile(terminate_flags, true);
CREATE_BLOCK(terminate_check_block, "terminate_check");
MOVE_BLOCK_AFTER_CURR(terminate_check_block);
CREATE_BLOCK(non_terminate_block, "non_terminate");
MOVE_BLOCK_AFTER_CURR(non_terminate_block);
BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
/* Move builder to terminate check block */
SET_BUILDER_POS(terminate_check_block);
CREATE_BLOCK(terminate_block, "terminate");
MOVE_BLOCK_AFTER_CURR(terminate_block);
if (!(flag =
LLVMBuildAnd(comp_ctx->builder, terminate_flags,
I32_ONE, "termination_flag"))) {
aot_set_last_error("llvm build AND failed");
return false;
}
BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
BUILD_COND_BR(res, terminate_block, non_terminate_block);
/* Move builder to terminate block */
SET_BUILDER_POS(terminate_block);
if (aot_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);
}
/* Move builder to terminate block */
SET_BUILDER_POS(non_terminate_block);
return true;
fail:
return false;
}
#endif /* End of WASM_ENABLE_THREAD_MGR */
bool
aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 br_depth, uint8 **p_frame_ip)
@ -624,6 +725,14 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
char name[32];
uint32 i, param_index, result_index;
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
if (!(block_dst = get_target_block(func_ctx, br_depth))) {
return false;
}
@ -680,6 +789,14 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 i, param_index, result_index;
uint64 size;
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
POP_COND(value_cmp);
if (!LLVMIsConstant(value_cmp)) {
/* Compare value is not constant, create condition br IR */
@ -798,6 +915,14 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint64 size;
char name[32];
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
POP_I32(value_cmp);
if (!LLVMIsConstant(value_cmp)) {
/* Compare value is not constant, create switch IR */

View File

@ -53,6 +53,11 @@ aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
uint8 **p_frame_ip);
#if WASM_ENABLE_THREAD_MGR != 0
bool
check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
#endif
#ifdef __cplusplus
} /* end of extern "C" */
#endif

View File

@ -326,6 +326,14 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
bool ret = false;
char buf[32];
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
/* Check function index */
if (func_idx >= import_func_count + func_count) {
aot_set_last_error("Function index out of range.");
@ -514,6 +522,14 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
char buf[32], *func_name = "aot_call_indirect";
uint32 i, cell_num = 0, ret_cell_num, argv_cell_num;
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
/* prepare function type of aot_call_indirect */
func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
func_param_types[1] = INT8_TYPE; /* check_func_type */

View File

@ -42,16 +42,16 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef mem_check_bound = NULL;
switch (bytes) {
case 1:
mem_check_bound = func_ctx->mem_bound_check_1byte;
mem_check_bound = func_ctx->mem_info[0].mem_bound_check_1byte;
break;
case 2:
mem_check_bound = func_ctx->mem_bound_check_2bytes;
mem_check_bound = func_ctx->mem_info[0].mem_bound_check_2bytes;
break;
case 4:
mem_check_bound = func_ctx->mem_bound_check_4bytes;
mem_check_bound = func_ctx->mem_info[0].mem_bound_check_4bytes;
break;
case 8:
mem_check_bound = func_ctx->mem_bound_check_8bytes;
mem_check_bound = func_ctx->mem_info[0].mem_bound_check_8bytes;
break;
default:
bh_assert(0);
@ -80,17 +80,26 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef check_succ;
AOTValue *aot_value;
#if WASM_ENABLE_SHARED_MEMORY != 0
bool is_shared_memory =
comp_ctx->comp_data->memories[0].memory_flags & 0x02;
#endif
CHECK_LLVM_CONST(offset_const);
/* Get memory base address and memory data size */
#if WASM_ENABLE_SHARED_MEMORY != 0
if (func_ctx->mem_space_unchanged || is_shared_memory) {
#else
if (func_ctx->mem_space_unchanged) {
mem_base_addr = func_ctx->mem_base_addr;
#endif
mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
}
else {
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_base_addr,
"mem_base"))) {
if (!(mem_base_addr =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_base_addr,
"mem_base"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
@ -103,8 +112,10 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* return addres directly if constant offset and inside memory space */
if (LLVMIsConstant(addr)) {
int64 mem_offset = (int64)LLVMConstIntGetSExtValue(addr) + (int64)offset;
uint32 num_bytes_per_page = comp_ctx->comp_data->num_bytes_per_page;
uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count;
uint32 num_bytes_per_page =
comp_ctx->comp_data->memories[0].num_bytes_per_page;
uint32 init_page_count =
comp_ctx->comp_data->memories[0].mem_init_page_count;
int64 mem_data_size = num_bytes_per_page * init_page_count;
if (mem_data_size > 0
&& mem_offset >= 0
@ -141,8 +152,9 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
BUILD_ICMP(LLVMIntSGT, func_ctx->mem_bound_check_heap_base, offset1,
cmp1, "cmp1");
BUILD_ICMP(LLVMIntSGT,
func_ctx->mem_info[0].mem_bound_check_heap_base,
offset1, cmp1, "cmp1");
BUILD_ICMP(LLVMIntSGT, offset1, mem_check_bound, cmp2, "cmp2");
BUILD_OP(Or, cmp1, cmp2, cmp, "cmp");
@ -448,32 +460,19 @@ fail:
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;
LLVMValueRef 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;
if (func_ctx->mem_space_unchanged) {
mem_size = func_ctx->mem_info[0].mem_cur_page_count_addr;
}
/* 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;
else {
if (!(mem_size =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_cur_page_count_addr,
"mem_size"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
}
return mem_size;
@ -614,17 +613,24 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef mem_base_addr;
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef check_succ;
uint32 off = offsetof(AOTModuleInstance, memory_data_size);
LLVMValueRef mem_size_offset, mem_size_ptr, mem_size;
LLVMValueRef mem_size;
/* Get memory base address and memory data size */
#if WASM_ENABLE_SHARED_MEMORY != 0
bool is_shared_memory =
comp_ctx->comp_data->memories[0].memory_flags & 0x02;
if (func_ctx->mem_space_unchanged || is_shared_memory) {
#else
if (func_ctx->mem_space_unchanged) {
mem_base_addr = func_ctx->mem_base_addr;
#endif
mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
}
else {
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_base_addr,
"mem_base"))) {
if (!(mem_base_addr =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_base_addr,
"mem_base"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
@ -634,8 +640,10 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
if (LLVMIsConstant(offset) && LLVMIsConstant(bytes)) {
uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset);
uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes);
uint32 num_bytes_per_page = comp_ctx->comp_data->num_bytes_per_page;
uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count;
uint32 num_bytes_per_page =
comp_ctx->comp_data->memories[0].num_bytes_per_page;
uint32 init_page_count =
comp_ctx->comp_data->memories[0].mem_init_page_count;
uint32 mem_data_size = num_bytes_per_page * init_page_count;
if (mem_data_size > 0
&& mem_offset + mem_len <= mem_data_size) {
@ -652,27 +660,8 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* mem_size_offset = aot_inst + off */
mem_size_offset = I32_CONST(off);
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 */
if (!(mem_size = LLVMBuildLoad(comp_ctx->builder,
mem_size_ptr, "mem_size"))) {
aot_set_last_error("llvm build load failed.");
return NULL;
if (!(mem_size = get_memory_size(comp_ctx, func_ctx))) {
goto fail;
}
ADD_BASIC_BLOCK(check_succ, "check_succ");

View File

@ -111,8 +111,9 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
{
AOTCompData *comp_data = comp_ctx->comp_data;
uint32 import_global_count = comp_data->import_global_count;
uint32 global_base_offset = offsetof(AOTModuleInstance,
global_table_data.bytes);
uint32 global_base_offset =
offsetof(AOTModuleInstance, global_table_data.bytes)
+ sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
uint32 global_offset;
uint8 global_type;
LLVMValueRef offset, global_ptr, global;

View File

@ -186,142 +186,279 @@ static bool
create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMTypeRef int8_ptr_type, uint32 func_index)
{
LLVMValueRef offset;
LLVMValueRef offset, mem_info_base;
uint32 memory_count;
WASMModule *module = comp_ctx->comp_data->wasm_module;
WASMFunction *func = module->functions[func_index];
bool mem_space_unchanged = (!func->has_op_memory_grow && !func->has_op_func_call)
|| (!module->possible_memory_grow);
#if WASM_ENABLE_SHARED_MEMORY != 0
bool is_shared_memory;
#endif
func_ctx->mem_space_unchanged = mem_space_unchanged;
/* Load memory base address */
offset = I32_CONST(offsetof(AOTModuleInstance, memory_data.ptr));
if (!(func_ctx->mem_base_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
&offset, 1, "mem_base_addr_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
memory_count = module->memory_count + module->import_memory_count;
/* If the module dosen't have memory, reserve
one mem_info space with empty content */
if (memory_count == 0)
memory_count = 1;
if (!(func_ctx->mem_info =
wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) {
return false;
}
if (!(func_ctx->mem_base_addr =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_base_addr,
memset(func_ctx->mem_info, 0, sizeof(AOTMemInfo));
/* Currently we only create memory info for memory 0 */
/* Load memory base address */
#if WASM_ENABLE_SHARED_MEMORY != 0
is_shared_memory = comp_ctx->comp_data->memories[0].memory_flags & 0x02
? true : false;
if (is_shared_memory) {
LLVMValueRef shared_mem_addr;
offset = I32_CONST(offsetof(AOTModuleInstance, memories));
if (!offset) {
aot_set_last_error("create llvm const failed.");
return false;
}
/* aot_inst->memories */
if (!(shared_mem_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
&offset, 1, "shared_mem_addr_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(shared_mem_addr =
LLVMBuildBitCast(comp_ctx->builder,
shared_mem_addr, int8_ptr_type,
"shared_mem_addr_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
/* aot_inst->memories[0] */
if (!(shared_mem_addr =
LLVMBuildLoad(comp_ctx->builder,
shared_mem_addr, "shared_mem_addr"))) {
aot_set_last_error("llvm build load failed");
return false;
}
if (!(shared_mem_addr =
LLVMBuildBitCast(comp_ctx->builder,
shared_mem_addr, int8_ptr_type,
"shared_mem_addr_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (!(shared_mem_addr =
LLVMBuildLoad(comp_ctx->builder,
shared_mem_addr, "shared_mem_addr"))) {
aot_set_last_error("llvm build load failed");
return false;
}
offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_base_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr,
&offset, 1, "mem_base_addr_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_cur_page_count));
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr,
&offset, 1, "mem_cur_page_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
}
else
#endif
{
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
+ offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_base_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
&offset, 1, "mem_base_addr_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
+ offsetof(AOTMemoryInstance, mem_cur_page_count));
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
&offset, 1, "mem_cur_page_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
}
/* Store mem info base address before cast */
mem_info_base = func_ctx->mem_info[0].mem_base_addr;
if (!(func_ctx->mem_info[0].mem_base_addr =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_base_addr,
int8_ptr_type, "mem_base_addr_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_cur_page_count_addr,
INT32_PTR_TYPE, "mem_cur_page_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (mem_space_unchanged) {
if (!(func_ctx->mem_base_addr =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_base_addr,
if (!(func_ctx->mem_info[0].mem_base_addr =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_base_addr,
"mem_base_addr"))) {
aot_set_last_error("llvm build load failed");
return false;
}
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_cur_page_count_addr,
"mem_cur_page_count_addr"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
#if WASM_ENABLE_SHARED_MEMORY != 0
else if (is_shared_memory) {
/* The base address for shared memory will never changed,
we can load the value here */
if (!(func_ctx->mem_info[0].mem_base_addr =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_base_addr,
"mem_base_addr"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
#endif
/* Load memory bound check constants */
offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_1byte));
if (!(func_ctx->mem_bound_check_1byte =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte)
- offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base,
&offset, 1, "bound_check_1byte_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(func_ctx->mem_bound_check_1byte =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_1byte,
if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_1byte,
INT64_PTR_TYPE, "bound_check_1byte_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (mem_space_unchanged) {
if (!(func_ctx->mem_bound_check_1byte =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_1byte,
"bound_check_1byte"))) {
if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_1byte,
"bound_check_1byte"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_2bytes));
if (!(func_ctx->mem_bound_check_2bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes)
- offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base,
&offset, 1, "bound_check_2bytes_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(func_ctx->mem_bound_check_2bytes =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_2bytes,
if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_2bytes,
INT64_PTR_TYPE, "bound_check_2bytes_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (mem_space_unchanged) {
if (!(func_ctx->mem_bound_check_2bytes =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_2bytes,
"bound_check_2bytes"))) {
if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_2bytes,
"bound_check_2bytes"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_4bytes));
if (!(func_ctx->mem_bound_check_4bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes)
- offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base,
&offset, 1, "bound_check_4bytes_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(func_ctx->mem_bound_check_4bytes =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_4bytes,
if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_4bytes,
INT64_PTR_TYPE, "bound_check_4bytes_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (mem_space_unchanged) {
if (!(func_ctx->mem_bound_check_4bytes =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_4bytes,
"bound_check_4bytes"))) {
if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_4bytes,
"bound_check_4bytes"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_8bytes));
if (!(func_ctx->mem_bound_check_8bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes)
- offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base,
&offset, 1, "bound_check_8bytes_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(func_ctx->mem_bound_check_8bytes =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_8bytes,
if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_8bytes,
INT64_PTR_TYPE, "bound_check_8bytes_ptr"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (mem_space_unchanged) {
if (!(func_ctx->mem_bound_check_8bytes =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_8bytes,
"bound_check_8bytes"))) {
if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_8bytes,
"bound_check_8bytes"))) {
aot_set_last_error("llvm build load failed");
return false;
}
}
/* Load bound_check_heap_base */
offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_heap_base));
if (!(func_ctx->mem_bound_check_heap_base =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_heap_base)
- offsetof(AOTMemoryInstance, memory_data.ptr));
if (!(func_ctx->mem_info[0].mem_bound_check_heap_base =
LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base,
&offset, 1, "bound_check_heap_base_offset"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
if (!(func_ctx->mem_bound_check_heap_base =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_heap_base,
if (!(func_ctx->mem_info[0].mem_bound_check_heap_base =
LLVMBuildBitCast(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_heap_base,
INT64_PTR_TYPE, "bound_check_heap_base_tmp"))) {
aot_set_last_error("llvm build bit cast failed");
return false;
}
if (!(func_ctx->mem_bound_check_heap_base =
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_heap_base,
if (!(func_ctx->mem_info[0].mem_bound_check_heap_base =
LLVMBuildLoad(comp_ctx->builder,
func_ctx->mem_info[0].mem_bound_check_heap_base,
"bound_check_heap_base"))) {
aot_set_last_error("llvm build load failed");
return false;
@ -616,6 +753,8 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
return func_ctx;
fail:
if (func_ctx->mem_info)
wasm_runtime_free(func_ctx->mem_info);
if (func_ctx->exception_blocks)
wasm_runtime_free(func_ctx->exception_blocks);
aot_block_stack_destroy(&func_ctx->block_stack);
@ -630,6 +769,8 @@ aot_destroy_func_contexts(AOTFuncContext **func_ctxes, uint32 count)
for (i = 0; i < count; i++)
if (func_ctxes[i]) {
if (func_ctxes[i]->mem_info)
wasm_runtime_free(func_ctxes[i]->mem_info);
if (func_ctxes[i]->exception_blocks)
wasm_runtime_free(func_ctxes[i]->exception_blocks);
aot_block_stack_destroy(&func_ctxes[i]->block_stack);
@ -929,6 +1070,9 @@ aot_create_comp_context(AOTCompData *comp_data,
if (option->enable_bulk_memory)
comp_ctx->enable_bulk_memory = true;
if (option->enable_thread_mgr)
comp_ctx->enable_thread_mgr = true;
if (option->is_jit_mode) {
/* Create LLVM execution engine */
LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options));

View File

@ -99,6 +99,16 @@ typedef struct AOTCheckedAddr {
uint32 bytes;
} AOTCheckedAddr, *AOTCheckedAddrList;
typedef struct AOTMemInfo {
LLVMValueRef mem_base_addr;
LLVMValueRef mem_cur_page_count_addr;
LLVMValueRef mem_bound_check_heap_base;
LLVMValueRef mem_bound_check_1byte;
LLVMValueRef mem_bound_check_2bytes;
LLVMValueRef mem_bound_check_4bytes;
LLVMValueRef mem_bound_check_8bytes;
} AOTMemInfo;
typedef struct AOTFuncContext {
AOTFunc *aot_func;
LLVMValueRef func;
@ -111,12 +121,7 @@ typedef struct AOTFuncContext {
LLVMValueRef native_stack_bound;
LLVMValueRef last_alloca;
LLVMValueRef mem_base_addr;
LLVMValueRef mem_bound_check_heap_base;
LLVMValueRef mem_bound_check_1byte;
LLVMValueRef mem_bound_check_2bytes;
LLVMValueRef mem_bound_check_4bytes;
LLVMValueRef mem_bound_check_8bytes;
AOTMemInfo *mem_info;
LLVMValueRef cur_exception;
@ -196,6 +201,9 @@ typedef struct AOTCompContext {
/* Bounday Check */
bool enable_bound_check;
/* Thread Manager */
bool enable_thread_mgr;
/* Whether optimize the JITed code */
bool optimize;
@ -235,6 +243,7 @@ typedef struct AOTCompOption{
char *target_cpu;
char *cpu_features;
bool enable_bulk_memory;
bool enable_thread_mgr;
bool is_sgx_platform;
uint32 opt_level;
uint32 size_level;