Compiler pipeline
Use this when
Section titled “Use this when”This is the Reference section — the contract layer of Quon’s docs. Use
it when you want to look up what a pipeline stage or a quonc flag
guarantees, without reading compiler source. The contracts here are frozen
against the implementation; they change only when the pipeline’s observable
behavior changes, not when internal pass ordering shifts.
Quon’s docs come in three depths. This page sits in the middle and links to the other two, each labelled so you know what you are stepping into:
- Language guide (concept) — what a
.qnprogram means and why the language is shaped the way it is, from first principles. Step back here when a contract references a concept you have not yet met. → Introduction. - Architecture (rationale) — where each stage lives in the compiler source, what invariant it owns, and why the ADRs made it that way. Step forward here when you will read or extend compiler code. → Compiler internals, Neutral-atom model.
Cross-links out of this page are marked (concept — Language guide) or
(rationale — Architecture).
quonc runs a shared frontend and MLIR-backed lowering path before selecting a
target-specific artifact: OpenQASM 3 for fixed gate-model targets, or
schedule/resource outputs for reconfigurable neutral-atom targets.
Pipeline overview
Section titled “Pipeline overview”Scope: contract view. This is the stable per-stage contract — what each stage guarantees, frozen against the implementation. For the concept-level map of features onto stages, see the language guide’s From source to artifact
(concept — Language guide); for where each stage lives in source and why, see compiler internals(rationale — Architecture).
- Parse and desugar. The frontend parses
.qnsource and desugars surface syntax into the core AST. - Typecheck and elaborate. The linear typechecker validates declarations, quantum ownership, depth bounds, register widths, and Clifford classifications. Parametric circuit calls are specialized at concrete call sites via the Melior-free SpecializedCircuit module — the typed boundary between elaboration and lowering (ADR-0038, #206). Specialization runs without linking LLVM/Melior, enabling fast unit and property testing.
- Lower to MLIR generic-form IR. Circuit functions lower through explicit
Rust builders around unregistered
quantum.circoperations.runblocks lower directly intoquantum.dynamicoperations — the ephemeralmonadic_stagingdialect was collapsed intoquantum.dynamicso only two quantum dialects exist in the IR:quantum.circandquantum.dynamic(ADR-0037, #213). - Optimize circuit IR. Circuit-level passes simplify gates and rotations,
run cancellation/merging, perform compiler uncomputation, apply bounded
ZX simplification where the representation supports it, and run real
Clifford+T optimization (ADR-0039, #96):
- Phase polynomial pass (for
clifford=falsecircuits): extracts non-Clifford content as linear Boolean phase terms, merges/cancels algebraically across non-adjacent gates, and re-synthesizes — reducing T-count beyond peephole adjacency. - Aaronson-Gottesman stabilizer tableau (for
clifford=truecircuits): simulates Clifford gates via a CHP tableau over GF(2), detects identity and single-Pauli sequences across non-adjacent patterns, and replaces them.
- Phase polynomial pass (for
- Lower dynamic behavior. Measurement deferral and classical-region
fusion normalize dynamic behavior.
runblocks are already inquantum.dynamicfrom step 3 — no separate staging pass. - Select the backend path. Fixed targets run the consolidated Fixed physical layout module (ADR-0034, #316): native-gate decomposition, SABRE-style routing, post-routing decomposition, depth scheduling, metrics, and OpenQASM 3 emission — all consuming a single canonical SSA-wiring representation for physical qubit identity. Neutral-atom targets extract an atom-indexed interaction graph (ADR-0029, #318), schedule entangling layers, plan movement, compact the schedule, and build a resource report.
This is the stable high-level shape. Individual internal pass ordering remains an implementation detail.
Typechecker architecture
Section titled “Typechecker architecture”The typechecker is decomposed into judgment modules, each owning one sub-language of the type system (ADR-0028, #207):
| Module | Judgment | ADR |
|---|---|---|
typecheck/circuit.rs |
Circuit typing — gate placement, depth/width inference, Clifford class | ADR-0028 |
typecheck/monad.rs |
Quantum Monad / borrow — run blocks, borrow escape policy, cleanup (measure/reset/discard per #180) |
ADR-0031 |
typecheck/obligation.rs |
Refinement / Z3 — depth upper-bound, width equality, well-founded termination, assumption recording | ADR-0032 |
typecheck/classical.rs |
Classical Γ — arithmetic, lists, lambdas, branches, match/exhaustiveness, patterns, subsumption | ADR-0035 |
typecheck/linear.rs |
Linear Δ — resource bookkeeping (consumption, splitting, residual joining) | — |
typecheck/exhaust.rs |
Exhaustiveness — match-arm usefulness algorithm | — |
typecheck/unify.rs |
Unification — metavariable substitution table | — |
The TypeChecker struct in mod.rs is the facade that dispatches into these
modules. Each module uses pub(super) methods so no new public exports leak.
This decomposition means removing any one judgment (e.g. Z3) touches only its
own module — the deletion test from the typechecker split epic (#207).
Circ extract/rebuild seam
Section titled “Circ extract/rebuild seam”ZX simplification (#75) and Clifford+T optimization (#96) share a faithful
circ extract/rebuild seam (ADR-0033, #320): quantum.circ regions are
extracted into a Melior-free CircGate IR keyed by the gate registry
(quon_core::gates), with SSA-root wire tracking for faithful multi-qubit
handling. Unsupported constructs fail closed — the rewrite is declined and
the function is left unchanged, never silently dropping gates that would change
semantics.
Fixed physical layout
Section titled “Fixed physical layout”The Fixed physical path is owned by one module (mlir_bridge/src/fixed_physical.rs,
ADR-0034, #316). SSA wiring is the single canonical channel for physical
qubit identity — both OpenQASM emission and depth scheduling consume it.
phys_qubit attributes are a derived view written from SSA after routing, not
a primary channel. This eliminates the prior fork where emit and scheduling
could disagree on physical qubit identity.
Neutral-atom architecture
Section titled “Neutral-atom architecture”The neutral-atom backend (quon_na) uses an atom-indexed interaction graph
(ADR-0029, #318): InteractionGraph<V> is generic over the vertex type, with
V = LogicalQubitId for the bare-qubit path and V = AtomVertexId for the
hybrid QEC path. The hybrid path names physical atoms directly via the
AtomVertexId newtype — no numeric casts from atom indices to logical qubit
IDs.
Both bare-qubit and hybrid QEC paths share a single plan_backend entry
point for placement, AOD movement, and entangling (ADR-0036, #317). The hybrid
shell (per-round expansion, Wait barriers, serial Z-then-X split, shared layout
across rounds) stays in qec_schedule per ADR-0016. The QEC path now populates
NaStats with per-stage timings, unblocking --emit-na-stats for QEC-backed
programs (#307).
Target-dependent stages
Section titled “Target-dependent stages”Fixed targets supply:
- physical qubit count and connectivity for routing;
- native gate set for decomposition and OpenQASM emission;
- coherence and timing metadata for scheduling and metrics;
- dynamic-circuit capability flags for target reporting.
With no --target, the compiler uses generic_openqasm: a built-in 64-qubit,
all-to-all fixed target with the standard gate set.
Neutral-atom targets supply:
- zone and array geometry;
- AOD movement and Rydberg interaction parameters;
- operation timing and fidelity data;
- resource and cost-model parameters.
Those targets use --emit-na-schedule and --emit-resource-report rather than
--emit-qasm. --emit-na-stats is now supported for both bare-qubit and
QEC-backed programs.
Diagnostics and debug checks
Section titled “Diagnostics and debug checks”Parse, type, elaboration, lowering, and emission failures stop the compile and
produce diagnostics. --dump-ir exposes selected pipeline checkpoints on
standard error. --verify-linear adds debug linearity checks before and after
dynamic lowering.
The compiler still builds the target artifact when no output flag is supplied. Output flags control what is written to standard output or files; metrics flags report data collected from the same compile.
Useful inspection commands:
cargo run -p quonc -- --list-passescargo run -p quonc -- test/verify/bell.qn --dump-ir --emit-qasmcargo run -p quonc -- \ --target targets/neutral_atom/generic_rna_v0.json \ --print-targetSee the quonc CLI reference for command examples and the maturation path for the production-hardening direction.
Where to go next
Section titled “Where to go next”- quonc CLI — the companion reference page: every flag and option the compiler accepts.
- Language guide: Introduction
(concept — Language guide)— step back when a contract references a source-language concept you have not yet met. - Compiler internals
(rationale — Architecture)— step forward to where each stage lives in the compiler source and why the ADRs shaped it that way. - Neutral-atom model
(rationale — Architecture)— the hardware model and target schema behind the neutral-atom stages above.