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:
83
tools/llvmlite_harness.py
Normal file
83
tools/llvmlite_harness.py
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Experimental llvmlite-based LLVM emission harness for Nyash.
|
||||
|
||||
Usage:
|
||||
python3 tools/llvmlite_harness.py [--in MIR.json] --out OUTPUT.o
|
||||
|
||||
Notes:
|
||||
- First cut emits a trivial ny_main that returns 0 to validate toolchain.
|
||||
- Extend to lower MIR14 JSON incrementally.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
from llvmlite import ir, binding
|
||||
except Exception as e: # noqa: BLE001
|
||||
sys.stderr.write(
|
||||
"llvmlite is required. Install with: python3 -m pip install llvmlite\n"
|
||||
)
|
||||
sys.stderr.write(f"Import error: {e}\n")
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
ap = argparse.ArgumentParser(description="Nyash llvmlite harness")
|
||||
ap.add_argument("--in", dest="in_path", help="MIR14 JSON input (optional)")
|
||||
ap.add_argument("--out", dest="out_path", required=True, help="Output object file path")
|
||||
return ap.parse_args()
|
||||
|
||||
|
||||
def load_mir(path: str | None) -> dict | None:
|
||||
if not path:
|
||||
return None
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def build_trivial_module() -> ir.Module:
|
||||
mod = ir.Module(name="nyash_harness")
|
||||
mod.triple = binding.get_default_triple()
|
||||
i64 = ir.IntType(64)
|
||||
i8 = ir.IntType(8)
|
||||
i8p = i8.as_pointer()
|
||||
i8pp = i8p.as_pointer()
|
||||
fn_ty = ir.FunctionType(i64, [i64, i8pp])
|
||||
fn = ir.Function(mod, fn_ty, name="ny_main")
|
||||
entry = fn.append_basic_block(name="entry")
|
||||
b = ir.IRBuilder(entry)
|
||||
b.ret(ir.Constant(i64, 0))
|
||||
return mod
|
||||
|
||||
|
||||
def emit_object(mod: ir.Module, out_path: str) -> None:
|
||||
binding.initialize()
|
||||
binding.initialize_native_target()
|
||||
binding.initialize_native_asmprinter()
|
||||
|
||||
target = binding.Target.from_default_triple()
|
||||
tm = target.create_target_machine()
|
||||
llvm_mod = binding.parse_assembly(str(mod))
|
||||
llvm_mod.verify()
|
||||
obj = tm.emit_object(llvm_mod)
|
||||
with open(out_path, "wb") as f:
|
||||
f.write(obj)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ns = parse_args()
|
||||
_mir = load_mir(ns.in_path)
|
||||
# For now, ignore MIR content and emit a trivial module.
|
||||
mod = build_trivial_module()
|
||||
os.makedirs(os.path.dirname(ns.out_path) or ".", exist_ok=True)
|
||||
emit_object(mod, ns.out_path)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
raise SystemExit(main())
|
||||
|
||||
Reference in New Issue
Block a user