Compiler Mid/Back: IR, SSA, Machine Code, Link
Compiler Mid/Back: IR, SSA, Machine Code, Link
Overview
After typecheck, the compiler optimizes in IR, lowers to SSA, emits machine code objects, then the linker produces a binary. This is where inlining, escape analysis, and PGO bite.
Diagram: mid and back end
typed frontend
│
v
IR (inline, escape, …)
│
v
SSA opts + arch lower
│
v
.o objects ──► linker ──► binary
IR responsibilities
| Pass family | Effect |
|---|---|
| Inlining | Expand small callees; enable more opts |
| Escape analysis | Stack vs heap |
| Devirtualization | Concrete calls when type known |
| Walk / order | Prepare for SSA |
Flags: go build -gcflags='-m -m' shows escape/inline decisions.
SSA
- Every value assigned once → easy dataflow
- Dozens of rewrite passes (nilcheck elim, bounds prove, …)
- Then lower to
AMD64…/ARM64…ops
GOSSAFUNC=main go build . # classic SSA HTML dump when supported
go build -gcflags='-S' . 2>&1 | headMachine code + object files
- Encode instructions, relocations, PC↔︎line metadata
- One package → one (or more) object; still not runnable alone
Linker
resolve symbols across packages
→ apply relocations
→ layout sections
→ emit ELF/Mach-O/PE + buildid
go build -ldflags='-s -w -X main.version=dev' -trimpath -o app .See also 210 link/race, 248 bootstrap.
Experiment
go build -gcflags='-m' . 2>&1 | head -40
go tool nm ./app | rg 'main\\.|runtime\\.main' | headWhat to notice: Even tiny mains reference large runtime.* symbol sets after link.
Try next: Build twice with/without -pgo=auto after a CPU profile; bench a hot path.