Lesson 6 of 7
Code Generation, Linking & JITs
This lesson covers the final stages: turning IR into real instructions, linking separate files into one executable, and how JIT do all of this while a program runs.
Codegen makes two hard choices. Instruction selection: which of the CPU's instructions implement each IR operation (x86 can often fold load-add-store into one instruction; ARM can't). Register allocation: the IR pretends registers are infinite, hardware has ~16 — graph coloring assigns the busiest values to registers and 'spills' the rest to . Register pressure is a real performance force: too many live means spills, means memory traffic.
# Separate compilation + linking — how big projects build:
gcc -c utils.c # -> utils.o (machine code, but
gcc -c main.c # -> main.o unresolved references)
gcc main.o utils.o -o app # linker joins them
# main.o contains 'call helper' with a BLANK address and
# a note: "patch this when you find 'helper'". The linker
# resolves every such note across all .o files + libraries.
# 'undefined reference to helper' = linker found no
# definition anywhere (forgot a file or a library flag).
# 'duplicate symbol' = found two.
nm utils.o # see a file's symbols: T=defined, U=neededStatic linking copies code into your (bigger, -contained — Go's default). Dynamic linking loads shared libraries (.so/.dll) at startup, so all programs share one libc in memory and library fixes arrive without recompiling — at the cost of 'DLL hell' version mismatches. Every deployment headache about glibc versions traces here.
JIT compilation — V8 running your JavaScript:
1. Parse to bytecode, start interpreting immediately
2. Profile while running: which functions are hot?
what types actually flow through them?
3. Hot function -> compile to machine code SPECIALIZED
to the observed types ("x is always a small int")
4. Guard checks protect the assumption; if a string
shows up one day -> DEOPTIMIZE: throw away the
fast code, fall back, maybe recompile
Why JS engines love consistent types — and why that
advice exists: monomorphic code stays compiled;
type-shifting code bounces between tiers.
The full pipeline, running in milliseconds,
while your page loads.Tip: use the ← and → keys to move between lessons.