ziglang/zig
Code generation backends
Active contributors: andrewrk, jacobly, mlugg, alexrp, robinvoetter
Purpose
src/codegen/ houses every backend that consumes AIR and produces machine code (or another IR like LLVM IR or C). The dispatcher is src/codegen.zig. The repository is unusual in shipping both a mature LLVM backend and a fleet of self-hosted backends.
Backends in the tree
| Backend | Path | Status / role |
|---|---|---|
| LLVM | src/codegen/llvm.zig (~580 KB single file), src/codegen/llvm/ |
The "release" backend. Lowers AIR to LLVM IR via the bundled C++ glue (src/zig_llvm.cpp, src/zig_llvm.h, src/zig_clang_*.cpp). Used by default when LLVM is available. |
| x86_64 (self-hosted) | src/codegen/x86_64/ |
The most complete hand-written backend. CodeGen.zig is ~10.4 MB — every AIR instruction is lowered here. Includes its own assembler (encoder.zig, ~101 KB), encoding table (encodings.zon, ~161 KB), and disassembler. |
| AArch64 | src/codegen/aarch64/, src/codegen/aarch64.zig |
In-progress hand-written backend. |
| RISC-V 64 | src/codegen/riscv64/CodeGen.zig (~326 KB) |
Hand-written. |
| SPARC64 | src/codegen/sparc64/ |
Hand-written. |
| Wasm | src/codegen/wasm/ |
Hand-written WebAssembly backend. |
| SPIR-V | src/codegen/spirv/ |
GPU shader IR. Consumes the spec generated by tools/gen_spirv_spec.zig. |
| ARM (32-bit) | src/codegen/arm/ |
Skeleton / WIP. |
| MIPS | src/codegen/mips/ |
Skeleton / WIP. |
| C | src/codegen/c.zig (~333 KB) |
Re-emits Zig as portable C. Used for -Donly-c bootstrap and as a fallback target. |
Anatomy of a self-hosted backend
Each hand-written backend follows a common shape, visible in src/codegen/x86_64/:
src/codegen/<arch>/
├── CodeGen.zig # AIR → MIR (the lowering)
├── Mir.zig # Machine IR for this target
├── Lower.zig # MIR → encoded instructions
├── Emit.zig # Bytes → object section
├── Encoding.zig # Instruction encoding helpers
├── encoder.zig # Per-instruction encoder
├── encodings.zon # Encoding table (data, not code)
├── abi.zig # Calling convention / register allocation hints
├── bits.zig # Register sets, immediates
└── Disassembler.zig (x86 only)The shared register allocator lives in src/register_manager.zig (~28 KB) and is reused by each backend.
Dispatch
graph LR Comp["src/Compilation.zig"] --> CG["src/codegen.zig"] CG -->|target uses LLVM| LLVM["src/codegen/llvm.zig"] CG -->|target=x86_64, no-LLVM| X86["src/codegen/x86_64/CodeGen.zig"] CG -->|target=aarch64, no-LLVM| AA["src/codegen/aarch64/"] CG -->|target=riscv64, no-LLVM| RV["src/codegen/riscv64/"] CG -->|target=wasm32| WASM["src/codegen/wasm/"] CG -->|target=spirv| SP["src/codegen/spirv/"] CG -->|backend=c| C["src/codegen/c.zig"] LLVM --> Link["src/link/"] X86 --> Link AA --> Link RV --> Link WASM --> Link SP --> Link C --> Link
The choice between LLVM and the self-hosted path is governed by build-time options (-fllvm / -fno-llvm) and per-target capability flags in src/target.zig. lib/std/Target.zig is the canonical target descriptor; lib/std/zig/llvm/ carries the LLVM target/triple mappings.
Key source files
| File | Purpose |
|---|---|
src/codegen.zig |
Backend dispatch from AIR. |
src/codegen/llvm.zig |
LLVM backend. |
src/codegen/c.zig |
C backend. |
src/codegen/x86_64/CodeGen.zig |
x86_64 lowering. |
src/codegen/x86_64/encoder.zig |
x86_64 encoder. |
src/codegen/x86_64/encodings.zon |
x86_64 encoding table. |
src/codegen/x86_64/Disassembler.zig |
x86_64 disassembler used in tests. |
src/codegen/aarch64/ |
AArch64 backend. |
src/codegen/riscv64/CodeGen.zig |
RISC-V 64 backend. |
src/codegen/wasm/ |
Wasm backend. |
src/codegen/spirv/ |
SPIR-V backend. |
src/register_manager.zig |
Shared register allocator. |
src/target.zig |
Target capability tables. |
src/zig_llvm.cpp, src/zig_clang_*.cpp |
C++ glue to LLVM/clang. |
See Compiler for what feeds AIR into these backends and Linkers for what consumes their output.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.