How GHC compiles Haskell
A guided tour of the Glasgow Haskell Compiler, assembled from its own source: the
3,270 Note […] comments in which its authors recorded why it is built the way it is.
Pinned to ghc-9.14.1-release.
Follow one module through GHC Start with the parser Browse the Notes →
The pipeline
Each phase is sized by how much design reasoning it carries. Phases with a chapter are live; the rest are mapped but not yet written up.
The front end
Text becomes a typed, name-resolved syntax tree. Everything here is about establishing meaning: what the symbols refer to, and whether the program is well typed.
- Lexer characters → tokens Turns the source text into a token stream, tracking layout so that indentation becomes explicit braces and semicolons. 10 notes Read →
- Parser tokens → HsSyn A Happy grammar that builds the surface syntax tree, preserving enough source detail to reprint the program exactly. 49 notes Read →
- Renamer RdrName → Name Resolves every occurrence to the thing it names, resolves fixities, and reports what is unused or ambiguous. 129 notes Read →
- Type checker Name → Id Generates constraints from the syntax tree and solves them. By far the largest phase, and the one that carries the most design reasoning. 836 notes Read →
- Desugarer HsSyn → Core Collapses the whole of Haskell into Core: a tiny explicitly-typed lambda calculus with just nine constructors. 115 notes Read →
The middle end
Core in, better Core out. This is where GHC earns its reputation: a long sequence of type-preserving transformations over a deliberately small language.
- Core the intermediate language System F-ish, explicitly typed, and small enough to fit on a page, which is exactly what makes the optimiser tractable. 145 notes Read →
- Simplifier Core → Core Inlining, beta reduction, case-of-case, and rewrite rules, run to a fixed point over several passes. 493 notes Read →
The back end
Types are erased, evaluation order is made explicit, and the program descends towards machine code.
- STG Core → STG Makes allocation and evaluation explicit. Every closure and every thunk becomes visible in the syntax. 89 notes Read →
- Cmm STG → Cmm A C-like portable assembly with explicit stack and heap operations: the last target-independent form. 123 notes Read →
- Code generation Cmm → machine code The native code generator, the LLVM backend, or the bytecode generator for GHCi. 74 notes Read →
The runtime
Compiled code does not run alone. The RTS provides the storage manager, the scheduler, and the machinery that makes laziness and concurrency work.