enable pthread for AoT && update AOT current version to 2 (#311)
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user