llvm/codegen: extract wrapper/object emission into object.rs; dedupe mod.rs. runner/json_v0_bridge: introduce BridgeEnv + VarScope to unify lowering paths (lower_expr/args) and cache env flags; thread env through stmt lowering; minor HashMap type cleanups. Build + PyVM stage-2 smokes passed.

This commit is contained in:
Selfhosting Dev
2025-09-17 02:50:39 +09:00
parent f2ffa30645
commit 4bd49884ca
32 changed files with 3348 additions and 2304 deletions

View File

@ -1,7 +1,7 @@
use std::collections::HashMap;
use inkwell::values::{BasicValueEnum as BVE, IntValue};
use inkwell::values::PointerValue;
use inkwell::values::{BasicValueEnum as BVE, IntValue};
use crate::backend::llvm::context::CodegenContext;
use crate::mir::{BasicBlockId, ValueId};
@ -19,7 +19,11 @@ pub struct Resolver<'ctx> {
impl<'ctx> Resolver<'ctx> {
pub fn new() -> Self {
Self { i64_locals: HashMap::new(), ptr_locals: HashMap::new(), f64_locals: HashMap::new() }
Self {
i64_locals: HashMap::new(),
ptr_locals: HashMap::new(),
f64_locals: HashMap::new(),
}
}
/// Resolve a MIR value as an i64 dominating the current block.
@ -32,13 +36,25 @@ impl<'ctx> Resolver<'ctx> {
vid: ValueId,
bb_map: &std::collections::HashMap<BasicBlockId, inkwell::basic_block::BasicBlock<'ctx>>,
preds: &std::collections::HashMap<BasicBlockId, Vec<BasicBlockId>>,
block_end_values: &std::collections::HashMap<BasicBlockId, std::collections::HashMap<ValueId, BVE<'ctx>>>,
block_end_values: &std::collections::HashMap<
BasicBlockId,
std::collections::HashMap<ValueId, BVE<'ctx>>,
>,
vmap: &std::collections::HashMap<ValueId, BVE<'ctx>>,
) -> Result<IntValue<'ctx>, String> {
if let Some(iv) = self.i64_locals.get(&(cur_bid, vid)).copied() {
return Ok(iv);
}
let iv = localize_to_i64(codegen, cursor, cur_bid, vid, bb_map, preds, block_end_values, vmap)?;
let iv = localize_to_i64(
codegen,
cursor,
cur_bid,
vid,
bb_map,
preds,
block_end_values,
vmap,
)?;
self.i64_locals.insert((cur_bid, vid), iv);
Ok(iv)
}
@ -52,7 +68,10 @@ impl<'ctx> Resolver<'ctx> {
vid: ValueId,
bb_map: &std::collections::HashMap<BasicBlockId, inkwell::basic_block::BasicBlock<'ctx>>,
preds: &std::collections::HashMap<BasicBlockId, Vec<BasicBlockId>>,
block_end_values: &std::collections::HashMap<BasicBlockId, std::collections::HashMap<ValueId, BVE<'ctx>>>,
block_end_values: &std::collections::HashMap<
BasicBlockId,
std::collections::HashMap<ValueId, BVE<'ctx>>,
>,
vmap: &std::collections::HashMap<ValueId, BVE<'ctx>>,
) -> Result<PointerValue<'ctx>, String> {
if let Some(pv) = self.ptr_locals.get(&(cur_bid, vid)).copied() {
@ -61,7 +80,16 @@ impl<'ctx> Resolver<'ctx> {
// Avoid using current vmap directly to keep dominance safe under multiple predecessors.
// Strategy: localize as i64 (dominance-safe PHI), then convert to i8* in current block.
let i8p = codegen.context.ptr_type(inkwell::AddressSpace::from(0));
let iv = localize_to_i64(codegen, cursor, cur_bid, vid, bb_map, preds, block_end_values, vmap)?;
let iv = localize_to_i64(
codegen,
cursor,
cur_bid,
vid,
bb_map,
preds,
block_end_values,
vmap,
)?;
let pv = cursor
.emit_instr(cur_bid, |b| b.build_int_to_ptr(iv, i8p, "loc_i2p_dom"))
.map_err(|e| e.to_string())?;
@ -78,7 +106,10 @@ impl<'ctx> Resolver<'ctx> {
vid: ValueId,
bb_map: &std::collections::HashMap<BasicBlockId, inkwell::basic_block::BasicBlock<'ctx>>,
preds: &std::collections::HashMap<BasicBlockId, Vec<BasicBlockId>>,
block_end_values: &std::collections::HashMap<BasicBlockId, std::collections::HashMap<ValueId, BVE<'ctx>>>,
block_end_values: &std::collections::HashMap<
BasicBlockId,
std::collections::HashMap<ValueId, BVE<'ctx>>,
>,
vmap: &std::collections::HashMap<ValueId, BVE<'ctx>>,
) -> Result<inkwell::values::FloatValue<'ctx>, String> {
if let Some(fv) = self.f64_locals.get(&(cur_bid, vid)).copied() {
@ -89,9 +120,15 @@ impl<'ctx> Resolver<'ctx> {
let cur_llbb = *bb_map.get(&cur_bid).ok_or("cur bb missing")?;
let pred_list = preds.get(&cur_bid).cloned().unwrap_or_default();
let saved_ip = codegen.builder.get_insert_block();
if let Some(first) = cur_llbb.get_first_instruction() { codegen.builder.position_before(&first); }
else { codegen.builder.position_at_end(cur_llbb); }
let phi = codegen.builder.build_phi(f64t, &format!("loc_f64_{}", vid.as_u32())).map_err(|e| e.to_string())?;
if let Some(first) = cur_llbb.get_first_instruction() {
codegen.builder.position_before(&first);
} else {
codegen.builder.position_at_end(cur_llbb);
}
let phi = codegen
.builder
.build_phi(f64t, &format!("loc_f64_{}", vid.as_u32()))
.map_err(|e| e.to_string())?;
if pred_list.is_empty() {
// No predecessor: conservatively zerovmap には依存しない)
let z = f64t.const_zero();
@ -106,10 +143,18 @@ impl<'ctx> Resolver<'ctx> {
let mut coerced = f64t.const_zero();
cursor.with_block(*p, pred_bb, |c| {
let term = unsafe { pred_bb.get_terminator() };
if let Some(t) = term { codegen.builder.position_before(&t); } else { c.position_at_end(pred_bb); }
if let Some(t) = term {
codegen.builder.position_before(&t);
} else {
c.position_at_end(pred_bb);
}
coerced = match base {
BVE::FloatValue(fv) => fv,
BVE::IntValue(iv) => codegen.builder.build_signed_int_to_float(iv, f64t, "loc_i2f_p").map_err(|e| e.to_string()).unwrap(),
BVE::IntValue(iv) => codegen
.builder
.build_signed_int_to_float(iv, f64t, "loc_i2f_p")
.map_err(|e| e.to_string())
.unwrap(),
BVE::PointerValue(_) => f64t.const_zero(),
_ => f64t.const_zero(),
};
@ -117,7 +162,9 @@ impl<'ctx> Resolver<'ctx> {
phi.add_incoming(&[(&coerced, pred_bb)]);
}
}
if let Some(bb) = saved_ip { codegen.builder.position_at_end(bb); }
if let Some(bb) = saved_ip {
codegen.builder.position_at_end(bb);
}
let out = phi.as_basic_value().into_float_value();
self.f64_locals.insert((cur_bid, vid), out);
Ok(out)