# Phase 87: LLVM Exe Line SSOT (2025-12-13) ## Goal Establish single source of truth for `.hako → .o → executable → execution` pipeline. **SSOT Tool**: `tools/build_llvm.sh` ## Prerequisites 1. **llvm-config-18** available: ```bash llvm-config-18 --version # Expected: 18.x.x ``` 2. **hakorune built with LLVM features**: ```bash cargo build --release --features llvm ./target/release/hakorune --version # Check --backend llvm available in --help ``` 3. **Python llvmlite** (for LLVM harness): ```bash python3 -c "import llvmlite; print(llvmlite.__version__)" # Expected: 0.40.0 or newer ``` ## Standard Procedure **Build and execute** a .hako program to native executable: ```bash # Step 1: Build .hako → executable tools/build_llvm.sh apps/tests/your_program.hako -o tmp/your_program # Step 2: Execute ./tmp/your_program echo $? # Check exit code ``` **What it does**: 1. Compiles `.hako` → MIR (hakorune compiler) 2. MIR → LLVM IR (llvmlite harness, `src/llvm_py/`) 3. LLVM IR → object file `.o` (llvm tools) 4. Links object → executable (clang) ## Example: Minimal Program **File**: `apps/tests/phase87_llvm_exe_min.hako` ```nyash static box Main { main() { return 42 } } ``` **Build**: ```bash tools/build_llvm.sh apps/tests/phase87_llvm_exe_min.hako -o tmp/phase87_test ``` **Execute**: ```bash ./tmp/phase87_test echo $? # Output: 42 ``` ## Detailed Pipeline Explanation ### Step 1: Hako → MIR JSON **Command** (internal to build_llvm.sh): ```bash ./target/release/hakorune --emit-mir-json tmp/program.json program.hako ``` **Output**: MIR JSON representation of the program ### Step 2: MIR JSON → LLVM IR **Command** (internal to build_llvm.sh): ```bash python3 src/llvm_py/llvm_builder.py tmp/program.json -o tmp/program.ll ``` **Output**: LLVM IR text file (.ll) ### Step 3: LLVM IR → Object File **Command** (internal to build_llvm.sh): ```bash llc-18 tmp/program.ll -o tmp/program.o -filetype=obj ``` **Output**: Object file (.o) ### Step 4: Object File → Executable **Command** (internal to build_llvm.sh): ```bash clang-18 tmp/program.o -o tmp/program ``` **Output**: Native executable ## Troubleshooting ### Issue: llvm-config-18 not found **Symptom**: `build_llvm.sh` fails with "llvm-config-18: command not found" **Solution**: ```bash # Ubuntu/Debian: sudo apt-get install llvm-18-dev llvm-18-tools # macOS (Homebrew): brew install llvm@18 export PATH="/opt/homebrew/opt/llvm@18/bin:$PATH" # WSL (Ubuntu): wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 18 ``` ### Issue: Python llvmlite not found **Symptom**: `ModuleNotFoundError: No module named 'llvmlite'` **Solution**: ```bash pip3 install llvmlite # If system-wide install fails, use virtual environment: python3 -m venv venv source venv/bin/activate pip install llvmlite ``` ### Issue: Linking fails **Symptom**: `ld: symbol(s) not found for architecture` **Check**: - Ensure clang-18 is installed - Verify LLVM 18 libraries available: ```bash llvm-config-18 --libdir ls $(llvm-config-18 --libdir) ``` ### Issue: MIR compilation error **Symptom**: hakorune fails to compile .hako to MIR **Debug**: ```bash # Test MIR generation manually: ./target/release/hakorune --emit-mir-json test.json test.hako # Check error messages: cat test.json # Should be valid JSON ``` ### Issue: LLVM IR generation error **Symptom**: llvm_builder.py fails **Debug**: ```bash # Run Python builder manually: python3 src/llvm_py/llvm_builder.py test.json -o test.ll # Check LLVM IR validity: llvm-as-18 test.ll -o /dev/null # Should complete without errors ``` ## What NOT to Do ❌ **DO NOT** create custom link procedures: - Scattered linking logic across multiple scripts - Manual `clang` invocations outside `build_llvm.sh` - Duplicate .o → exe pipelines ❌ **DO NOT** bypass build_llvm.sh: - Direct llvm_builder.py invocations for production - Custom shell scripts for one-off builds - Hardcoded paths in makefiles ✅ **DO** use `tools/build_llvm.sh` for all LLVM exe generation ## Integration Test **Location**: `tools/smokes/v2/profiles/integration/apps/phase87_llvm_exe_min.sh` **What it tests**: - Full pipeline: .hako → exe → execution - Exit code verification (42) - SKIP if LLVM unavailable (graceful degradation) **Run manually**: ```bash tools/smokes/v2/run.sh --profile integration --filter 'phase87_llvm_exe_min\.sh' ``` **Expected outcomes**: - **PASS**: If llvm-config-18 available → exit code 42 verified - **SKIP**: If llvm-config-18 not found → graceful skip message ## Why Exit Code 42? - **Stdout-independent**: Works even if stdout is redirected/buffered - **Deterministic**: No parsing required, simple integer comparison - **Traditional**: Unix convention for testable exit codes - **Minimal**: No dependencies on print/console boxes ## Advanced Usage ### Custom output location ```bash # Default: output to tmp/ tools/build_llvm.sh program.hako -o custom/path/binary # Ensure directory exists first: mkdir -p custom/path ``` ### Debugging build steps **Set verbose mode** (if supported by build_llvm.sh): ```bash VERBOSE=1 tools/build_llvm.sh program.hako -o output ``` **Check intermediate files**: ```bash # MIR JSON: ls -lh tmp/*.json # LLVM IR: ls -lh tmp/*.ll # Object file: ls -lh tmp/*.o ``` ### Comparing with VM backend **VM execution** (interpreted): ```bash ./target/release/hakorune --backend vm program.hako echo $? ``` **LLVM execution** (native): ```bash tools/build_llvm.sh program.hako -o tmp/program ./tmp/program echo $? ``` **Should produce identical exit codes** for correct programs. ## Performance Characteristics **Build time**: ~1-3 seconds for minimal programs - .hako → MIR: ~100ms - MIR → LLVM IR: ~500ms - LLVM IR → .o: ~1s - Linking: ~200ms **Execution time**: Native speed (no VM overhead) - Typical speedup: 10-100x vs VM backend - No JIT warmup required - Full LLVM optimizations applied ## Related Documentation - LLVM Python harness: `src/llvm_py/README.md` - MIR spec: `docs/reference/mir/INSTRUCTION_SET.md` - Integration smokes: `tools/smokes/v2/README.md` - build_llvm.sh implementation: `tools/build_llvm.sh` (read source for details) ## SSOT Principle **Single Source of Truth**: - ONE script: `tools/build_llvm.sh` - ONE pipeline: .hako → MIR → LLVM IR → .o → exe - ONE integration test: `phase87_llvm_exe_min.sh` **Benefits**: - Maintainability: Update one script, not scattered logic - Consistency: All LLVM builds use same pipeline - Testability: Single smoke test covers full pipeline - Documentation: One canonical reference **Anti-patterns to avoid**: - Multiple competing build scripts - Copy-pasted linking commands - Ad-hoc shell scripts for "quick builds" ## Status - ✅ SSOT established: `tools/build_llvm.sh` - ✅ Integration smoke added: `phase87_llvm_exe_min.sh` - ✅ Documentation complete - ✅ Prerequisites verified: llvm-config-18, llvmlite, LLVM features - 🎯 Production ready: Use for all LLVM native compilations ## Future Enhancements (Out of Scope for Phase 87) - **Optimization levels**: -O0, -O1, -O2, -O3 flags - **Debug symbols**: -g flag support - **Static linking**: --static flag - **Cross-compilation**: --target flag - **LTO**: Link-time optimization support **Current scope**: Baseline SSOT pipeline establishment only.