feat(llvm): Major refactor - BuilderCursor全域化 & Resolver API導入

Added:
- Resolver API (resolve_i64) for unified value resolution with per-block cache
- llvmlite harness (Python) for rapid PHI/SSA verification
- Comprehensive LLVM documentation suite:
  - LLVM_LAYER_OVERVIEW.md: Overall architecture and invariants
  - RESOLVER_API.md: Value resolution strategy
  - LLVM_HARNESS.md: Python verification harness

Updated:
- BuilderCursor applied to ALL lowering paths (externcall/newbox/arrays/maps/call)
- localize_to_i64 for dominance safety in strings/compare/flow
- NYASH_LLVM_DUMP_ON_FAIL=1 for debug IR output

Key insight: LoopForm didn't cause problems, it just exposed existing design flaws:
- Scattered value resolution (now unified via Resolver)
- Inconsistent type conversion placement
- Ambiguous PHI wiring responsibilities

Next: Wire Resolver throughout, achieve sealed=ON green for dep_tree_min_string
This commit is contained in:
Selfhosting Dev
2025-09-12 20:06:48 +09:00
parent 45f13cf7a8
commit c04b0c059d
16 changed files with 377 additions and 168 deletions

View File

@ -0,0 +1,43 @@
use std::collections::HashMap;
use inkwell::values::{BasicValueEnum as BVE, IntValue};
use crate::backend::llvm::context::CodegenContext;
use crate::mir::{BasicBlockId, ValueId};
use super::builder_cursor::BuilderCursor;
use super::flow::localize_to_i64;
/// Minimal per-function resolver caches. Caches localized i64 values per (block,value) to avoid
/// redundant PHIs and casts when multiple users in the same block request the same MIR value.
pub struct Resolver<'ctx> {
i64_locals: HashMap<(BasicBlockId, ValueId), IntValue<'ctx>>,
}
impl<'ctx> Resolver<'ctx> {
pub fn new() -> Self {
Self { i64_locals: HashMap::new() }
}
/// Resolve a MIR value as an i64 dominating the current block.
/// Strategy: if present in cache, return it; otherwise localize via sealed snapshots and cache.
pub fn resolve_i64<'b>(
&mut self,
codegen: &CodegenContext<'ctx>,
cursor: &mut BuilderCursor<'ctx, 'b>,
cur_bid: BasicBlockId,
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>>>,
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)?;
self.i64_locals.insert((cur_bid, vid), iv);
Ok(iv)
}
}