mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-17 01:38:15 +00:00
Fix GC struct field offset calculation in AOT compiler (#2746)
The struct field size and field offset of a wasm struct may vary in 32-bit target and 64-bit target, the aot compiler should not use the offset calculated in wasm loader. It re-calculates them according to the target info and whether GC is enabled. And set the alignment of sruct.get/set when field size is 2, 4, or 8.
This commit is contained in:
parent
f92630108c
commit
943274e3b9
|
@ -384,13 +384,81 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static void
|
||||
calculate_struct_field_sizes_offsets(AOTCompData *comp_data, bool is_target_x86,
|
||||
bool gc_enabled)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < comp_data->type_count; i++) {
|
||||
if (comp_data->types[i]->type_flag == WASM_TYPE_STRUCT) {
|
||||
WASMStructType *struct_type = (WASMStructType *)comp_data->types[i];
|
||||
WASMStructFieldType *fields = struct_type->fields;
|
||||
uint32 field_offset_64bit, field_offset_32bit;
|
||||
uint32 field_size_64bit, field_size_32bit, j;
|
||||
|
||||
/* offsetof(WASMStructObject, field_data) in 64-bit */
|
||||
field_offset_64bit = sizeof(uint64);
|
||||
|
||||
/* offsetof(WASMStructObject, field_data) in 32-bit */
|
||||
field_offset_32bit = sizeof(uint32);
|
||||
|
||||
for (j = 0; j < struct_type->field_count; j++) {
|
||||
get_value_type_size(fields[j].field_type, gc_enabled,
|
||||
&field_size_64bit, &field_size_32bit);
|
||||
|
||||
fields[j].field_size_64bit = field_size_64bit;
|
||||
fields[j].field_size_32bit = field_size_32bit;
|
||||
|
||||
if (!is_target_x86) {
|
||||
if (field_size_64bit == 2)
|
||||
field_offset_64bit = align_uint(field_offset_64bit, 2);
|
||||
else if (field_size_64bit >= 4)
|
||||
field_offset_64bit = align_uint(field_offset_64bit, 4);
|
||||
|
||||
if (field_size_32bit == 2)
|
||||
field_offset_32bit = align_uint(field_offset_32bit, 2);
|
||||
else if (field_size_32bit >= 4)
|
||||
field_offset_32bit = align_uint(field_offset_32bit, 4);
|
||||
}
|
||||
|
||||
fields[j].field_offset_64bit = field_offset_64bit;
|
||||
fields[j].field_offset_32bit = field_offset_32bit;
|
||||
|
||||
field_offset_64bit += field_size_64bit;
|
||||
field_offset_32bit += field_size_32bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
AOTCompData *
|
||||
aot_create_comp_data(WASMModule *module, bool gc_enabled)
|
||||
aot_create_comp_data(WASMModule *module, const char *target_arch,
|
||||
bool gc_enabled)
|
||||
{
|
||||
AOTCompData *comp_data;
|
||||
uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0, i, j;
|
||||
uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
|
||||
uint64 size;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
bool is_target_x86 = false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (!target_arch) {
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
|
||||
|| defined(BUILD_TARGET_X86_32)
|
||||
is_target_x86 = true;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (!strncmp(target_arch, "x86_64", 6)
|
||||
|| !strncmp(target_arch, "i386", 4))
|
||||
is_target_x86 = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate memory */
|
||||
if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
|
||||
|
@ -534,6 +602,11 @@ aot_create_comp_data(WASMModule *module, bool gc_enabled)
|
|||
/* Create types, they are checked by wasm loader */
|
||||
comp_data->type_count = module->type_count;
|
||||
comp_data->types = module->types;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* Calculate the field sizes and field offsets for 64-bit and 32-bit
|
||||
targets since they may vary in 32-bit target and 64-bit target */
|
||||
calculate_struct_field_sizes_offsets(comp_data, is_target_x86, gc_enabled);
|
||||
#endif
|
||||
|
||||
/* Create import functions */
|
||||
comp_data->import_func_count = module->import_function_count;
|
||||
|
|
|
@ -332,7 +332,8 @@ typedef struct AOTNativeSymbol {
|
|||
} AOTNativeSymbol;
|
||||
|
||||
AOTCompData *
|
||||
aot_create_comp_data(WASMModule *module, bool gc_enabled);
|
||||
aot_create_comp_data(WASMModule *module, const char *target_arch,
|
||||
bool gc_enabled);
|
||||
|
||||
void
|
||||
aot_destroy_comp_data(AOTCompData *comp_data);
|
||||
|
|
|
@ -73,6 +73,13 @@
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
is_target_x86(AOTCompContext *comp_ctx)
|
||||
{
|
||||
return !strncmp(comp_ctx->target_arch, "x86_64", 6)
|
||||
|| !strncmp(comp_ctx->target_arch, "i386", 4);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_call_aot_create_func_obj(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef func_idx, LLVMValueRef *p_gc_obj)
|
||||
|
@ -345,7 +352,7 @@ aot_struct_obj_set_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
|
|||
uint8 field_type)
|
||||
{
|
||||
bool trunc = false;
|
||||
LLVMValueRef field_data_ptr;
|
||||
LLVMValueRef field_data_ptr, res;
|
||||
LLVMTypeRef field_data_type = NULL, field_data_ptr_type = NULL;
|
||||
|
||||
get_struct_field_data_types(comp_ctx, field_type, &field_data_type,
|
||||
|
@ -383,11 +390,18 @@ aot_struct_obj_set_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!LLVMBuildStore(comp_ctx->builder, field_value, field_data_ptr)) {
|
||||
if (!(res =
|
||||
LLVMBuildStore(comp_ctx->builder, field_value, field_data_ptr))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!is_target_x86(comp_ctx)
|
||||
&& (field_data_type == I64_TYPE || field_data_type == F64_TYPE
|
||||
|| field_data_type == GC_REF_TYPE)) {
|
||||
LLVMSetAlignment(res, 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -431,6 +445,12 @@ aot_struct_obj_get_field(AOTCompContext *comp_ctx, LLVMValueRef struct_obj,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!is_target_x86(comp_ctx)
|
||||
&& (field_data_type == I64_TYPE || field_data_type == F64_TYPE
|
||||
|| field_data_type == GC_REF_TYPE)) {
|
||||
LLVMSetAlignment(field_value, 4);
|
||||
}
|
||||
|
||||
if (extend) {
|
||||
if (sign_extend) {
|
||||
if (!(field_value = LLVMBuildSExt(comp_ctx->builder, field_value,
|
||||
|
@ -466,11 +486,14 @@ struct_new_canon_init_fields(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
WASMStructFieldType *fields = compile_time_struct_type->fields;
|
||||
int32 field_count = (int32)compile_time_struct_type->field_count;
|
||||
int32 field_idx;
|
||||
uint8 field_type, field_offset;
|
||||
uint32 field_offset;
|
||||
uint8 field_type;
|
||||
|
||||
for (field_idx = field_count - 1; field_idx >= 0; field_idx--) {
|
||||
field_type = fields[field_idx].field_type;
|
||||
field_offset = fields[field_idx].field_offset;
|
||||
field_offset = comp_ctx->pointer_size == sizeof(uint64)
|
||||
? fields[field_idx].field_offset_64bit
|
||||
: fields[field_idx].field_offset_32bit;
|
||||
|
||||
if (wasm_is_type_reftype(field_type)) {
|
||||
POP_GC_REF(field_value);
|
||||
|
@ -565,11 +588,14 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
WASMStructType *compile_time_struct_type =
|
||||
(WASMStructType *)comp_ctx->comp_data->types[type_index];
|
||||
WASMStructFieldType *field;
|
||||
uint8 field_type, field_offset;
|
||||
uint32 field_offset;
|
||||
uint8 field_type;
|
||||
|
||||
field = compile_time_struct_type->fields + field_idx;
|
||||
field_type = field->field_type;
|
||||
field_offset = field->field_offset;
|
||||
field_offset = comp_ctx->pointer_size == sizeof(uint64)
|
||||
? field->field_offset_64bit
|
||||
: field->field_offset_32bit;
|
||||
|
||||
if (field_idx >= compile_time_struct_type->field_count) {
|
||||
aot_set_last_error("struct field index out of bounds");
|
||||
|
@ -626,11 +652,14 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
WASMStructType *compile_time_struct_type =
|
||||
(WASMStructType *)comp_ctx->comp_data->types[type_index];
|
||||
WASMStructFieldType *field;
|
||||
uint8 field_type, field_offset;
|
||||
uint32 field_offset;
|
||||
uint8 field_type;
|
||||
|
||||
field = compile_time_struct_type->fields + field_idx;
|
||||
field_type = field->field_type;
|
||||
field_offset = field->field_offset;
|
||||
field_offset = comp_ctx->pointer_size == sizeof(uint64)
|
||||
? field->field_offset_64bit
|
||||
: field->field_offset_32bit;
|
||||
|
||||
if (field_idx >= compile_time_struct_type->field_count) {
|
||||
aot_set_last_error("struct field index out of bounds");
|
||||
|
@ -805,7 +834,7 @@ aot_array_obj_set_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
LLVMValueRef array_elem, uint8 array_elem_type)
|
||||
{
|
||||
bool trunc = false;
|
||||
LLVMValueRef elem_data_ptr;
|
||||
LLVMValueRef elem_data_ptr, res;
|
||||
LLVMTypeRef elem_data_type = NULL, elem_data_ptr_type = NULL;
|
||||
|
||||
if (!aot_array_obj_elem_addr(comp_ctx, func_ctx, array_obj, elem_idx,
|
||||
|
@ -867,11 +896,17 @@ aot_array_obj_set_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!LLVMBuildStore(comp_ctx->builder, array_elem, elem_data_ptr)) {
|
||||
if (!(res = LLVMBuildStore(comp_ctx->builder, array_elem, elem_data_ptr))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!is_target_x86(comp_ctx)
|
||||
&& (elem_data_type == I64_TYPE || elem_data_type == F64_TYPE
|
||||
|| elem_data_type == GC_REF_TYPE)) {
|
||||
LLVMSetAlignment(res, 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -991,6 +1026,12 @@ aot_call_wasm_array_get_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!is_target_x86(comp_ctx)
|
||||
&& (elem_data_type == I64_TYPE || elem_data_type == F64_TYPE
|
||||
|| elem_data_type == GC_REF_TYPE)) {
|
||||
LLVMSetAlignment(array_elem, 4);
|
||||
}
|
||||
|
||||
if (extend) {
|
||||
if (sign) {
|
||||
if (!(array_elem = LLVMBuildSExt(comp_ctx->builder, array_elem,
|
||||
|
|
|
@ -22,7 +22,8 @@ struct AOTCompContext;
|
|||
typedef struct AOTCompContext *aot_comp_context_t;
|
||||
|
||||
aot_comp_data_t
|
||||
aot_create_comp_data(void *wasm_module, bool gc_enabled);
|
||||
aot_create_comp_data(void *wasm_module, const char *target_arch,
|
||||
bool gc_enabled);
|
||||
|
||||
void
|
||||
aot_destroy_comp_data(aot_comp_data_t comp_data);
|
||||
|
|
|
@ -339,6 +339,19 @@ typedef struct WASMStructFieldType {
|
|||
uint8 field_type;
|
||||
uint8 field_size;
|
||||
uint32 field_offset;
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
|
||||
/*
|
||||
* The field size and field offset of a wasm struct may vary
|
||||
* in 32-bit target and 64-bit target, e.g., the size of a
|
||||
* GC reference is 4 bytes in the former and 8 bytes in the
|
||||
* latter, the AOT compiler needs to use the correct field
|
||||
* offset according to the target info.
|
||||
*/
|
||||
uint8 field_size_64bit;
|
||||
uint8 field_size_32bit;
|
||||
uint32 field_offset_64bit;
|
||||
uint32 field_offset_32bit;
|
||||
#endif
|
||||
} WASMStructFieldType;
|
||||
|
||||
typedef struct WASMStructType {
|
||||
|
|
|
@ -4019,13 +4019,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
|||
AOTCompOption option = { 0 };
|
||||
char *aot_last_error;
|
||||
uint64 size;
|
||||
bool gc_enabled =
|
||||
#if WASM_ENABLE_GC != 0
|
||||
true
|
||||
bool gc_enabled = true;
|
||||
#else
|
||||
false
|
||||
bool gc_enabled = false;
|
||||
#endif
|
||||
;
|
||||
|
||||
if (module->function_count == 0)
|
||||
return true;
|
||||
|
@ -4052,7 +4050,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
|||
(bool *)((uint8 *)module->func_ptrs
|
||||
+ sizeof(void *) * module->function_count);
|
||||
|
||||
module->comp_data = aot_create_comp_data(module, gc_enabled);
|
||||
module->comp_data = aot_create_comp_data(module, NULL, gc_enabled);
|
||||
if (!module->comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
|
|
|
@ -1867,7 +1867,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
|||
(bool *)((uint8 *)module->func_ptrs
|
||||
+ sizeof(void *) * module->function_count);
|
||||
|
||||
module->comp_data = aot_create_comp_data(module, gc_enabled);
|
||||
module->comp_data = aot_create_comp_data(module, NULL, gc_enabled);
|
||||
if (!module->comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
|
|
|
@ -630,7 +630,8 @@ main(int argc, char *argv[])
|
|||
goto fail2;
|
||||
}
|
||||
|
||||
if (!(comp_data = aot_create_comp_data(wasm_module, option.enable_gc))) {
|
||||
if (!(comp_data = aot_create_comp_data(wasm_module, option.target_arch,
|
||||
option.enable_gc))) {
|
||||
printf("%s\n", aot_get_last_error());
|
||||
goto fail3;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user