🚀 Major LLVM breakthrough by ChatGPT5\!
PHI type coercion and core-first routing fixes: - Auto type conversion for PHI nodes (i64↔i8*↔i1↔f64) - Fixed ArrayBox.get misrouting to Map path - Core-first strategy for Array/Map creation - Added comprehensive debug logging ([PHI], [ARR], [MAP]) Results: ✅ Array smoke test: 'Result: 3' ✅ Map smoke test: 'Map: v=42, size=1' After 34+ minutes of battling Rust lifetime errors, ChatGPT5 achieved a major breakthrough\! Key insight: The bug wasn't in PHI/SSA logic but in Box type routing - ArrayBox.get was incorrectly caught by Map fallback due to missing annotations. We're SO CLOSE to Nyash self-hosting paradise\! 🌟 Once this stabilizes, everything can be written in simple, beautiful Nyash code instead of Rust complexity.
This commit is contained in:
@ -57,8 +57,23 @@ pub(in super::super) fn emit_jump<'ctx>(
|
||||
if let Some(list) = phis_by_block.get(target) {
|
||||
for (_dst, phi, inputs) in list {
|
||||
if let Some((_, in_vid)) = inputs.iter().find(|(pred, _)| pred == &bid) {
|
||||
let val = *vmap.get(in_vid).ok_or("phi incoming value missing")?;
|
||||
let mut val = *vmap.get(in_vid).ok_or("phi incoming value missing")?;
|
||||
let pred_bb = *bb_map.get(&bid).ok_or("pred bb missing")?;
|
||||
// Coerce incoming to PHI type when needed
|
||||
val = coerce_to_type(codegen, phi, val)?;
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
let tys = phi
|
||||
.as_basic_value()
|
||||
.get_type()
|
||||
.print_to_string()
|
||||
.to_string();
|
||||
eprintln!(
|
||||
"[PHI] incoming add pred_bb={} val={} ty={}",
|
||||
bid.as_u32(),
|
||||
in_vid.as_u32(),
|
||||
tys
|
||||
);
|
||||
}
|
||||
match val {
|
||||
BasicValueEnum::IntValue(iv) => phi.add_incoming(&[(&iv, pred_bb)]),
|
||||
BasicValueEnum::FloatValue(fv) => phi.add_incoming(&[(&fv, pred_bb)]),
|
||||
@ -95,10 +110,24 @@ pub(in super::super) fn emit_branch<'ctx>(
|
||||
if let Some(list) = phis_by_block.get(then_bb) {
|
||||
for (_dst, phi, inputs) in list {
|
||||
if let Some((_, in_vid)) = inputs.iter().find(|(pred, _)| pred == &bid) {
|
||||
let val = *vmap
|
||||
let mut val = *vmap
|
||||
.get(in_vid)
|
||||
.ok_or("phi incoming (then) value missing")?;
|
||||
let pred_bb = *bb_map.get(&bid).ok_or("pred bb missing")?;
|
||||
val = coerce_to_type(codegen, phi, val)?;
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
let tys = phi
|
||||
.as_basic_value()
|
||||
.get_type()
|
||||
.print_to_string()
|
||||
.to_string();
|
||||
eprintln!(
|
||||
"[PHI] incoming add (then) pred_bb={} val={} ty={}",
|
||||
bid.as_u32(),
|
||||
in_vid.as_u32(),
|
||||
tys
|
||||
);
|
||||
}
|
||||
match val {
|
||||
BasicValueEnum::IntValue(iv) => phi.add_incoming(&[(&iv, pred_bb)]),
|
||||
BasicValueEnum::FloatValue(fv) => phi.add_incoming(&[(&fv, pred_bb)]),
|
||||
@ -112,10 +141,24 @@ pub(in super::super) fn emit_branch<'ctx>(
|
||||
if let Some(list) = phis_by_block.get(else_bb) {
|
||||
for (_dst, phi, inputs) in list {
|
||||
if let Some((_, in_vid)) = inputs.iter().find(|(pred, _)| pred == &bid) {
|
||||
let val = *vmap
|
||||
let mut val = *vmap
|
||||
.get(in_vid)
|
||||
.ok_or("phi incoming (else) value missing")?;
|
||||
let pred_bb = *bb_map.get(&bid).ok_or("pred bb missing")?;
|
||||
val = coerce_to_type(codegen, phi, val)?;
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
let tys = phi
|
||||
.as_basic_value()
|
||||
.get_type()
|
||||
.print_to_string()
|
||||
.to_string();
|
||||
eprintln!(
|
||||
"[PHI] incoming add (else) pred_bb={} val={} ty={}",
|
||||
bid.as_u32(),
|
||||
in_vid.as_u32(),
|
||||
tys
|
||||
);
|
||||
}
|
||||
match val {
|
||||
BasicValueEnum::IntValue(iv) => phi.add_incoming(&[(&iv, pred_bb)]),
|
||||
BasicValueEnum::FloatValue(fv) => phi.add_incoming(&[(&fv, pred_bb)]),
|
||||
@ -133,3 +176,60 @@ pub(in super::super) fn emit_branch<'ctx>(
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Coerce a value to the PHI node's type, inserting casts in the current block if necessary.
|
||||
fn coerce_to_type<'ctx>(
|
||||
codegen: &CodegenContext<'ctx>,
|
||||
phi: &PhiValue<'ctx>,
|
||||
val: BasicValueEnum<'ctx>,
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
use inkwell::types::BasicTypeEnum as BT;
|
||||
match (phi.as_basic_value().get_type(), val) {
|
||||
(BT::IntType(it), BasicValueEnum::IntValue(iv)) => {
|
||||
let bw_src = iv.get_type().get_bit_width();
|
||||
let bw_dst = it.get_bit_width();
|
||||
if bw_src == bw_dst {
|
||||
Ok(iv.into())
|
||||
} else if bw_src < bw_dst {
|
||||
Ok(codegen
|
||||
.builder
|
||||
.build_int_z_extend(iv, it, "phi_zext")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into())
|
||||
} else if bw_dst == 1 {
|
||||
// Narrow to i1 via != 0
|
||||
Ok(super::super::types::to_bool(codegen.context, iv.into(), &codegen.builder)?.into())
|
||||
} else {
|
||||
Ok(codegen
|
||||
.builder
|
||||
.build_int_truncate(iv, it, "phi_trunc")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into())
|
||||
}
|
||||
}
|
||||
(BT::IntType(it), BasicValueEnum::PointerValue(pv)) => Ok(codegen
|
||||
.builder
|
||||
.build_ptr_to_int(pv, it, "phi_p2i")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into()),
|
||||
(BT::IntType(it), BasicValueEnum::FloatValue(fv)) => Ok(codegen
|
||||
.builder
|
||||
.build_float_to_signed_int(fv, it, "phi_f2i")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into()),
|
||||
(BT::PointerType(pt), BasicValueEnum::IntValue(iv)) => Ok(codegen
|
||||
.builder
|
||||
.build_int_to_ptr(iv, pt, "phi_i2p")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into()),
|
||||
(BT::PointerType(_), BasicValueEnum::PointerValue(pv)) => Ok(pv.into()),
|
||||
(BT::FloatType(ft), BasicValueEnum::IntValue(iv)) => Ok(codegen
|
||||
.builder
|
||||
.build_signed_int_to_float(iv, ft, "phi_i2f")
|
||||
.map_err(|e| e.to_string())?
|
||||
.into()),
|
||||
(BT::FloatType(_), BasicValueEnum::FloatValue(fv)) => Ok(fv.into()),
|
||||
// Already matching or unsupported combination
|
||||
(_, v) => Ok(v),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user