ziglang/zig
Architecture
The Zig compiler is a multi-stage pipeline that turns Zig source into machine code or object files. The same pipeline is shared by zig build-exe, zig build-lib, zig build-obj, zig test, and zig run. The high-level invariant is: every module passes through tokenization → AST → ZIR → AIR → backend, with comptime evaluation happening inside semantic analysis.
graph TD src["Zig source"] --> Tok["Tokenizer (lib/std/zig/tokenizer.zig)"] Tok --> Parse["Parser (lib/std/zig/Parse.zig)"] Parse --> Ast["std.zig.Ast"] Ast --> AstGen["AstGen (lib/std/zig/AstGen.zig)"] AstGen --> Zir["ZIR (lib/std/zig/Zir.zig)"] Zir --> Sema["Sema (src/Sema.zig)"] Sema --> InternPool["InternPool (src/InternPool.zig)"] Sema --> Air["AIR (src/Air.zig)"] Air --> CG["codegen (src/codegen.zig + src/codegen/*)"] CG --> Link["link (src/link.zig + src/link/*)"] Link --> Out["Executable / object / library"]
Stages
1. Driver — src/main.zig
mainArgs in src/main.zig parses the CLI, builds a Compilation.Config, and constructs a Compilation for the requested artifact. The CLI also handles non-build commands (fmt, ast-check, init, fetch, targets, etc.) directly.
2. Package resolution — src/Package.zig
A Package.Manifest describes the root module of the project. The package manager (src/Package/Fetch.zig, src/Package/Manifest.zig) resolves dependencies declared in build.zig.zon, downloads tarballs into the global cache, verifies hashes, and produces the dependency graph that Compilation consumes.
3. Compilation orchestrator — src/Compilation.zig
This is the largest single file in the compiler (≈344 KB). It owns:
- The
ThreadPooland work queues. - The
Cache(lib/std/Build/Cache.zig) used to skip work between runs. - The list of
Modules to analyze, theZcu(Zig Compilation Unit) that holds analyzed declarations, and thelink.Filethat owns the output. - The pipeline itself: parse → AstGen → analyze → codegen → emit.
Watch-mode and the incremental debug server (src/IncrementalDebugServer.zig) re-run only the work units affected by file edits.
4. Frontend (parse + AstGen) — lib/std/zig/
Tokenization (tokenizer.zig), parsing (Parse.zig), and AST shape (Ast.zig) all live in the standard library so user programs can run them too. AstGen.zig lowers an AST into ZIR (Zig Intermediate Representation), a flat untyped IR designed for cheap diffing and incremental compilation. ZIR is documented in Zir.zig.
5. Semantic analysis — src/Sema.zig
Sema.zig (≈1.6 MB, the largest single file in the codebase) walks ZIR, executes comptime code, performs type checking, and emits AIR (Analyzed IR — src/Air.zig). Several heavy responsibilities split into siblings:
src/Zcu.zig— module graph, declarations, source locations, error rendering.src/InternPool.zig— interned types, values, and strings shared bySemaand codegen (≈513 KB).src/Sema/arith.zig,src/Sema/bitcast.zig,src/Sema/comptime_ptr_access.zig,src/Sema/LowerZon.zig— focused subroutines for arithmetic, bitcast, comptime pointer reads/writes, and ZON lowering.src/Type.zig,src/Value.zig,src/mutable_value.zig— the type/value model.
6. Backends — src/codegen.zig + src/codegen/*
Each backend consumes AIR and emits machine code or another IR.
src/codegen/llvm.zig— the LLVM backend (the "release" path, ≈580 KB single file plus support modules).src/codegen/x86_64/CodeGen.zig— the self-hosted x86_64 backend (≈10.4 MB single Zig file; the largest hand-written backend).src/codegen/aarch64/,src/codegen/riscv64/,src/codegen/sparc64/,src/codegen/wasm/,src/codegen/spirv/,src/codegen/arm/,src/codegen/mips/— additional self-hosted backends in varying degrees of completeness.src/codegen/c.zig— the C backend, which can re-emit Zig as portable C.
src/register_manager.zig is the shared register allocator used by the hand-written backends.
7. Linking — src/link.zig + src/link/*
Each output format has its own linker that consumes the per-object output of codegen and produces the final binary:
src/link/Elf.zig(andsrc/link/Elf/) — ELF.src/link/MachO.zig(andsrc/link/MachO/) — Mach-O.src/link/Coff.zig— COFF/PE (Windows).src/link/Wasm.zig(andsrc/link/Wasm/) — WebAssembly.src/link/SpirV.zig(andsrc/link/SpirV/) — SPIR-V (GPU).src/link/C.zig— output as C source.src/link/Lld.zig— LLD fallback used when-fuse-lldis selected (typically with the LLVM backend).src/link/Dwarf.zig,src/link/Elf2.zig— debug info and a newer ELF linker, respectively.
8. Bundled tools and runtime
When zig is also acting as a C/C++ toolchain, several other libraries ship in the binary:
lib/compiler_rt/— soft-float, integer division, atomic helpers, etc.lib/libcxx/,lib/libcxxabi/,lib/libunwind/,lib/libtsan/— the C++ runtime sources LLVM expects.lib/libc/{glibc,musl,mingw,wasi,darwin,freebsd,netbsd}/— bundled libc sources or stubs for cross-compilation.lib/include/— clang resource headers.
How comptime and incremental compilation interact
A central design point is that Sema runs as a fixed-point evaluator over ZIR and produces AIR for everything that is reachable. ZIR is intentionally cheap to regenerate from the AST; AIR is invalidated only when the analysis result it depends on changes. The Zcu keeps an explicit dependency graph so that file edits, when caught by lib/std/Build/Watch.zig, cause only the affected declarations to be re-analyzed and re-codegen'd — that is the foundation for zig build --watch and the incremental debug server (src/IncrementalDebugServer.zig, tools/incr-check.zig).
What runs where
graph LR
subgraph CLI ["zig (binary)"]
Main["src/main.zig"]
end
subgraph Stdlib ["lib/std (also used by user programs)"]
AstGenS["zig.AstGen + Ast"]
BuildS["std.Build (zig build)"]
Cache["std.Build.Cache"]
end
subgraph CompilerLib ["lib/compiler (shipped tools)"]
Aro["aro (C frontend)"]
Resinator["resinator (rc.exe)"]
BuildRunner["build_runner"]
TestRunner["test_runner"]
Objcopy["objcopy"]
StdDocs["std-docs"]
Reduce["reduce"]
TranslateC["translate-c"]
end
Main --> AstGenS
Main --> BuildRunner
Main --> Cache
Main --> Aro
Main --> Resinator
Main --> Objcopy
Main --> Reduce
Main --> TranslateC
Main --> TestRunner
Main --> StdDocsKey files at a glance
| File | Lines / size | Role |
|---|---|---|
src/Sema.zig |
~1.6 MB | Semantic analysis and comptime evaluation. |
src/InternPool.zig |
~513 KB | Interned types/values/strings. |
src/codegen/x86_64/CodeGen.zig |
~10.4 MB | Hand-written x86_64 backend. |
src/codegen/llvm.zig |
~580 KB | LLVM backend. |
src/main.zig |
~350 KB | CLI dispatch. |
src/Compilation.zig |
~344 KB | Compilation pipeline driver. |
src/Zcu.zig |
~212 KB | Module graph, errors. |
src/link/MachO.zig |
~196 KB | Mach-O linker. |
src/link/Elf.zig |
~159 KB | ELF linker. |
src/link/Wasm.zig |
~167 KB | Wasm linker. |
lib/std/zig/AstGen.zig |
~576 KB | AST → ZIR. |
lib/std/zig/Zir.zig |
~210 KB | ZIR encoding/decoding. |
lib/std/Build.zig |
~101 KB | std.Build API. |
See by the numbers for more.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.