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
1.2 KiB
1.2 KiB
Resolver API (Minimal i64 Prototype)
Goals
- Centralize "ValueId → current-block value" resolution.
- Guarantee dominance by localizing values at the start of the block (before non-PHI).
- De-duplicate per (block, value) to avoid redundant PHIs/casts.
Design
Resolverkeeps small per-function caches keyed by(BasicBlockId, ValueId).resolve_i64(...)returns ani64-typedIntValue, inserting PHI and casts as needed using sealed snapshots.- Internally uses
flow::localize_to_i64(...)for now; later, fold logic directly and addresolve_ptr/resolve_f64.
Usage (planned wiring)
- Create
let mut resolver = instructions::Resolver::new();at function lowering start. - Replace all integer value fetches in lowerers with
resolver.resolve_i64(...). - Keep builder insertion discipline via
BuilderCursor.
Next
- Add
resolve_ptr(...)andresolve_f64(...)with same caching discipline. - Migrate existing
localize_to_i64call sites to the resolver. - Enforce vmap direct access ban in lowerers (Resolver-only for reads).
Acceptance tie-in
- Combined with LoopForm: dispatch-only PHI + resolver-based value access → dominance violations drop to zero (A2.5).