Skip to content

Commit bf2d478

Browse files
committed
fix: allocate stack space for struct undef values in Cranelift JIT
Previously, HirValueKind::Undef for struct types was mapped to iconst(0), causing InsertValue operations to attempt stores to address 0, resulting in segfaults during JIT execution. Now struct undef values are properly allocated on the stack: - Calculate struct size from field types - Create stack slot with cranelift_codegen::ir::StackSlotData - Return stack address pointer instead of zero constant This enables struct initialization with field access to work correctly: const p = Point{ .x = 10, .y = 20 }; return p.x; // Returns 10
1 parent 8ebf3c5 commit bf2d478

1 file changed

Lines changed: 39 additions & 13 deletions

File tree

crates/compiler/src/cranelift_backend.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -702,22 +702,48 @@ impl CraneliftBackend {
702702
}
703703

704704
// Map undef values to zero constants (for IDF-based SSA)
705+
// For struct types, allocate stack space instead of using a zero constant
705706
for value in function.values.values() {
706707
if let HirValueKind::Undef = value.kind {
707-
let ty = type_cache.get(&value.ty).copied().unwrap_or(types::I64);
708-
let cranelift_val = if ty.is_int() {
709-
builder.ins().iconst(ty, 0)
710-
} else if ty.is_float() {
711-
if ty == types::F32 {
712-
builder.ins().f32const(0.0)
713-
} else {
714-
builder.ins().f64const(0.0)
715-
}
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+
723+
let slot = builder.create_sized_stack_slot(cranelift_codegen::ir::StackSlotData::new(
724+
cranelift_codegen::ir::StackSlotKind::ExplicitSlot,
725+
struct_size,
726+
));
727+
let ptr = builder.ins().stack_addr(self.module.target_config().pointer_type(), slot, 0);
728+
self.value_map.insert(value.id, ptr);
729+
eprintln!("[CRANELIFT UNDEF] Allocated {} bytes stack for struct undef {:?}", struct_size, value.id);
716730
} else {
717-
// For other types, use null constant
718-
builder.ins().iconst(ty, 0)
719-
};
720-
self.value_map.insert(value.id, cranelift_val);
731+
// For scalar types, use zero constant
732+
let ty = type_cache.get(&value.ty).copied().unwrap_or(types::I64);
733+
let cranelift_val = if ty.is_int() {
734+
builder.ins().iconst(ty, 0)
735+
} else if ty.is_float() {
736+
if ty == types::F32 {
737+
builder.ins().f32const(0.0)
738+
} else {
739+
builder.ins().f64const(0.0)
740+
}
741+
} else {
742+
// For other types, use null constant
743+
builder.ins().iconst(ty, 0)
744+
};
745+
self.value_map.insert(value.id, cranelift_val);
746+
}
721747
}
722748
}
723749

0 commit comments

Comments
 (0)