Open-Source Wikis

/

Zig

/

Systems

/

Code generation backends

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.

Code generation backends – Zig wiki | Factory