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:
36
docs/LLVM_HARNESS.md
Normal file
36
docs/LLVM_HARNESS.md
Normal file
@ -0,0 +1,36 @@
|
||||
# llvmlite Harness (Experimental)
|
||||
|
||||
Purpose
|
||||
- Provide a fast, scriptable LLVM emission path using Python + llvmlite for validation and prototyping.
|
||||
- Run in parallel with the Rust/inkwell path; keep outputs functionally equivalent for targeted smokes.
|
||||
|
||||
Switch
|
||||
- Set `NYASH_LLVM_USE_HARNESS=1` to prefer the harness (future: wired in LLVM backend entry).
|
||||
|
||||
Protocol (tentative)
|
||||
- Input: MIR14 JSON file path (subset sufficient for dep_tree_min_string initially).
|
||||
- Output: `.o` object file written to `NYASH_AOT_OBJECT_OUT` or `--out` path.
|
||||
- Entry function: `ny_main(i64 argc, i8** argv) -> i64` (returns app exit code/box-handle per ABI).
|
||||
|
||||
Quick Start
|
||||
- Install deps: `python3 -m pip install llvmlite`
|
||||
- Generate a dummy object to validate toolchain:
|
||||
- `python3 tools/llvmlite_harness.py --out /tmp/dummy.o`
|
||||
- Link with NyRT as usual to produce an executable.
|
||||
|
||||
Intended Wiring (Rust side)
|
||||
- LLVM backend checks `NYASH_LLVM_USE_HARNESS=1` and, if set, exports MIR14 of the target module to a temp JSON, then invokes:
|
||||
- `python3 tools/llvmlite_harness.py --in <mir.json> --out <obj.o>`
|
||||
- On success, the normal link step continues using `<obj.o>`.
|
||||
|
||||
Scope (Phase 15)
|
||||
- Minimal ops: i64 arithmetic, comparisons, branches, PHI(Sealed), basic string ops through NyRT shims.
|
||||
- Target case: `apps/selfhost/tools/dep_tree_min_string.nyash` builds and runs.
|
||||
|
||||
Acceptance
|
||||
- A5: Harness ON vs OFF produce functionally equivalent output for the target smoke.
|
||||
|
||||
Notes
|
||||
- The first version may ignore MIR details and emit a fixed `ny_main` body for smoke scaffolding; then iterate to lower MIR ops.
|
||||
- Keep the harness self-contained; no external state besides inputs and env.
|
||||
|
||||
37
docs/LLVM_LAYER_OVERVIEW.md
Normal file
37
docs/LLVM_LAYER_OVERVIEW.md
Normal file
@ -0,0 +1,37 @@
|
||||
# LLVM Layer Overview (Phase 15)
|
||||
|
||||
Scope
|
||||
- Practical guide to LLVM lowering architecture and invariants used in Phase 15.
|
||||
- Complements LOWERING_LLVM.md (rules), RESOLVER_API.md (value resolution), and LLVM_HARNESS.md (harness).
|
||||
|
||||
Module Layout
|
||||
- `src/backend/llvm/compiler/codegen/`
|
||||
- `instructions/` split by concern: `flow.rs`, `blocks.rs`, `arith.rs`, `arith_ops.rs`, `mem.rs`,
|
||||
`strings.rs`, `arrays.rs`, `maps.rs`, `boxcall/`, `externcall/`, `call.rs`, `loopform.rs`, `resolver.rs`.
|
||||
- `builder_cursor.rs`: central insertion/terminator guard.
|
||||
|
||||
Core Invariants
|
||||
- Resolver-only reads: lowerers fetch MIR values through `Resolver` (no direct `vmap` access for cross-BB values).
|
||||
- Localize at block start: PHIs created at the beginning of the current BB (before non-PHI) to guarantee dominance.
|
||||
- Cast placement: perform ptr↔int and width casts outside PHIs, at BB start or just-before-pred-terminator via `with_block`.
|
||||
- Sealed SSA: successor PHIs wired by predecessor snapshots and `seal_block`; branch/jump do not push incoming directly.
|
||||
- Cursor discipline: only insert via `BuilderCursor`; post-terminator insertions are forbidden.
|
||||
|
||||
LoopForm (gated)
|
||||
- Shape: `preheader → header → body → dispatch(phi) → {latch|exit} → header` with PHIs centralized in `dispatch`.
|
||||
- State: model loop-carried values via a `LoopState` aggregate (tag + payloads).
|
||||
- Goals: move all PHIs to dispatch, ensure header uses are dominated by preheader/dispatch values.
|
||||
|
||||
Types and Bridges
|
||||
- Box handle is `i64` across NyRT boundary; strings prefer `i8*` fast paths.
|
||||
- Convert rules: `ensure_i64/ensure_i1/ensure_ptr` style helpers (planned extraction) to centralize casting.
|
||||
|
||||
Harness (optional)
|
||||
- llvmlite harness exists for fast prototyping and structural checks.
|
||||
- Gate: `NYASH_LLVM_USE_HARNESS=1` (planned wiring); target parity tested by Acceptance A5.
|
||||
|
||||
References
|
||||
- LOWERING_LLVM.md — lowering rules and runtime calls
|
||||
- RESOLVER_API.md — Resolver design and usage
|
||||
- LLVM_HARNESS.md — llvmlite harness interface and usage
|
||||
|
||||
25
docs/RESOLVER_API.md
Normal file
25
docs/RESOLVER_API.md
Normal file
@ -0,0 +1,25 @@
|
||||
# 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
|
||||
- `Resolver` keeps small per-function caches keyed by `(BasicBlockId, ValueId)`.
|
||||
- `resolve_i64(...)` returns an `i64`-typed `IntValue`, inserting PHI and casts as needed using sealed snapshots.
|
||||
- Internally uses `flow::localize_to_i64(...)` for now; later, fold logic directly and add `resolve_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(...)` and `resolve_f64(...)` with same caching discipline.
|
||||
- Migrate existing `localize_to_i64` call 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).
|
||||
|
||||
Reference in New Issue
Block a user