struct field reordering (minimizing padding)

This commit is contained in:
2026-08-09 14:12:25 +02:00
parent 729488e702
commit 6688822de2
4 changed files with 111 additions and 15 deletions
+38 -5
View File
@@ -1117,6 +1117,15 @@ emit_instruction_stream :: proc(
} else if item.kind == .Range && arg_index == 2 {
element_type = types.BOOL
}
aggregate_index := arg_index
if item.kind == .Struct {
aggregate_index = types.physical_field_index(
&emitter.module.types,
instruction.type,
arg_index,
emitter.module.target,
)
}
final := arg_index == total-1
if final {
fmt.sbprintf(&emitter.builder, " %%v%d = insertvalue %s ", instruction_index, type_name)
@@ -1134,7 +1143,7 @@ emit_instruction_stream :: proc(
} else {
write_constant(&emitter.builder, i64(item.sentinel), element_type, &emitter.module.types)
}
fmt.sbprintf(&emitter.builder, ", %d\n", arg_index)
fmt.sbprintf(&emitter.builder, ", %d\n", aggregate_index)
}
case .Null:
item, ok := types.node(&emitter.module.types, instruction.type)
@@ -1334,13 +1343,19 @@ emit_instruction_stream :: proc(
emit_recovery_value(emitter, instruction_index, instruction, "invalid field reference")
continue
}
physical_index := types.physical_field_index(
&emitter.module.types,
base_type,
field_index,
emitter.module.target,
)
if types.is_union(base_type, &emitter.module.types) {
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr i8, ptr %%v%d, i64 %d\n", instruction_index, instruction.a, types.union_payload_offset(base_type, &emitter.module.types, emitter.module.target))
} else {
fmt.sbprintf(
&emitter.builder,
" %%v%d = getelementptr %s, ptr %%v%d, i32 0, i32 %d\n",
instruction_index, llvm_type(base_type, &emitter.module.types), instruction.a, field_index,
instruction_index, llvm_type(base_type, &emitter.module.types), instruction.a, physical_index,
)
}
case .Load:
@@ -2593,12 +2608,30 @@ emit_types :: proc(emitter: ^Emitter) {
strings.write_string(&emitter.builder, " }\n")
continue
}
fields := types.fields_for(&emitter.module.types, id)
strings.write_string(&emitter.builder, "{ ")
for field, field_index in types.fields_for(&emitter.module.types, id) {
if field_index > 0 {
previous_index := -1
for physical_index in 0..<len(fields) {
logical_index := -1
for _, candidate_index in fields {
if previous_index >= 0 &&
!types.field_layout_precedes(
&emitter.module.types, id, previous_index, candidate_index, emitter.module.target,
) {
continue
}
if logical_index < 0 ||
types.field_layout_precedes(
&emitter.module.types, id, candidate_index, logical_index, emitter.module.target,
) {
logical_index = candidate_index
}
}
if physical_index > 0 {
strings.write_string(&emitter.builder, ", ")
}
strings.write_string(&emitter.builder, llvm_type(field.type, &emitter.module.types))
strings.write_string(&emitter.builder, llvm_type(fields[logical_index].type, &emitter.module.types))
previous_index = logical_index
}
strings.write_string(&emitter.builder, " }\n")
}