Skip to main content

gruel_codegen_llvm/
lib.rs

1//! LLVM-based code generation for the Gruel compiler.
2//!
3//! This crate converts CFG (Control Flow Graph) to native object code via LLVM IR,
4//! using the `inkwell` crate as safe Rust bindings to LLVM's C API.
5//!
6//! ## Build requirements
7//!
8//! LLVM 22 must be installed and `LLVM_SYS_221_PREFIX` or a system `llvm-config`
9//! must be available.
10//!
11//! - On macOS: `brew install llvm`
12//! - On Linux: `apt install llvm-22-dev`
13//!
14//! ## Pipeline
15//!
16//! ```text
17//! CFG → LLVM IR (via inkwell) → [opt passes] → object file bytes
18//! ```
19
20mod codegen;
21mod opt_level;
22mod types;
23
24pub use opt_level::OptLevel;
25
26use gruel_air::TypeInternPool;
27use gruel_cfg::Cfg;
28use gruel_target::Target;
29use gruel_util::CompileResult;
30use lasso::ThreadedRodeo;
31
32/// Inputs to LLVM codegen, bundled to keep function signatures readable.
33///
34/// All borrows are produced upstream by sema/CFG construction; codegen reads
35/// from them but does not own or mutate them.
36pub struct CodegenInputs<'a> {
37    pub functions: &'a [&'a Cfg],
38    pub type_pool: &'a TypeInternPool,
39    pub strings: &'a [String],
40    pub bytes: &'a [Vec<u8>],
41    pub interner: &'a ThreadedRodeo,
42    pub interface_defs: &'a [gruel_air::InterfaceDef],
43    pub interface_vtables: &'a gruel_air::InterfaceVtables,
44    /// The compilation target — controls the LLVM target triple and
45    /// platform-conditional codegen (e.g. inline-asm syscall layout).
46    pub target: &'a Target,
47}
48
49/// Generate a native object file from a collection of function CFGs using LLVM.
50///
51/// All functions are compiled into a single LLVM module, which is then lowered
52/// to an object file via LLVM's backend. The returned bytes can be written to a
53/// `.o` file and passed to a system linker.
54///
55/// At `-O1` and above the LLVM mid-end pipeline (`default<OX>`) is run before
56/// emission, enabling InstCombine, GVN, SCCP, ADCE, SimplifyCFG, and more.
57///
58/// # Errors
59///
60/// Returns an error if an LLVM compilation error occurs.
61pub fn generate(inputs: &CodegenInputs<'_>, opt_level: OptLevel) -> CompileResult<Vec<u8>> {
62    codegen::generate(inputs, opt_level)
63}
64
65/// Generate LLVM textual IR from a collection of function CFGs.
66///
67/// Returns the LLVM IR in human-readable `.ll` format. Used by `--emit asm`
68/// to produce inspectable IR in place of native assembly. At `-O1+` the
69/// returned IR is the post-optimization form.
70pub fn generate_ir(inputs: &CodegenInputs<'_>, opt_level: OptLevel) -> CompileResult<String> {
71    codegen::generate_ir(inputs, opt_level)
72}
73
74/// Generate pre-optimization LLVM bitcode from a collection of function CFGs.
75///
76/// Returns the LLVM bitcode bytes (the binary equivalent of `.ll` text) BEFORE
77/// the optimizer pipeline runs. Used by ADR-0074's bitcode cache: on miss,
78/// generate + cache; on hit, skip this step and pass the cached bitcode to
79/// [`compile_bitcode_to_object`].
80///
81/// The output is a `.bc` blob — same format `clang -emit-llvm -c` produces.
82pub fn generate_bitcode(inputs: &CodegenInputs<'_>) -> CompileResult<Vec<u8>> {
83    codegen::generate_bitcode(inputs)
84}
85
86/// Compile cached or freshly-emitted LLVM bitcode into a native object file.
87///
88/// Runs the LLVM mid-end optimizer pipeline at the given level (no-op at
89/// `-O0`) and emits an object via the host machine's back-end. Used by
90/// ADR-0074's bitcode cache to consume the output of either
91/// [`generate_bitcode`] (cache miss) or a previously cached `.bc` blob
92/// (cache hit).
93pub fn compile_bitcode_to_object(
94    bitcode: &[u8],
95    opt_level: OptLevel,
96    target: &Target,
97) -> CompileResult<Vec<u8>> {
98    codegen::compile_bitcode_to_object(bitcode, opt_level, target)
99}