Skip to content

Commit 79906ae

Browse files
committed
refactor: use proper type_size() for aggregate undef allocation
Instead of manually computing struct sizes inline, use the existing type_size() method which correctly handles: - Proper alignment padding (e.g., {i8, i64} is 16 bytes, not 9) - Nested structs and arrays - Unions and closures Pre-compute sizes before the FunctionBuilder scope to avoid borrow checker issues with self.
1 parent bf2d478 commit 79906ae

1 file changed

Lines changed: 24 additions & 19 deletions

File tree

crates/compiler/src/cranelift_backend.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,24 @@ impl CraneliftBackend {
594594
}
595595
}
596596

597+
// Pre-compute sizes for aggregate undef values (to avoid borrow checker issues later)
598+
let mut undef_aggregate_sizes: HashMap<HirId, u32> = HashMap::new();
599+
for value in function.values.values() {
600+
if let HirValueKind::Undef = value.kind {
601+
match &value.ty {
602+
HirType::Struct(_) | HirType::Array(_, _) | HirType::Union(_) => {
603+
let alloc_size = self.type_size(&value.ty).unwrap_or(8) as u32;
604+
let alloc_size = std::cmp::max(alloc_size, 8); // At least 8 bytes
605+
undef_aggregate_sizes.insert(value.id, alloc_size);
606+
}
607+
_ => {}
608+
}
609+
}
610+
}
611+
612+
// Pre-compute pointer type for use inside builder scope
613+
let pointer_type = self.module.target_config().pointer_type();
614+
597615
// Phase 2: Create builder and all Cranelift blocks
598616
let mut builder = FunctionBuilder::new(
599617
&mut self.codegen_context.func,
@@ -702,31 +720,18 @@ impl CraneliftBackend {
702720
}
703721

704722
// Map undef values to zero constants (for IDF-based SSA)
705-
// For struct types, allocate stack space instead of using a zero constant
723+
// For aggregate types (structs, arrays), allocate stack space instead of using a zero constant
706724
for value in function.values.values() {
707725
if let HirValueKind::Undef = value.kind {
708-
// Check if this is a struct type that needs stack allocation
709-
if let HirType::Struct(struct_ty) = &value.ty {
710-
// Allocate stack space for the struct
711-
let struct_size = struct_ty.fields.iter()
712-
.map(|f| match f {
713-
HirType::I8 | HirType::U8 | HirType::Bool => 1,
714-
HirType::I16 | HirType::U16 => 2,
715-
HirType::I32 | HirType::U32 | HirType::F32 => 4,
716-
HirType::I64 | HirType::U64 | HirType::F64 | HirType::Ptr(_) => 8,
717-
HirType::I128 | HirType::U128 => 16,
718-
_ => 8, // Default
719-
})
720-
.sum::<usize>();
721-
let struct_size = std::cmp::max(struct_size, 8) as u32; // At least 8 bytes
722-
726+
// Check if this is an aggregate type with pre-computed size
727+
if let Some(&alloc_size) = undef_aggregate_sizes.get(&value.id) {
723728
let slot = builder.create_sized_stack_slot(cranelift_codegen::ir::StackSlotData::new(
724729
cranelift_codegen::ir::StackSlotKind::ExplicitSlot,
725-
struct_size,
730+
alloc_size,
726731
));
727-
let ptr = builder.ins().stack_addr(self.module.target_config().pointer_type(), slot, 0);
732+
let ptr = builder.ins().stack_addr(pointer_type, slot, 0);
728733
self.value_map.insert(value.id, ptr);
729-
eprintln!("[CRANELIFT UNDEF] Allocated {} bytes stack for struct undef {:?}", struct_size, value.id);
734+
eprintln!("[CRANELIFT UNDEF] Allocated {} bytes stack for aggregate undef {:?}", alloc_size, value.id);
730735
} else {
731736
// For scalar types, use zero constant
732737
let ty = type_cache.get(&value.ty).copied().unwrap_or(types::I64);

0 commit comments

Comments
 (0)