Codegen Architecture
The compiler’s codegen infrastructure is split into backend-agnostic and backend-specific components:The
rustc_codegen_ssa crate provides backend-agnostic code generation infrastructure, defining traits and common functionality that all codegen backends must implement.Backend-Agnostic Layer (rustc_codegen_ssa)
This crate defines the interface that all backends must implement:
Available Backends
LLVM (rustc_codegen_llvm)
The default and most mature backend. Produces highly optimized code for many platforms.
Cranelift (rustc_codegen_cranelift)
A fast code generator focused on compilation speed rather than runtime performance. Useful for debug builds.
LLVM Backend
Therustc_codegen_llvm crate implements code generation using LLVM:
LLVM IR Generation
MIR is translated to LLVM IR through several steps:Monomorphization
Monomorphization
Generic functions are instantiated with concrete types. The
rustc_monomorphize crate handles this, creating separate versions of generic functions for each concrete type combination used.MIR to LLVM IR Translation
MIR to LLVM IR Translation
Each MIR basic block is translated to LLVM basic blocks, and MIR statements/terminators become LLVM instructions.
Type Lowering
Type Lowering
Rust types are mapped to LLVM types. This includes handling representation optimizations like niche filling for enums.
ABI Handling
ABI Handling
The
abi module handles calling conventions and argument passing according to platform ABIs.Codegen Units
Code is divided into compilation units (CGUs) for parallel compilation:Codegen units are compiled in parallel to speed up compilation. The number of CGUs can be controlled with the
-C codegen-units=N flag.Translation Process
Here’s how MIR translates to LLVM IR:Basic Blocks
Function Calls
Control Flow
Type Translation
Rust types are mapped to LLVM types:Integers
i32 → i32, u64 → i64, etc.Pointers
References and raw pointers → LLVM pointers
Structs
Structs → LLVM struct types with appropriate layout
Enums
Enums → Tagged unions or optimized representations
Enum Optimizations
The compiler applies sophisticated optimizations to enums:Optimization Levels
LLVM optimization is controlled by the-C opt-level flag:
Link-Time Optimization (LTO)
LTO performs whole-program optimization:Thin LTO provides most of the benefits of LTO with significantly reduced compilation time and memory usage compared to fat LTO.
LTO Modes
No LTO (default)
No LTO (default)
Each codegen unit is optimized independently. Fast compilation but less optimization.
Thin LTO
Thin LTO
LLVM performs lightweight cross-module optimization. Good balance of compile time and runtime performance.
Fat LTO
Fat LTO
Full program optimization across all codegen units. Slowest compilation but maximum optimization.
Debugging Information
The compiler can emit debugging information for debuggers:Target Selection
The compiler supports many target platforms:Target specifications are defined in
rustc_target and include:- Architecture (x86_64, aarch64, wasm32, etc.)
- Operating system (linux, windows, macos, none)
- ABI and calling conventions
- Supported features and optimizations
Inline Assembly
The compiler supports inline assembly via theasm! macro:
asm module in rustc_codegen_llvm handles translating inline assembly to LLVM inline asm.
Intrinsics
Compiler intrinsics provide access to low-level operations:intrinsic module maps Rust intrinsics to LLVM intrinsics or custom code.
Codegen Workflow
The complete codegen workflow:Performance Considerations
Codegen Units
More CGUs = faster compilation but less optimization. Fewer CGUs = better optimization but slower compilation.
LTO
Enable for release builds when maximum performance is needed, despite longer compile times.
Target CPU
Use
-C target-cpu=native to optimize for your specific CPU.Profile-Guided Optimization
Use PGO to optimize based on actual runtime behavior.
Related Compiler Flags
Next Steps
MIR
Learn about the MIR that feeds code generation
Incremental Compilation
Understand how the compiler optimizes rebuilds