mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Merge pull request #4611 from tf2spi/4491-max-field-align-pack
Add packing + aligned access w/ field_align
This commit is contained in:
@@ -747,3 +747,5 @@ gb_global char const *llvm_linkage_strings[] = {
|
||||
};
|
||||
|
||||
#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed")
|
||||
#define ODIN_METADATA_MIN_ALIGN str_lit("odin-min-align")
|
||||
#define ODIN_METADATA_MAX_ALIGN str_lit("odin-max-align")
|
||||
|
||||
@@ -734,6 +734,17 @@ gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLV
|
||||
if (is_packed != 0) {
|
||||
LLVMSetAlignment(result, 1);
|
||||
}
|
||||
u64 align = LLVMGetAlignment(result);
|
||||
u64 align_min = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MIN_ALIGN);
|
||||
u64 align_max = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MAX_ALIGN);
|
||||
if (align_min != 0 && align < align_min) {
|
||||
align = align_min;
|
||||
}
|
||||
if (align_max != 0 && align > align_max) {
|
||||
align = align_max;
|
||||
}
|
||||
GB_ASSERT(align <= UINT_MAX);
|
||||
LLVMSetAlignment(result, (unsigned int)align);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2121,6 +2132,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
}
|
||||
|
||||
i64 prev_offset = 0;
|
||||
bool requires_packing = type->Struct.is_packed;
|
||||
for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) {
|
||||
Entity *field = type->Struct.fields[field_index];
|
||||
i64 offset = type->Struct.offsets[field_index];
|
||||
@@ -2141,6 +2153,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
field_type = t_rawptr;
|
||||
}
|
||||
|
||||
// max_field_align might misalign items in a way that requires packing
|
||||
// so check the alignment of all fields to see if packing is required.
|
||||
requires_packing = requires_packing || ((offset % type_align_of(field_type)) != 0);
|
||||
|
||||
array_add(&fields, lb_type(m, field_type));
|
||||
|
||||
prev_offset = offset + type_size_of(field->type);
|
||||
@@ -2155,7 +2171,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
GB_ASSERT(fields[i] != nullptr);
|
||||
}
|
||||
|
||||
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed);
|
||||
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
|
||||
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
|
||||
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
|
||||
#if 0
|
||||
|
||||
@@ -1200,9 +1200,22 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
|
||||
lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type);
|
||||
|
||||
Type *bt = base_type(t);
|
||||
if (bt->kind == Type_Struct && bt->Struct.is_packed) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
|
||||
if (bt->kind == Type_Struct) {
|
||||
if (bt->Struct.is_packed) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
|
||||
}
|
||||
u64 align_max = bt->Struct.custom_max_field_align;
|
||||
u64 align_min = bt->Struct.custom_min_field_align;
|
||||
GB_ASSERT(align_min == 0 || align_max == 0 || align_min <= align_max);
|
||||
if (align_max) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN, align_max);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN) == align_max);
|
||||
}
|
||||
if (align_min) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN, align_min);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN) == align_min);
|
||||
}
|
||||
}
|
||||
|
||||
return gep;
|
||||
|
||||
Reference in New Issue
Block a user