From e3dcf4f8acfe58a04d54319bef5fc3728bd612bf Mon Sep 17 00:00:00 2001 From: "xiangjia.xj" Date: Tue, 25 Feb 2025 17:52:59 +0800 Subject: [PATCH 1/2] feature: better memory information restore mechanism --- core/iwasm/compilation/aot_compiler.c | 9 + core/iwasm/compilation/aot_emit_memory.c | 57 ++---- core/iwasm/compilation/aot_llvm.c | 247 ++++++++++++----------- core/iwasm/compilation/aot_llvm.h | 12 +- 4 files changed, 173 insertions(+), 152 deletions(-) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 82f70ca3d..66a5a2b23 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -999,6 +999,7 @@ static bool aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) { AOTFuncContext *func_ctx = comp_ctx->func_ctxes[func_index]; + WASMModule *module = comp_ctx->comp_data->wasm_module; LLVMValueRef func_index_ref; uint8 *frame_ip = func_ctx->aot_func->code, opcode, *p_f32, *p_f64; uint8 *frame_ip_end = frame_ip + func_ctx->aot_func->code_size; @@ -1230,6 +1231,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) read_leb_uint32(frame_ip, frame_ip_end, func_idx); if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false)) return false; + if (module->functions[func_index]->has_memory_operations) + restore_memory_info(comp_ctx, func_ctx); break; } @@ -1250,6 +1253,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx, tbl_idx)) return false; + if (module->functions[func_index]->has_memory_operations) + restore_memory_info(comp_ctx, func_ctx); break; } @@ -1420,6 +1425,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) if (!aot_compile_op_call_ref(comp_ctx, func_ctx, type_idx, false)) return false; + if (module->functions[func_index]->has_memory_operations) + restore_memory_info(comp_ctx, func_ctx); break; } @@ -2092,6 +2099,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) read_leb_uint32(frame_ip, frame_ip_end, mem_idx); if (!aot_compile_op_memory_grow(comp_ctx, func_ctx)) return false; + if (module->functions[func_index]->has_memory_operations) + restore_memory_info(comp_ctx, func_ctx); break; case WASM_OP_I32_CONST: diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index 9adf96ac5..639cf6dce 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -78,9 +78,6 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return NULL; } - if (func_ctx->mem_space_unchanged) - return mem_check_bound; - if (!(mem_check_bound = LLVMBuildLoad2( comp_ctx->builder, (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE : I32_TYPE, @@ -164,17 +161,15 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Get memory base address and memory data size */ - if (func_ctx->mem_space_unchanged #if WASM_ENABLE_SHARED_MEMORY != 0 - || is_shared_memory -#endif - ) { + if (is_shared_memory) mem_base_addr = func_ctx->mem_info[0].mem_base_addr; - } - else { + else +#endif + { if (!(mem_base_addr = LLVMBuildLoad2( comp_ctx->builder, OPQ_PTR_TYPE, - func_ctx->mem_info[0].mem_base_addr, "mem_base"))) { + func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -1015,16 +1010,11 @@ get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { LLVMValueRef mem_size; - if (func_ctx->mem_space_unchanged) { - mem_size = func_ctx->mem_info[0].mem_cur_page_count_addr; - } - else { - if (!(mem_size = LLVMBuildLoad2( - comp_ctx->builder, I32_TYPE, - func_ctx->mem_info[0].mem_cur_page_count_addr, "mem_size"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } + if (!(mem_size = LLVMBuildLoad2( + comp_ctx->builder, I32_TYPE, + func_ctx->mem_info[0].mem_cur_page_count, "mem_size"))) { + aot_set_last_error("llvm build load failed."); + goto fail; } return LLVMBuildIntCast(comp_ctx->builder, mem_size, @@ -1165,16 +1155,14 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #if WASM_ENABLE_SHARED_MEMORY != 0 bool is_shared_memory = comp_ctx->comp_data->memories[0].flags & 0x02; - if (func_ctx->mem_space_unchanged || is_shared_memory) { -#else - if (func_ctx->mem_space_unchanged) { -#endif + if (is_shared_memory) mem_base_addr = func_ctx->mem_info[0].mem_base_addr; - } - else { + else +#endif + { if (!(mem_base_addr = LLVMBuildLoad2( comp_ctx->builder, OPQ_PTR_TYPE, - func_ctx->mem_info[0].mem_base_addr, "mem_base"))) { + func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -1206,16 +1194,11 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } } - if (func_ctx->mem_space_unchanged) { - mem_size = func_ctx->mem_info[0].mem_data_size_addr; - } - else { - if (!(mem_size = LLVMBuildLoad2( - comp_ctx->builder, I64_TYPE, - func_ctx->mem_info[0].mem_data_size_addr, "mem_size"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } + if (!(mem_size = LLVMBuildLoad2( + comp_ctx->builder, I64_TYPE, + func_ctx->mem_info[0].mem_data_size, "mem_size"))) { + aot_set_last_error("llvm build load failed."); + goto fail; } ADD_BASIC_BLOCK(check_succ, "check_succ"); diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 14ee4dd2b..30bdeb639 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1186,6 +1186,53 @@ create_local_variables(const AOTCompData *comp_data, return true; } +static bool +restore_from_addr(const AOTCompContext *comp_ctx, const char *name, + LLVMTypeRef type, LLVMValueRef src, LLVMValueRef dest) { + LLVMValueRef item; + if (!(item = LLVMBuildLoad2(comp_ctx->builder, type, src, name))) { + aot_set_last_error("llvm build load failed"); + return false; + } + if (!LLVMBuildStore(comp_ctx->builder, item, dest)) { + aot_set_last_error("llvm build store failed"); + return false; + } + return true; +} + +bool +restore_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { + LLVMTypeRef ptr_type = (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE; + if (!restore_from_addr(comp_ctx, "mem_base_addr", OPQ_PTR_TYPE, + func_ctx->mem_info[0].mem_base_addr_addr, + func_ctx->mem_info[0].mem_base_addr) + || !restore_from_addr(comp_ctx, "mem_data_size", I64_TYPE, + func_ctx->mem_info[0].mem_data_size_addr, + func_ctx->mem_info[0].mem_data_size) + || !restore_from_addr(comp_ctx, "mem_cur_page_count", I32_TYPE, + func_ctx->mem_info[0].mem_cur_page_count_addr, + func_ctx->mem_info[0].mem_cur_page_count) + || !restore_from_addr(comp_ctx, "mem_bound_check_1byte", ptr_type, + func_ctx->mem_info[0].mem_bound_check_1byte_addr, + func_ctx->mem_info[0].mem_bound_check_1byte) + || !restore_from_addr(comp_ctx, "mem_bound_check_2bytes", ptr_type, + func_ctx->mem_info[0].mem_bound_check_2bytes_addr, + func_ctx->mem_info[0].mem_bound_check_2bytes) + || !restore_from_addr(comp_ctx, "mem_bound_check_4bytes", ptr_type, + func_ctx->mem_info[0].mem_bound_check_4bytes_addr, + func_ctx->mem_info[0].mem_bound_check_4bytes) + || !restore_from_addr(comp_ctx, "mem_bound_check_8bytes", ptr_type, + func_ctx->mem_info[0].mem_bound_check_8bytes_addr, + func_ctx->mem_info[0].mem_bound_check_8bytes) + || !restore_from_addr(comp_ctx, "mem_bound_check_16bytes", ptr_type, + func_ctx->mem_info[0].mem_bound_check_16bytes_addr, + func_ctx->mem_info[0].mem_bound_check_16bytes)) + return false; + return true; +} + static bool create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMTypeRef int8_ptr_type, uint32 func_index) @@ -1193,17 +1240,11 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef offset, mem_info_base; uint32 memory_count; WASMModule *module = comp_ctx->comp_data->wasm_module; - WASMFunction *func = module->functions[func_index]; LLVMTypeRef bound_check_type; - 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; - memory_count = module->memory_count + module->import_memory_count; /* If the module doesn't have memory, reserve one mem_info space with empty content */ @@ -1263,7 +1304,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* memories[0]->memory_data */ offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2( + if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildInBoundsGEP2( comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, "mem_base_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); @@ -1274,7 +1315,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, - "mem_cur_page_offset"))) { + "mem_cur_page_count_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } @@ -1301,7 +1342,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offset_of_global_table_data + offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2( + if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildInBoundsGEP2( comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, "mem_base_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); @@ -1312,7 +1353,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, - "mem_cur_page_offset"))) { + "mem_cur_page_count_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } @@ -1326,59 +1367,55 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } } /* 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"))) { + mem_info_base = func_ctx->mem_info[0].mem_base_addr_addr; + if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr_addr, + int8_ptr_type, "mem_base_addr_addr"))) { 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"))) { + INT32_PTR_TYPE, "mem_cur_page_count_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast( comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr, - INT64_PTR_TYPE, "mem_data_size_ptr"))) { + INT64_PTR_TYPE, "mem_data_size_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad2( - comp_ctx->builder, OPQ_PTR_TYPE, - 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 = - LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, - func_ctx->mem_info[0].mem_cur_page_count_addr, - "mem_cur_page_count"))) { - aot_set_last_error("llvm build load failed"); - return false; - } - if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildLoad2( - comp_ctx->builder, I64_TYPE, - func_ctx->mem_info[0].mem_data_size_addr, "mem_data_size"))) { - aot_set_last_error("llvm build load failed"); - return false; - } - } #if WASM_ENABLE_SHARED_MEMORY != 0 - else if (is_shared_memory) { + 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 = LLVMBuildLoad2( comp_ctx->builder, OPQ_PTR_TYPE, - func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) { + func_ctx->mem_info[0].mem_base_addr_addr, "mem_base_addr"))) { aot_set_last_error("llvm build load failed"); return false; } } + else #endif + { + if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildAlloca( + comp_ctx->builder, OPQ_PTR_TYPE, "mem_base_addr"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + if (!(func_ctx->mem_info[0].mem_data_size = LLVMBuildAlloca( + comp_ctx->builder, I64_TYPE, "mem_data_size"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + if (!(func_ctx->mem_info[0].mem_cur_page_count = LLVMBuildAlloca( + comp_ctx->builder, I32_TYPE, "mem_cur_page_count"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + } bound_check_type = (comp_ctx->pointer_size == sizeof(uint64)) ? INT64_PTR_TYPE @@ -1387,135 +1424,117 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Load memory bound check constants */ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte) - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_1byte = + if (!(func_ctx->mem_info[0].mem_bound_check_1byte_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_1byte = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte, - bound_check_type, "bound_check_1byte_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_1byte_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte_addr, + bound_check_type, "bound_check_1byte_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildLoad2( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - func_ctx->mem_info[0].mem_bound_check_1byte, - "bound_check_1byte"))) { - aot_set_last_error("llvm build load failed"); - return false; - } + if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildAlloca( + comp_ctx->builder, + (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE, + "mem_bound_check_1byte"))) { + aot_set_last_error("llvm build alloca failed."); + return false; } offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes) - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = + if (!(func_ctx->mem_info[0].mem_bound_check_2bytes_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_2bytes = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes, - bound_check_type, "bound_check_2bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_2bytes_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes_addr, + bound_check_type, "bound_check_2bytes_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildLoad2( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - func_ctx->mem_info[0].mem_bound_check_2bytes, - "bound_check_2bytes"))) { - aot_set_last_error("llvm build load failed"); - return false; - } + if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildAlloca( + comp_ctx->builder, + (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE, + "mem_bound_check_2bytes"))) { + aot_set_last_error("llvm build alloca failed."); + return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes) - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = + if (!(func_ctx->mem_info[0].mem_bound_check_4bytes_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_4bytes = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes, - bound_check_type, "bound_check_4bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_4bytes_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes_addr, + bound_check_type, "bound_check_4bytes_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildLoad2( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - func_ctx->mem_info[0].mem_bound_check_4bytes, - "bound_check_4bytes"))) { - aot_set_last_error("llvm build load failed"); - return false; - } + if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildAlloca( + comp_ctx->builder, + (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE, + "mem_bound_check_4bytes"))) { + aot_set_last_error("llvm build alloca failed."); + return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes) - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = + if (!(func_ctx->mem_info[0].mem_bound_check_8bytes_addr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_8bytes = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes, - bound_check_type, "bound_check_8bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_8bytes_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes_addr, + bound_check_type, "bound_check_8bytes_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildLoad2( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - func_ctx->mem_info[0].mem_bound_check_8bytes, - "bound_check_8bytes"))) { - aot_set_last_error("llvm build load failed"); - return false; - } + if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildAlloca( + comp_ctx->builder, + (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE, + "mem_bound_check_8bytes"))) { + aot_set_last_error("llvm build alloca failed."); + return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes) - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildInBoundsGEP2( + if (!(func_ctx->mem_info[0].mem_bound_check_16bytes_addr = LLVMBuildInBoundsGEP2( comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, "bound_check_16bytes_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes, - bound_check_type, "bound_check_16bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_16bytes_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes_addr, + bound_check_type, "bound_check_16bytes_addr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildLoad2( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - func_ctx->mem_info[0].mem_bound_check_16bytes, - "bound_check_16bytes"))) { - aot_set_last_error("llvm build load failed"); - return false; - } + if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildAlloca( + comp_ctx->builder, + (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE, + "mem_bound_check_16bytes"))) { + aot_set_last_error("llvm build alloca failed."); + return false; } - return true; + return restore_memory_info(comp_ctx, func_ctx); } static bool diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 9c608d301..14004a13a 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -215,13 +215,21 @@ typedef struct AOTCheckedAddr { typedef struct AOTMemInfo { LLVMValueRef mem_base_addr; + LLVMValueRef mem_base_addr_addr; + LLVMValueRef mem_data_size; LLVMValueRef mem_data_size_addr; + LLVMValueRef mem_cur_page_count; LLVMValueRef mem_cur_page_count_addr; LLVMValueRef mem_bound_check_1byte; + LLVMValueRef mem_bound_check_1byte_addr; LLVMValueRef mem_bound_check_2bytes; + LLVMValueRef mem_bound_check_2bytes_addr; LLVMValueRef mem_bound_check_4bytes; + LLVMValueRef mem_bound_check_4bytes_addr; LLVMValueRef mem_bound_check_8bytes; + LLVMValueRef mem_bound_check_8bytes_addr; LLVMValueRef mem_bound_check_16bytes; + LLVMValueRef mem_bound_check_16bytes_addr; } AOTMemInfo; typedef struct AOTFuncContext { @@ -251,7 +259,6 @@ typedef struct AOTFuncContext { LLVMValueRef wasm_stack_top_bound; LLVMValueRef wasm_stack_top_ptr; - bool mem_space_unchanged; AOTCheckedAddrList checked_addr_list; LLVMValueRef shared_heap_base_addr_adj; @@ -653,6 +660,9 @@ unsigned int aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx, const AOTFuncType *callee_func_type); +bool +restore_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + #ifdef __cplusplus } /* end of extern "C" */ #endif From d9325b25494dd3d40c1263dbda2e9f3ed9087fb6 Mon Sep 17 00:00:00 2001 From: "xiangjia.xj" Date: Mon, 10 Mar 2025 17:26:16 +0800 Subject: [PATCH 2/2] refactor: remove the intermediate addresses in AOTMemInfo --- core/iwasm/compilation/aot_compiler.h | 1 + core/iwasm/compilation/aot_llvm.c | 560 ++++++++++++++------------ core/iwasm/compilation/aot_llvm.h | 8 - 3 files changed, 301 insertions(+), 268 deletions(-) diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index 06d8e42bd..01ab8df00 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -648,6 +648,7 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type) #define SIZE_T_TYPE comp_ctx->basic_types.size_t_type #define MD_TYPE comp_ctx->basic_types.meta_data_type #define INT8_PTR_TYPE comp_ctx->basic_types.int8_ptr_type +#define INT8_PPTR_TYPE comp_ctx->basic_types.int8_pptr_type #define INT16_PTR_TYPE comp_ctx->basic_types.int16_ptr_type #define INT32_PTR_TYPE comp_ctx->basic_types.int32_ptr_type #define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 30bdeb639..8bba50490 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1188,7 +1188,8 @@ create_local_variables(const AOTCompData *comp_data, static bool restore_from_addr(const AOTCompContext *comp_ctx, const char *name, - LLVMTypeRef type, LLVMValueRef src, LLVMValueRef dest) { + LLVMTypeRef type, LLVMValueRef src, LLVMValueRef dest) +{ LLVMValueRef item; if (!(item = LLVMBuildLoad2(comp_ctx->builder, type, src, name))) { aot_set_last_error("llvm build load failed"); @@ -1201,43 +1202,291 @@ restore_from_addr(const AOTCompContext *comp_ctx, const char *name, return true; } +#if WASM_ENABLE_SHARED_MEMORY != 0 +static LLVMValueRef +aot_get_shared_mem_addr(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset, shared_mem_addr; + offset = I32_CONST(offsetof(AOTModuleInstance, memories)); + if (!offset) { + aot_set_last_error("create llvm const failed."); + return NULL; + } + + /* aot_inst->memories */ + if (!(shared_mem_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, + "shared_mem_addr_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return NULL; + } + if (!(shared_mem_addr = + LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr, + INT8_PPTR_TYPE, "shared_mem_addr_ptr"))) { + aot_set_last_error("llvm build bit cast failed"); + return NULL; + } + /* aot_inst->memories[0] */ + if (!(shared_mem_addr = + LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, + shared_mem_addr, "shared_mem_addr"))) { + aot_set_last_error("llvm build load failed"); + return NULL; + } + if (!(shared_mem_addr = + LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr, + INT8_PPTR_TYPE, "shared_mem_addr_ptr"))) { + aot_set_last_error("llvm build bit cast failed"); + return NULL; + } + if (!(shared_mem_addr = + LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, + shared_mem_addr, "shared_mem_addr"))) { + aot_set_last_error("llvm build load failed"); + return NULL; + } + return shared_mem_addr; +} +#endif + bool -restore_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - LLVMTypeRef ptr_type = (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE; - if (!restore_from_addr(comp_ctx, "mem_base_addr", OPQ_PTR_TYPE, - func_ctx->mem_info[0].mem_base_addr_addr, - func_ctx->mem_info[0].mem_base_addr) - || !restore_from_addr(comp_ctx, "mem_data_size", I64_TYPE, - func_ctx->mem_info[0].mem_data_size_addr, - func_ctx->mem_info[0].mem_data_size) - || !restore_from_addr(comp_ctx, "mem_cur_page_count", I32_TYPE, - func_ctx->mem_info[0].mem_cur_page_count_addr, - func_ctx->mem_info[0].mem_cur_page_count) - || !restore_from_addr(comp_ctx, "mem_bound_check_1byte", ptr_type, - func_ctx->mem_info[0].mem_bound_check_1byte_addr, - func_ctx->mem_info[0].mem_bound_check_1byte) - || !restore_from_addr(comp_ctx, "mem_bound_check_2bytes", ptr_type, - func_ctx->mem_info[0].mem_bound_check_2bytes_addr, - func_ctx->mem_info[0].mem_bound_check_2bytes) - || !restore_from_addr(comp_ctx, "mem_bound_check_4bytes", ptr_type, - func_ctx->mem_info[0].mem_bound_check_4bytes_addr, - func_ctx->mem_info[0].mem_bound_check_4bytes) - || !restore_from_addr(comp_ctx, "mem_bound_check_8bytes", ptr_type, - func_ctx->mem_info[0].mem_bound_check_8bytes_addr, - func_ctx->mem_info[0].mem_bound_check_8bytes) - || !restore_from_addr(comp_ctx, "mem_bound_check_16bytes", ptr_type, - func_ctx->mem_info[0].mem_bound_check_16bytes_addr, - func_ctx->mem_info[0].mem_bound_check_16bytes)) +restore_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset, mem_info_base, mem_base_addr_addr, + mem_cur_page_count_addr, mem_data_size_addr, bound_check_addr; + LLVMTypeRef bound_check_type, bound_check_ptr_type; +#if WASM_ENABLE_SHARED_MEMORY != 0 + bool is_shared_memory = + comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false; + + if (is_shared_memory) { + LLVMValueRef shared_mem_addr; + if (!(shared_mem_addr = aot_get_shared_mem_addr(comp_ctx, func_ctx))) + return false; + + /* memories[0]->memory_data */ + offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data)); + if (!(mem_base_addr_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, + "mem_base_addr_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + /* memories[0]->cur_page_count */ + offset = I32_CONST(offsetof(AOTMemoryInstance, cur_page_count)); + if (!(mem_cur_page_count_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, + "mem_cur_page_count_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + /* memories[0]->memory_data_size */ + offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size)); + if (!(mem_data_size_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, + "mem_data_size_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + } + else +#endif + { + uint32 offset_of_global_table_data; + + if (comp_ctx->is_jit_mode) + offset_of_global_table_data = + offsetof(WASMModuleInstance, global_table_data); + else + offset_of_global_table_data = + offsetof(AOTModuleInstance, global_table_data); + + offset = I32_CONST(offset_of_global_table_data + + offsetof(AOTMemoryInstance, memory_data)); + if (!(mem_base_addr_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, 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(offset_of_global_table_data + + offsetof(AOTMemoryInstance, cur_page_count)); + if (!(mem_cur_page_count_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, + "mem_cur_page_count_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + offset = I32_CONST(offset_of_global_table_data + + offsetof(AOTMemoryInstance, memory_data_size)); + if (!(mem_data_size_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, + "mem_data_size_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + } + /* Store mem info base address before cast */ + mem_info_base = mem_base_addr_addr; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (is_shared_memory) { + /* The base address for shared memory will never changed */ + } + else +#endif + { + /* Store mem_info[0].mem_base_addr */ + if (!(mem_base_addr_addr = LLVMBuildBitCast( + comp_ctx->builder, mem_base_addr_addr, INT8_PPTR_TYPE, + "mem_base_addr_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_base_addr", OPQ_PTR_TYPE, mem_base_addr_addr, + func_ctx->mem_info[0].mem_base_addr)) + return false; + } + + /* Store mem_info[0].mem_cur_page_count */ + if (!(mem_cur_page_count_addr = LLVMBuildBitCast( + comp_ctx->builder, mem_cur_page_count_addr, INT32_PTR_TYPE, + "mem_cur_page_count_addr"))) { + aot_set_last_error("llvm build bit cast failed"); return false; + } + if (!restore_from_addr( + comp_ctx, "mem_cur_page_count", I32_TYPE, mem_cur_page_count_addr, + func_ctx->mem_info[0].mem_cur_page_count)) + return false; + + /* Store mem_info[0].mem_data_size */ + if (!(mem_data_size_addr = LLVMBuildBitCast( + comp_ctx->builder, mem_data_size_addr, INT64_PTR_TYPE, + "mem_data_size_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_data_size", I64_TYPE, mem_data_size_addr, + func_ctx->mem_info[0].mem_data_size)) + return false; + + /* Store memory bound check constants */ + bound_check_type = (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE; + bound_check_ptr_type = (comp_ctx->pointer_size == sizeof(uint64)) + ? INT64_PTR_TYPE + : INT32_PTR_TYPE; + + /* Store mem_info[0].mem_bound_check_1byte */ + offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte) + - offsetof(AOTMemoryInstance, memory_data)); + if (!(bound_check_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, + "bound_check_1byte_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(bound_check_addr = LLVMBuildBitCast( + comp_ctx->builder, bound_check_addr, bound_check_ptr_type, + "bound_check_1byte_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_bound_check_1byte", bound_check_type, + bound_check_addr, func_ctx->mem_info[0].mem_bound_check_1byte)) + return false; + + /* Store mem_info[0].mem_bound_check_2bytes */ + offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes) + - offsetof(AOTMemoryInstance, memory_data)); + if (!(bound_check_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, + "bound_check_2bytes_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(bound_check_addr = LLVMBuildBitCast( + comp_ctx->builder, bound_check_addr, bound_check_ptr_type, + "bound_check_2bytes_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_bound_check_2bytes", bound_check_type, + bound_check_addr, func_ctx->mem_info[0].mem_bound_check_2bytes)) + return false; + + /* Store mem_info[0].mem_bound_check_4bytes */ + offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes) + - offsetof(AOTMemoryInstance, memory_data)); + if (!(bound_check_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, + "bound_check_4bytes_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(bound_check_addr = LLVMBuildBitCast( + comp_ctx->builder, bound_check_addr, bound_check_ptr_type, + "bound_check_4bytes_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_bound_check_4bytes", bound_check_type, + bound_check_addr, func_ctx->mem_info[0].mem_bound_check_4bytes)) + return false; + + /* Store mem_info[0].mem_bound_check_8bytes */ + offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes) + - offsetof(AOTMemoryInstance, memory_data)); + if (!(bound_check_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, + "bound_check_8bytes_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(bound_check_addr = LLVMBuildBitCast( + comp_ctx->builder, bound_check_addr, bound_check_ptr_type, + "bound_check_8bytes_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_bound_check_8bytes", bound_check_type, + bound_check_addr, func_ctx->mem_info[0].mem_bound_check_8bytes)) + return false; + + /* Store mem_info[0].mem_bound_check_16bytes */ + offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes) + - offsetof(AOTMemoryInstance, memory_data)); + if (!(bound_check_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, + "bound_check_16bytes_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(bound_check_addr = LLVMBuildBitCast( + comp_ctx->builder, bound_check_addr, bound_check_ptr_type, + "bound_check_16bytes_addr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!restore_from_addr( + comp_ctx, "mem_bound_check_16bytes", bound_check_type, + bound_check_addr, func_ctx->mem_info[0].mem_bound_check_16bytes)) + return false; + return true; } static bool create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMTypeRef int8_ptr_type, uint32 func_index) + uint32 func_index) { - LLVMValueRef offset, mem_info_base; + LLVMValueRef offset; uint32 memory_count; WASMModule *module = comp_ctx->comp_data->wasm_module; LLVMTypeRef bound_check_type; @@ -1263,136 +1512,23 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, is_shared_memory = comp_ctx->comp_data->memories[0].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."); + LLVMValueRef shared_mem_addr, mem_base_addr_addr; + if (!(shared_mem_addr = aot_get_shared_mem_addr(comp_ctx, func_ctx))) return false; - } - /* aot_inst->memories */ - if (!(shared_mem_addr = LLVMBuildInBoundsGEP2( - comp_ctx->builder, INT8_TYPE, 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 = - LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, - 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 = - LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, - shared_mem_addr, "shared_mem_addr"))) { - aot_set_last_error("llvm build load failed"); - return false; - } /* memories[0]->memory_data */ offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildInBoundsGEP2( + if (!(mem_base_addr_addr = LLVMBuildInBoundsGEP2( comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, "mem_base_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - /* memories[0]->cur_page_count */ - offset = I32_CONST(offsetof(AOTMemoryInstance, cur_page_count)); - if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - shared_mem_addr, &offset, 1, - "mem_cur_page_count_offset"))) { - aot_set_last_error("llvm build in bounds gep failed"); - return false; - } - /* memories[0]->memory_data_size */ - offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size)); - if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2( - comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1, - "mem_data_size_offset"))) { - aot_set_last_error("llvm build in bounds gep failed"); - return false; - } - } - else -#endif - { - uint32 offset_of_global_table_data; - - if (comp_ctx->is_jit_mode) - offset_of_global_table_data = - offsetof(WASMModuleInstance, global_table_data); - else - offset_of_global_table_data = - offsetof(AOTModuleInstance, global_table_data); - - offset = I32_CONST(offset_of_global_table_data - + offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildInBoundsGEP2( - comp_ctx->builder, INT8_TYPE, 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(offset_of_global_table_data - + offsetof(AOTMemoryInstance, cur_page_count)); - if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - func_ctx->aot_inst, &offset, 1, - "mem_cur_page_count_offset"))) { - aot_set_last_error("llvm build in bounds gep failed"); - return false; - } - offset = I32_CONST(offset_of_global_table_data - + offsetof(AOTMemoryInstance, memory_data_size)); - if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2( - comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1, - "mem_data_size_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_addr; - if (!(func_ctx->mem_info[0].mem_base_addr_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr_addr, - int8_ptr_type, "mem_base_addr_addr"))) { - 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_count_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } - if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr, - INT64_PTR_TYPE, "mem_data_size_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } -#if WASM_ENABLE_SHARED_MEMORY != 0 - 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 = LLVMBuildLoad2( - comp_ctx->builder, OPQ_PTR_TYPE, - func_ctx->mem_info[0].mem_base_addr_addr, "mem_base_addr"))) { + if (!(func_ctx->mem_info[0].mem_base_addr = + LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, + mem_base_addr_addr, "mem_base_addr"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -1405,131 +1541,41 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build alloca failed."); return false; } - if (!(func_ctx->mem_info[0].mem_data_size = LLVMBuildAlloca( - comp_ctx->builder, I64_TYPE, "mem_data_size"))) { - aot_set_last_error("llvm build alloca failed."); - return false; - } - if (!(func_ctx->mem_info[0].mem_cur_page_count = LLVMBuildAlloca( - comp_ctx->builder, I32_TYPE, "mem_cur_page_count"))) { - aot_set_last_error("llvm build alloca failed."); - return false; - } } - - bound_check_type = (comp_ctx->pointer_size == sizeof(uint64)) - ? INT64_PTR_TYPE - : INT32_PTR_TYPE; - - /* Load memory bound check constants */ - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte) - - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_1byte_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_1byte_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte_addr, - bound_check_type, "bound_check_1byte_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } - if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildAlloca( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - "mem_bound_check_1byte"))) { + if (!(func_ctx->mem_info[0].mem_data_size = LLVMBuildAlloca( + comp_ctx->builder, I64_TYPE, "mem_data_size"))) { aot_set_last_error("llvm build alloca failed."); return false; } - - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes) - - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_2bytes_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base, - &offset, 1, "bound_check_2bytes_offset"))) { - aot_set_last_error("llvm build in bounds gep failed"); + if (!(func_ctx->mem_info[0].mem_cur_page_count = LLVMBuildAlloca( + comp_ctx->builder, I32_TYPE, "mem_cur_page_count"))) { + aot_set_last_error("llvm build alloca failed."); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_2bytes_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes_addr, - bound_check_type, "bound_check_2bytes_addr"))) { - aot_set_last_error("llvm build bit cast failed"); + bound_check_type = (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE + : I32_TYPE; + if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildAlloca( + comp_ctx->builder, bound_check_type, "mem_bound_check_1byte"))) { + aot_set_last_error("llvm build alloca failed."); return false; } if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildAlloca( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - "mem_bound_check_2bytes"))) { + comp_ctx->builder, bound_check_type, "mem_bound_check_2bytes"))) { aot_set_last_error("llvm build alloca failed."); return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes) - - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_4bytes_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_4bytes_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes_addr, - bound_check_type, "bound_check_4bytes_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildAlloca( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - "mem_bound_check_4bytes"))) { + comp_ctx->builder, bound_check_type, "mem_bound_check_4bytes"))) { aot_set_last_error("llvm build alloca failed."); return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes) - - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_8bytes_addr = - LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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_info[0].mem_bound_check_8bytes_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes_addr, - bound_check_type, "bound_check_8bytes_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildAlloca( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - "mem_bound_check_8bytes"))) { + comp_ctx->builder, bound_check_type, "mem_bound_check_8bytes"))) { aot_set_last_error("llvm build alloca failed."); return false; } - offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes) - - offsetof(AOTMemoryInstance, memory_data)); - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes_addr = LLVMBuildInBoundsGEP2( - comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1, - "bound_check_16bytes_offset"))) { - aot_set_last_error("llvm build in bounds gep failed"); - return false; - } - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes_addr = LLVMBuildBitCast( - comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes_addr, - bound_check_type, "bound_check_16bytes_addr"))) { - aot_set_last_error("llvm build bit cast failed"); - return false; - } if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildAlloca( - comp_ctx->builder, - (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE - : I32_TYPE, - "mem_bound_check_16bytes"))) { + comp_ctx->builder, bound_check_type, "mem_bound_check_16bytes"))) { aot_set_last_error("llvm build alloca failed."); return false; } @@ -1805,7 +1851,6 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx, WASMModule *module = comp_ctx->comp_data->wasm_module; WASMFunction *wasm_func = module->functions[func_index]; AOTBlock *aot_block; - LLVMTypeRef int8_ptr_type; uint64 size; /* Allocate memory for the function context */ @@ -1869,14 +1914,9 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx, goto fail; } - if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) { - aot_set_last_error("llvm add pointer type failed."); - goto fail; - } - /* Create base addr, end addr, data size of mem, heap */ if (wasm_func->has_memory_operations - && !create_memory_info(comp_ctx, func_ctx, int8_ptr_type, func_index)) { + && !create_memory_info(comp_ctx, func_ctx, func_index)) { goto fail; } diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 14004a13a..fb1162511 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -215,21 +215,13 @@ typedef struct AOTCheckedAddr { typedef struct AOTMemInfo { LLVMValueRef mem_base_addr; - LLVMValueRef mem_base_addr_addr; LLVMValueRef mem_data_size; - LLVMValueRef mem_data_size_addr; LLVMValueRef mem_cur_page_count; - LLVMValueRef mem_cur_page_count_addr; LLVMValueRef mem_bound_check_1byte; - LLVMValueRef mem_bound_check_1byte_addr; LLVMValueRef mem_bound_check_2bytes; - LLVMValueRef mem_bound_check_2bytes_addr; LLVMValueRef mem_bound_check_4bytes; - LLVMValueRef mem_bound_check_4bytes_addr; LLVMValueRef mem_bound_check_8bytes; - LLVMValueRef mem_bound_check_8bytes_addr; LLVMValueRef mem_bound_check_16bytes; - LLVMValueRef mem_bound_check_16bytes_addr; } AOTMemInfo; typedef struct AOTFuncContext {