Make heap and linear memory contiguous to refine compilation time and footprint (#233)
Use FastISel for JIT mode Use united aot version in aot file and aot runtime Disable check signature failed warning for wamrc Fix fast interpreter x86_32 float issue Remove unused empty lvgl folder
This commit is contained in:
@ -821,13 +821,14 @@ aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 offset = *p_offset;
|
||||
uint32 aot_curr_version = AOT_CURRENT_VERSION;
|
||||
|
||||
EMIT_U8('\0');
|
||||
EMIT_U8('a');
|
||||
EMIT_U8('o');
|
||||
EMIT_U8('t');
|
||||
|
||||
EMIT_U32(1);
|
||||
EMIT_U32(aot_curr_version);
|
||||
|
||||
*p_offset = offset;
|
||||
return true;
|
||||
|
||||
@ -143,20 +143,19 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef ret_type, uint8 wasm_ret_type,
|
||||
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
|
||||
{
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[4];
|
||||
LLVMTypeRef ret_ptr_type, elem_ptr_type;
|
||||
LLVMValueRef func, elem_idx, elem_ptr;
|
||||
LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res;
|
||||
LLVMValueRef func_param_values[4], value_ret = NULL, res;
|
||||
char buf[32], *func_name = "aot_invoke_native";
|
||||
uint32 i, cell_num = 0;
|
||||
|
||||
/* prepare function type of aot_invoke_native */
|
||||
func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
|
||||
func_param_types[1] = I32_TYPE; /* func_idx */
|
||||
func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */
|
||||
func_param_types[3] = I32_TYPE; /* argc */
|
||||
func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */
|
||||
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
|
||||
func_param_types[2] = I32_TYPE; /* argc */
|
||||
func_param_types[3] = INT32_PTR_TYPE; /* argv */
|
||||
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
@ -216,6 +215,24 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
|
||||
}
|
||||
|
||||
func_param_values[0] = func_ctx->exec_env;
|
||||
func_param_values[1] = func_idx;
|
||||
func_param_values[2] = I32_CONST(param_cell_num);
|
||||
func_param_values[3] = func_ctx->argv_buf;
|
||||
|
||||
if (!func_param_values[2]) {
|
||||
aot_set_last_error("llvm create const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call aot_invoke_native() function */
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
|
||||
func_param_values, 4, "res"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get function return value */
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID) {
|
||||
if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
@ -227,39 +244,12 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* convert to int32 pointer */
|
||||
if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
|
||||
INT32_PTR_TYPE, "argv_ret_ptr"))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret,
|
||||
"value_ret"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
|
||||
}
|
||||
|
||||
func_param_values[0] = func_ctx->exec_env;
|
||||
func_param_values[1] = func_idx;
|
||||
func_param_values[2] = func_ctx->argv_buf;
|
||||
func_param_values[3] = I32_CONST(param_cell_num);
|
||||
func_param_values[4] = value_ret_ptr;
|
||||
|
||||
if (!func_param_values[3]) {
|
||||
aot_set_last_error("llvm create const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call aot_invoke_native() function */
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
|
||||
func_param_values, 5, "res"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID)
|
||||
/* get function return value */
|
||||
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
|
||||
|
||||
*p_res = res;
|
||||
return true;
|
||||
@ -395,10 +385,10 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef ret_type, uint8 wasm_ret_type,
|
||||
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
|
||||
{
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[7];
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
|
||||
LLVMTypeRef ret_ptr_type, elem_ptr_type;
|
||||
LLVMValueRef func, elem_idx, elem_ptr;
|
||||
LLVMValueRef func_param_values[7], value_ret = NULL, value_ret_ptr, res = NULL;
|
||||
LLVMValueRef func_param_values[6], value_ret = NULL, res = NULL;
|
||||
char buf[32], *func_name = "aot_call_indirect";
|
||||
uint32 i, cell_num = 0;
|
||||
|
||||
@ -407,10 +397,9 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
func_param_types[1] = INT8_TYPE; /* check_func_type */
|
||||
func_param_types[2] = I32_TYPE; /* func_type_idx */
|
||||
func_param_types[3] = I32_TYPE; /* table_elem_idx */
|
||||
func_param_types[4] = INT32_PTR_TYPE; /* frame_lp */
|
||||
func_param_types[5] = I32_TYPE; /* argc */
|
||||
func_param_types[6] = INT32_PTR_TYPE; /* argv_ret */
|
||||
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 7, false))) {
|
||||
func_param_types[4] = I32_TYPE; /* argc */
|
||||
func_param_types[5] = INT32_PTR_TYPE; /* argv */
|
||||
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
@ -470,6 +459,26 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
|
||||
}
|
||||
|
||||
func_param_values[0] = func_ctx->exec_env;
|
||||
func_param_values[1] = I8_CONST(true);
|
||||
func_param_values[2] = func_type_idx;
|
||||
func_param_values[3] = table_elem_idx;
|
||||
func_param_values[4] = I32_CONST(param_cell_num);
|
||||
func_param_values[5] = func_ctx->argv_buf;
|
||||
|
||||
if (!func_param_values[1] || !func_param_values[4]) {
|
||||
aot_set_last_error("llvm create const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call aot_call_indirect() function */
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
|
||||
func_param_values, 6, "res"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get function return value */
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID) {
|
||||
if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
|
||||
aot_set_last_error("llvm add pointer type failed.");
|
||||
@ -482,40 +491,12 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* convert to int32 pointer */
|
||||
if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
|
||||
INT32_PTR_TYPE, "argv_ret_ptr"))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret,
|
||||
"value_ret"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
|
||||
}
|
||||
|
||||
func_param_values[0] = func_ctx->exec_env;
|
||||
func_param_values[1] = I8_CONST(true);
|
||||
func_param_values[2] = func_type_idx;
|
||||
func_param_values[3] = table_elem_idx;
|
||||
func_param_values[4] = func_ctx->argv_buf;
|
||||
func_param_values[5] = I32_CONST(param_cell_num);
|
||||
func_param_values[6] = value_ret_ptr;
|
||||
|
||||
if (!func_param_values[1] || !func_param_values[4]) {
|
||||
aot_set_last_error("llvm create const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call aot_call_indirect() function */
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
|
||||
func_param_values, 7, "res"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wasm_ret_type != VALUE_TYPE_VOID)
|
||||
/* get function return value */
|
||||
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
|
||||
|
||||
*p_res = res;
|
||||
return true;
|
||||
|
||||
@ -23,14 +23,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_COND_BR(cmp_val, then_block, else_block) do { \
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cmp_val, \
|
||||
then_block, else_block)) { \
|
||||
aot_set_last_error("llvm build cond br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
@ -43,53 +35,88 @@
|
||||
#define SET_BUILD_POS(block) \
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block)
|
||||
|
||||
static LLVMValueRef
|
||||
get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 bytes)
|
||||
{
|
||||
LLVMValueRef mem_check_bound = NULL;
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
mem_check_bound = func_ctx->mem_bound_check_1byte;
|
||||
break;
|
||||
case 2:
|
||||
mem_check_bound = func_ctx->mem_bound_check_2bytes;
|
||||
break;
|
||||
case 4:
|
||||
mem_check_bound = func_ctx->mem_bound_check_4bytes;
|
||||
break;
|
||||
case 8:
|
||||
mem_check_bound = func_ctx->mem_bound_check_8bytes;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (func_ctx->mem_space_unchanged)
|
||||
return mem_check_bound;
|
||||
|
||||
if (!(mem_check_bound = LLVMBuildLoad(comp_ctx->builder,
|
||||
mem_check_bound,
|
||||
"mem_check_bound"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
return mem_check_bound;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 offset, uint32 bytes)
|
||||
{
|
||||
LLVMValueRef offset_const = I32_CONST(offset);
|
||||
LLVMValueRef size_const = I32_CONST(bytes);
|
||||
LLVMValueRef addr, maddr, moffset;
|
||||
LLVMValueRef cmp, phi;
|
||||
LLVMValueRef mem_base_addr, mem_data_size;
|
||||
LLVMValueRef heap_base_addr, heap_base_offset;
|
||||
LLVMValueRef mem_offset_max = NULL, heap_offset_max = NULL;
|
||||
LLVMBasicBlockRef check_mem_space, check_heap_space, check_succ;
|
||||
LLVMValueRef bytes_const = I32_CONST(bytes);
|
||||
LLVMValueRef bytes64_const = I64_CONST(bytes);
|
||||
LLVMValueRef heap_base_offset = func_ctx->heap_base_offset;
|
||||
LLVMValueRef addr, maddr, offset1, offset2, cmp;
|
||||
LLVMValueRef mem_base_addr, mem_check_bound, total_mem_size;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef check_succ, check_mem_space;
|
||||
|
||||
CHECK_LLVM_CONST(offset_const);
|
||||
CHECK_LLVM_CONST(size_const);
|
||||
CHECK_LLVM_CONST(bytes_const);
|
||||
CHECK_LLVM_CONST(bytes64_const);
|
||||
|
||||
heap_base_addr = func_ctx->heap_base_addr;
|
||||
heap_base_offset = func_ctx->heap_base_offset;
|
||||
/* Get memory base address and memory data size */
|
||||
if (func_ctx->mem_space_unchanged) {
|
||||
mem_base_addr = func_ctx->mem_base_addr;
|
||||
}
|
||||
else {
|
||||
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_base_addr,
|
||||
"mem_base"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
POP_I32(addr);
|
||||
BUILD_OP(Add, offset_const, addr, moffset, "moffset");
|
||||
/* offset1 = offset + addr; */
|
||||
BUILD_OP(Add, offset_const, addr, offset1, "offset1");
|
||||
|
||||
/* return addres directly if constant offset and inside memory space */
|
||||
if (LLVMIsConstant(moffset)) {
|
||||
uint32 memory_offset = (uint32)LLVMConstIntGetZExtValue(moffset);
|
||||
if (LLVMIsConstant(offset1)) {
|
||||
uint32 mem_offset = (uint32)LLVMConstIntGetZExtValue(offset1);
|
||||
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;
|
||||
if (init_page_count > 0
|
||||
&& memory_offset <= comp_ctx->comp_data->num_bytes_per_page
|
||||
* init_page_count - bytes) {
|
||||
uint32 mem_data_size = num_bytes_per_page * init_page_count;
|
||||
if (mem_data_size > 0
|
||||
&& mem_offset <= mem_data_size - bytes) {
|
||||
/* inside memory space */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_base_addr,
|
||||
"mem_base"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_base_addr = func_ctx->mem_base_addr;
|
||||
}
|
||||
|
||||
/* maddr = mem_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
mem_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
&offset1, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
@ -97,136 +124,63 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(check_heap_space, "check_heap_space");
|
||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_heap_space, block_curr);
|
||||
LLVMMoveBasicBlockAfter(check_succ, check_heap_space);
|
||||
|
||||
/* Add return maddress phi for check_succ block */
|
||||
SET_BUILD_POS(check_succ);
|
||||
if (!(phi = LLVMBuildPhi(comp_ctx->builder,
|
||||
INT8_PTR_TYPE, "maddr_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(block_curr);
|
||||
|
||||
/* Get memory data size */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_data_size = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_data_size,
|
||||
"mem_data_size"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_data_size = func_ctx->mem_data_size;
|
||||
}
|
||||
|
||||
if (comp_ctx->comp_data->mem_init_page_count == 0) {
|
||||
/* Get total memory size */
|
||||
if (func_ctx->mem_space_unchanged) {
|
||||
total_mem_size = func_ctx->total_mem_size;
|
||||
}
|
||||
else {
|
||||
if (!(total_mem_size = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->total_mem_size,
|
||||
"total_mem_size"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ADD_BASIC_BLOCK(check_mem_space, "check_mem_space");
|
||||
LLVMMoveBasicBlockAfter(check_mem_space, block_curr);
|
||||
|
||||
/* if mem_data_size is zero, check heap space */
|
||||
BUILD_ICMP(LLVMIntEQ, mem_data_size, I32_ZERO, cmp,
|
||||
"cmp_mem_data_size");
|
||||
BUILD_COND_BR(cmp, check_heap_space, check_mem_space);
|
||||
/* if total_mem_size is zero, boundary check fail */
|
||||
BUILD_ICMP(LLVMIntEQ, total_mem_size, I32_ZERO, cmp,
|
||||
"cmp_total_mem_size");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
true, cmp, check_mem_space)) {
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(check_mem_space);
|
||||
}
|
||||
|
||||
/* Get memory base address */
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_base_addr,
|
||||
"mem_base"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem_base_addr = func_ctx->mem_base_addr;
|
||||
}
|
||||
/* offset2 = offset1 - heap_base_offset; */
|
||||
BUILD_OP(Sub, offset1, heap_base_offset, offset2, "offset2");
|
||||
|
||||
/* maddr = mem_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(phi, &maddr, &block_curr, 1);
|
||||
|
||||
if (!func_ctx->mem_space_unchanged) {
|
||||
/* mem_offset_max = mem_data_size - bytes to load/read */
|
||||
if (!(mem_offset_max = LLVMBuildSub(comp_ctx->builder,
|
||||
mem_data_size, size_const,
|
||||
"mem_offset_max"))) {
|
||||
aot_set_last_error("llvm build sub failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bytes == 1)
|
||||
mem_offset_max = func_ctx->mem_bound_1_byte;
|
||||
else if (bytes == 2)
|
||||
mem_offset_max = func_ctx->mem_bound_2_bytes;
|
||||
else if (bytes == 4)
|
||||
mem_offset_max = func_ctx->mem_bound_4_bytes;
|
||||
else if (bytes == 8)
|
||||
mem_offset_max = func_ctx->mem_bound_8_bytes;
|
||||
}
|
||||
|
||||
/* in linear memory if (uint32)moffset <= (uint32)mem_offset_max,
|
||||
else check heap space */
|
||||
BUILD_ICMP(LLVMIntULE, moffset, mem_offset_max, cmp, "cmp_mem_offset");
|
||||
|
||||
/* Create condtion br */
|
||||
BUILD_COND_BR(cmp, check_succ, check_heap_space);
|
||||
|
||||
/* Start to translate the check_heap_space block */
|
||||
SET_BUILD_POS(check_heap_space);
|
||||
|
||||
/* moffset -= heap_base_offset */
|
||||
if (!(moffset = LLVMBuildSub(comp_ctx->builder,
|
||||
moffset, heap_base_offset,
|
||||
"moffset_to_heap"))) {
|
||||
aot_set_last_error("llvm build sub failed.");
|
||||
if (!(mem_check_bound =
|
||||
get_memory_check_bound(comp_ctx, func_ctx, bytes))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* maddr = heap_base_addr + moffset */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, heap_base_addr,
|
||||
&moffset, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(phi, &maddr, &block_curr, 1);
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
LLVMMoveBasicBlockAfter(check_succ, block_curr);
|
||||
|
||||
/* heap space base addr and size is unchanged,
|
||||
the heap boundary is unchanged also. */
|
||||
if (bytes == 1)
|
||||
heap_offset_max = func_ctx->heap_bound_1_byte;
|
||||
else if (bytes == 2)
|
||||
heap_offset_max = func_ctx->heap_bound_2_bytes;
|
||||
else if (bytes == 4)
|
||||
heap_offset_max = func_ctx->heap_bound_4_bytes;
|
||||
else if (bytes == 8)
|
||||
heap_offset_max = func_ctx->heap_bound_8_bytes;
|
||||
|
||||
/* in heap space if (uint32)moffset <= (uint32)heap_offset_max,
|
||||
else throw exception */
|
||||
BUILD_ICMP(LLVMIntUGT, moffset, heap_offset_max, cmp, "cmp_heap_offset");
|
||||
/* offset2 > bound ? */
|
||||
BUILD_ICMP(LLVMIntUGT, offset2, mem_check_bound, cmp, "cmp");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
true, cmp, check_succ))
|
||||
true, cmp, check_succ)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SET_BUILD_POS(check_succ);
|
||||
return phi;
|
||||
|
||||
/* maddr = mem_base_addr + offset1 */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
|
||||
&offset1, 1, "maddr"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
return maddr;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ 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_heap_data.bytes);
|
||||
global_table_data.bytes);
|
||||
uint32 global_offset;
|
||||
uint8 global_type;
|
||||
LLVMValueRef offset, global_ptr, global;
|
||||
|
||||
@ -181,68 +181,117 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/* Load memory data size */
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, memory_data_size));
|
||||
if (!(func_ctx->mem_data_size =
|
||||
/* Load total memory size */
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, total_mem_size));
|
||||
if (!(func_ctx->total_mem_size =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "mem_data_size_offset"))) {
|
||||
&offset, 1, "bound_check_1byte_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->mem_data_size =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_data_size,
|
||||
INT32_PTR_TYPE, "mem_data_size_ptr"))) {
|
||||
if (!(func_ctx->total_mem_size =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->total_mem_size,
|
||||
INT32_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_data_size =
|
||||
LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_data_size,
|
||||
"mem_data_size"))) {
|
||||
if (!(func_ctx->total_mem_size =
|
||||
LLVMBuildLoad(comp_ctx->builder, func_ctx->total_mem_size,
|
||||
"bound_check_1byte"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->mem_bound_1_byte =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->mem_data_size, I32_ONE,
|
||||
"mem_bound_1_byte"))
|
||||
|| !(func_ctx->mem_bound_2_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->mem_data_size, I32_TWO,
|
||||
"mem_bound_2_bytes"))
|
||||
|| !(func_ctx->mem_bound_4_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->mem_data_size, I32_FOUR,
|
||||
"mem_bound_4_bytes"))
|
||||
|| !(func_ctx->mem_bound_8_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->mem_data_size, I32_EIGHT,
|
||||
"mem_bound_8_bytes"))) {
|
||||
aot_set_last_error("llvm build sub failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load heap base address */
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, heap_data.ptr));
|
||||
if (!(func_ctx->heap_base_addr =
|
||||
/* 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, 1, "heap_base_addr_offset"))) {
|
||||
&offset, 1, "bound_check_1byte_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->heap_base_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_base_addr,
|
||||
int8_ptr_type, "heap_base_addr_tmp"))) {
|
||||
if (!(func_ctx->mem_bound_check_1byte =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_1byte,
|
||||
INT32_PTR_TYPE, "bound_check_1byte_ptr"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->heap_base_addr =
|
||||
LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_base_addr,
|
||||
"heap_base_addr"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
if (mem_space_unchanged) {
|
||||
if (!(func_ctx->mem_bound_check_1byte =
|
||||
LLVMBuildLoad(comp_ctx->builder, func_ctx->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, 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,
|
||||
INT32_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"))) {
|
||||
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, 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,
|
||||
INT32_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"))) {
|
||||
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, 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,
|
||||
INT32_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"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load heap base offset */
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, heap_base_offset));
|
||||
@ -265,46 +314,6 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load heap data size */
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, heap_data_size));
|
||||
if (!(func_ctx->heap_data_size =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "heap_data_size_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->heap_data_size =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_data_size,
|
||||
INT32_PTR_TYPE, "heap_data_size_tmp"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->heap_data_size =
|
||||
LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_data_size,
|
||||
"heap_data_size"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->heap_bound_1_byte =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->heap_data_size, I32_ONE,
|
||||
"heap_bound_1_byte"))
|
||||
|| !(func_ctx->heap_bound_2_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->heap_data_size, I32_TWO,
|
||||
"heap_bound_2_bytes"))
|
||||
|| !(func_ctx->heap_bound_4_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->heap_data_size, I32_FOUR,
|
||||
"heap_bound_4_bytes"))
|
||||
|| !(func_ctx->heap_bound_8_bytes =
|
||||
LLVMBuildSub(comp_ctx->builder,
|
||||
func_ctx->heap_data_size, I32_EIGHT,
|
||||
"heap_bound_8_bytes"))) {
|
||||
aot_set_last_error("llvm build sub failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -313,7 +322,7 @@ create_table_base(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef offset;
|
||||
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_heap_data.bytes)
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ comp_ctx->comp_data->global_data_size);
|
||||
func_ctx->table_base = LLVMBuildInBoundsGEP(comp_ctx->builder,
|
||||
func_ctx->aot_inst,
|
||||
@ -918,6 +927,7 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
/* Create LLVM execution engine */
|
||||
LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options));
|
||||
jit_options.OptLevel = LLVMCodeGenLevelAggressive;
|
||||
jit_options.EnableFastISel = true;
|
||||
/*jit_options.CodeModel = LLVMCodeModelSmall;*/
|
||||
if (LLVMCreateMCJITCompilerForModule
|
||||
(&comp_ctx->exec_engine, comp_ctx->module,
|
||||
|
||||
@ -94,20 +94,13 @@ typedef struct AOTFuncContext {
|
||||
LLVMValueRef table_base;
|
||||
LLVMValueRef argv_buf;
|
||||
|
||||
LLVMValueRef mem_data_size;
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef mem_bound_1_byte;
|
||||
LLVMValueRef mem_bound_2_bytes;
|
||||
LLVMValueRef mem_bound_4_bytes;
|
||||
LLVMValueRef mem_bound_8_bytes;
|
||||
|
||||
LLVMValueRef heap_base_offset;
|
||||
LLVMValueRef heap_base_addr;
|
||||
LLVMValueRef heap_data_size;
|
||||
LLVMValueRef heap_bound_1_byte;
|
||||
LLVMValueRef heap_bound_2_bytes;
|
||||
LLVMValueRef heap_bound_4_bytes;
|
||||
LLVMValueRef heap_bound_8_bytes;
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef total_mem_size;
|
||||
LLVMValueRef mem_bound_check_1byte;
|
||||
LLVMValueRef mem_bound_check_2bytes;
|
||||
LLVMValueRef mem_bound_check_4bytes;
|
||||
LLVMValueRef mem_bound_check_8bytes;
|
||||
|
||||
LLVMValueRef cur_exception;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user