cp-11 · LLVM Codegen (the real C++ API)
Goal: emit a verified
llvm::Modulestraight from our TAC IR usingIRBuilder, then run the new-pass-manager O2 pipeline (mem2reg, instcombine, GVN, SimplifyCFG, …) over it. Execute withlli, or pipe throughllcto produce native object code.
cp-10 wrote LLVM IR as text. cp-11 builds the same IR through the
official C++ API, links against libLLVM*, and lets LLVM run its
production-grade optimisation pipeline on the result.
What changed since cp-10
| Concern | cp-10 | cp-11 |
|---|---|---|
| IR producer | hand-written text emitter | llvm::IRBuilder<> |
| Verifier | none — trusted lli to complain | llvm::verifyModule after build |
| Optimiser | none | PassBuilder::buildPerModuleDefaultPipeline(O2) |
| Globals | string-templated @x = global i64 0 | new llvm::GlobalVariable(...) |
| Format string | hand-emitted [6 x i8] literal | IRBuilder::CreateGlobalString |
Build & run
cmake -S src/cpp -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build
./build/tests/test_llvm_codegen # → 25/25 checks passed
# REPL-ish: pipe MiniLang in, get IR out
echo 'fn fib(n){ if(n<2){return n;} return fib(n-1)+fib(n-2);} print fib(20);' \
| ./build/mlcc -O \
| /opt/homebrew/opt/llvm/bin/lli
# 6765
-O runs both our cp-09 TAC passes and LLVM's O2 pipeline.
Layout
src/cpp/
├── CMakeLists.txt # find_package(LLVM); link core/passes/analysis/...
├── src/
│ ├── llvm_codegen.hpp # CodegenResult + build()/optimise()
│ ├── llvm_codegen.cpp # IRBuilder emitter + new-PM pipeline
│ └── main.cpp # `mlcc` CLI
└── tests/test_llvm_codegen.cpp