I've been reading the commits from @Richard Feldman roll in with the new MIR and LIR stages... and thought I'd put together an updated diagram for the Roc pipeline. I like having high level diagrams to help me understand how it works, and why etc.
I haven't included much here, it's just the high level flow -- but maybe it helps anyone interested in following along.
Roc Compiler Pipeline-2026-02-16-225823.png
# Roc Compiler Pipeline
The Coordinator drives the compilation pipeline @src/compile/coordinator.zig
## Input
0. Roc Source Code
## Intermediate Representations
1. Abstract Syntax Tree (AST) @src/parse/AST.zig
2. Canonical Intermediate Representation (CIR) @src/canonicalize/CIR.zig
3. Monomorphic Intermediate Representation (MIR) @src/mir/MIR.zig
4. Layout Intermediate Representation (LIR) @src/lir/LIR.zig
## Output
5.1. LLVM bitcode
5.2. x86-64 machine code
5.3. aarch64 machine code
5.4. WASM bytecode
## Transformations
6.1. Syntax Analysis (Source -> AST)
6.1.1. Tokenize @src/parse/tokenize.zig
6.1.2. Parse @src/parse/Parser.zig
6.2. Semantic Analysis (AST -> CIR) @src/canonicalize/Can.zig
6.3. Type Checking (CIR -> CIR) @src/check/Check.zig
6.4. Monomorphization (CIR -> MIR) @src/mir/Lower.zig
6.5. Lowering (MIR -> LIR) @src/lir/MirToLir.zig
6.6. Code Generation (LIR -> Output) @src/backend/mod.zig
personally I'd draw Type Checking as producing a separate box to the side of CIR, something like "Types" maybe, and then similarly there would be a box called Monotypes next to MIR.
then an arrow from Types to Monotypes next to the arrow from CIR to MIR, and then finally an arrow from Monotypes to LIR - because LIR is created using a combination of MIR and Monotypes
this is also missing the lambda set steps, which I personally think would be good to include!
Excellent ... I'll look into it
It might be easier to use the convention where boxes are actions/functions and arrows are data. Then functions can naturally accept have multiple inputs/outputs.
Last updated: Feb 20 2026 at 12:27 UTC