Home Explore Blog CI



rustc

src/backend/lowering-mir.md
5723096ae42313690fe6cb5d29535a991bec08d1105a80ff0000000300000cf3
# Lowering MIR to a Codegen IR

Now that we have a list of symbols to generate from the collector, we need to
generate some sort of codegen IR. In this chapter, we will assume LLVM IR,
since that's what rustc usually uses. The actual monomorphization is performed
as we go, while we do the translation.

Recall that the backend is started by
[`rustc_codegen_ssa::base::codegen_crate`][codegen1]. Eventually, this reaches
[`rustc_codegen_ssa::mir::codegen_mir`][codegen2], which does the lowering from
MIR to LLVM IR.


The code is split into modules which handle particular MIR primitives:

- [`rustc_codegen_ssa::mir::block`][mirblk] will deal with translating
  blocks and their terminators.  The most complicated and also the most
  interesting thing this module does is generating code for function calls,
  including the necessary unwinding handling IR.
- [`rustc_codegen_ssa::mir::statement`][mirst] translates MIR statements.
- [`rustc_codegen_ssa::mir::operand`][mirop] translates MIR operands.
- [`rustc_codegen_ssa::mir::place`][mirpl] translates MIR place references.
- [`rustc_codegen_ssa::mir::rvalue`][mirrv] translates MIR r-values.


Before a function is translated a number of simple and primitive analysis
passes will run to help us generate simpler and more efficient LLVM IR. An
example of such an analysis pass would be figuring out which variables are
SSA-like, so that we can translate them to SSA directly rather than relying on
LLVM's `mem2reg` for those variables. The analysis can be found in
[`rustc_codegen_ssa::mir::analyze`][mirana].


Usually a single MIR basic block will map to a LLVM basic block, with very few
exceptions: intrinsic or function calls and less basic MIR statements like
`assert` can result in multiple basic blocks. This is a perfect lede into the
non-portable LLVM-specific part of the code generation. Intrinsic generation is
fairly easy to understand as it involves very few abstraction levels in between
and can be found in [`rustc_codegen_llvm::intrinsic`][llvmint].


Everything else will use the [builder interface][builder]. This is the code that gets
called in the [`rustc_codegen_ssa::mir::*`][ssamir] modules discussed above.


> TODO: discuss how constants are generated

Chunks
57271fd1 (1st chunk of `src/backend/lowering-mir.md`)
Title: Lowering MIR to LLVM IR in Rustc
Summary
This section describes the process of lowering MIR (Mid-level Intermediate Representation) to LLVM IR within the Rust compiler (rustc). The lowering process starts in `rustc_codegen_ssa::base::codegen_crate` and eventually reaches `rustc_codegen_ssa::mir::codegen_mir`. The code is organized into modules like `block`, `statement`, `operand`, `place`, and `rvalue`, each handling specific MIR primitives. Before translation, analysis passes optimize the MIR, such as identifying SSA-like variables. Intrinsic calls are handled in `rustc_codegen_llvm::intrinsic`, while other operations use a builder interface. A single MIR basic block generally maps to a single LLVM basic block.