#!/usr/bin/env python3 """ Nyash llvmlite harness (scaffold) Usage: - python3 tools/llvmlite_harness.py --out out.o # dummy ny_main -> object - python3 tools/llvmlite_harness.py --in mir.json --out out.o # MIR(JSON) -> object (partial support) Notes: - For initial scaffolding, when --in is omitted, a trivial ny_main that returns 0 is emitted. - When --in is provided, this script delegates to src/llvm_py/llvm_builder.py. """ import argparse import json import os import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] PY_BUILDER = ROOT / "src" / "llvm_py" / "llvm_builder.py" def run_dummy(out_path: str) -> None: # Minimal llvmlite program: ny_main() -> i32 0 import llvmlite.ir as ir import llvmlite.binding as llvm llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() mod = ir.Module(name="nyash_module") i32 = ir.IntType(32) ny_main_ty = ir.FunctionType(i32, []) ny_main = ir.Function(mod, ny_main_ty, name="ny_main") entry = ny_main.append_basic_block("entry") b = ir.IRBuilder(entry) b.ret(ir.Constant(i32, 0)) # Emit object via target machine m = llvm.parse_assembly(str(mod)) m.verify() target = llvm.Target.from_default_triple() tm = target.create_target_machine() obj = tm.emit_object(m) Path(out_path).parent.mkdir(parents=True, exist_ok=True) with open(out_path, "wb") as f: f.write(obj) def run_from_json(in_path: str, out_path: str) -> None: # Delegate to python builder to keep code unified import runpy # Enable safe defaults for prepasses unless explicitly disabled by env os.environ.setdefault('NYASH_LLVM_PREPASS_LOOP', os.environ.get('NYASH_LLVM_PREPASS_LOOP', '0')) os.environ.setdefault('NYASH_LLVM_PREPASS_IFMERGE', os.environ.get('NYASH_LLVM_PREPASS_IFMERGE', '1')) # Ensure src/llvm_py is on sys.path for relative imports builder_dir = str(PY_BUILDER.parent) if builder_dir not in sys.path: sys.path.insert(0, builder_dir) # Simulate "python llvm_builder.py -o " sys.argv = [str(PY_BUILDER), str(in_path), "-o", str(out_path)] runpy.run_path(str(PY_BUILDER), run_name="__main__") def main(): ap = argparse.ArgumentParser() ap.add_argument("--in", dest="infile", help="MIR JSON input", default=None) ap.add_argument("--out", dest="outfile", help="output object (.o)", required=True) args = ap.parse_args() if args.infile is None: # Dummy path run_dummy(args.outfile) print(f"[harness] dummy object written: {args.outfile}") else: run_from_json(args.infile, args.outfile) print(f"[harness] object written: {args.outfile}") if __name__ == "__main__": try: main() except Exception as e: import traceback print(f"[harness] error: {e}", file=sys.stderr) if os.environ.get('NYASH_CLI_VERBOSE') == '1': traceback.print_exc() sys.exit(1)