jcc is a production-grade, clean-room C11 compiler written in idiomatic
Rust (C23 is an ongoing stretch goal). It is built for strict C11 compliance,
deterministic granular undefined-behavior diagnostics, a query-driven compiler
architecture, and drop-in Clang command-line compatibility — jcc is designed
to be a CC/CMAKE_C_COMPILER replacement in existing build systems.
Status: M0–M4 complete · M5 nearly green · M6 in flight. The pipeline works end to end on C11 —
-E/-S/-c/-emit-jcc-ir/-emit-llvmall function, and the ELF x86_64 objects jcc emits link and run. Validation: c-testsuite 220/220, Csmith 93 pass / 0 fail / 7 skip (100-seed-O1), LLVM test suite 32/36 (4 documented GNU-extension policy gates), lz4 full green (build +tests:essentials8/8 + benchmark); sqlite3.c parses and lowers clean with the full-file gate run in final verification. The workspace test suite (~2,700 unit + integration tests) is green and the clippy/fmt gates are clean. See docs/roadmap.md for the milestone tracker.
- Strict C11 — with deterministic, granular UB diagnostics as a headline feature (constant-operand UB is diagnosed at compile time).
- Query-driven architecture (salsa-like, cf. rustc): lazy evaluation, incremental compilation, and LSP-ready semantic queries from day one.
- CIR — a bespoke, strongly-typed SSA IR designed for C semantics, built on arena allocation and index-based references (data-oriented design). Independent of LLVM IR by design; LLVM IR text export is supported for interop (bitcode export is M7).
- Fearless concurrency — no global mutable compiler context; phases parallelize across cores.
- Drop-in Clang CLI (
-O,-S,-emit-llvm,-emit-jcc-ir, …) with first-class help and diagnostics; emits native object files and integrates withmold/lld/ the system linker. - Validation targets: c-testsuite
(220/220 — M4 gate), the LLVM test suite (32/36, M5), Csmith differential
fuzzing (93/0/7, M5), and real-world applications (
lz4green, thesqlite3.camalgamation in final verification — M6). - Targets: x86 and x86_64 (mandatory), AArch64 (high priority, M7).
| Area | Status |
|---|---|
Frontend (C11): preprocessor (target builtin macros incl. __x86_64__, trigraphs always-on, $-identifiers, C23 ' digit separators + binary literals, #pragma pack), parser, sema; GNU statement-expressions and range designators; K&R function definitions; bundled C11 standard headers (#include <stdio.h> works) |
Supported |
Integer/pointer arithmetic, shifts, 8/16/32/64-bit compares, _Bool, __int128/__uint128_t ABI |
Supported |
Control flow: if / loops / switch incl. jump tables (dense switches) |
Supported |
Calls: direct/indirect, variadic calls and definitions (va_list/va_arg), SSE scalar float (F32/F64) args/returns |
Supported |
| Records/unions: values by value (INTEGER/MEMORY/SRET/SSE classification, incl. mixed Integer+SSE eightbytes and records > 64 B), bit-fields (expression access, initializers incl. file-scope, packed layouts), whole-struct copies, inline memset/memcpy/memmove | Supported |
| VLAs (dynamic alloca), fixed-size arrays, string literals | Supported |
Atomics: loads/stores/RMW/CAS/fences (TSO mapping), incl. compound RMW (*= /= %= <<= >>=) |
Supported |
Constant-UB diagnostics (CompileErrorKind::Ub): shift count / signed overflow / div-by-zero on constant operands |
Supported |
offsetof incl. flexible-array members; anchored address constants (C11 6.6p9, &((T *)0)->member); empty structs; _Alignas/_Alignof |
Supported |
Constructor/destructor attributes end-to-end (.init_array/.fini_array emission, verified link-and-run) |
Supported |
| Regalloc spill-fallback eviction | Supported |
long double (x87 F80): type, loads/stores, varargs, int → long double |
Partial — F80 arithmetic (Add/Sub/Mul), FPExt (double → long double), and FPToSI (long double → int) are rejected loudly (documented) |
Thread-locals (_Thread_local) |
Rejected loudly (clean diagnostic; M2 backlog) |
PIC (-fPIC accepted; no PIE-safe jump-table variant yet) |
Partial |
i386/Win64/AArch64 targets, Mach-O/COFF object writers, LLVM bitcode export (-emit-llvm -c), LSP groundwork |
M7 backlog (designed, not implemented; -m32 accepted no-effect) |
Documented GNU-extension policy gates (accepted outcome, deterministic clean
rejections — tracked in docs/c11-compliance.md and
the tools gate ledgers): GNU colon-style designated initializers
({ __d: __x }), __transparent_union__ call-argument coercion, computed goto
(&&label / goto *ptr).
The full per-flag matrix — accepted, deferred, rejected, not implemented — lives in docs/cli-compat.md.
Requires a stable Rust toolchain (see rust-toolchain.toml).
cargo build --releaseThe jcc binary is produced at target/release/jcc (or target/debug/jcc
for a dev build).
Contributor note (this development environment only): when the rustup home cannot be created under
$HOME(read-only root fs), prefix cargo invocations withRUSTUP_HOME=$TMPDIR/rustup CARGO_HOME=$TMPDIR/cargo, e.g.RUSTUP_HOME=$TMPDIR/rustup CARGO_HOME=$TMPDIR/cargo cargo build --release. Some preprocess temp-file tests also needTMPDIRon a writable, roomy filesystem (e.g.TMPDIR=/home/bill/.cache/jcc_tmp).
jcc mirrors Clang's flag structure, so existing LLVM-centric workflows keep
working:
# Compile to an object file and link with mold
jcc -O2 -c hello.c -o hello.o
jcc hello.o -o hello -fuse-ld=mold
# Assembly output (AT&T syntax on x86_64 by default, like clang)
jcc -S hello.c
# Preprocess only
jcc -E hello.c
# Emit the internal CIR or LLVM IR
jcc -emit-jcc-ir hello.c
jcc -emit-llvm -S hello.cOptimization levels -O0 … -O3, -Os, -Oz are parsed and wired into the
jcc-opt pass pipeline (const-fold, DCE, GVN, unroll — conservative at
OptLevel::Default, aggressive at Aggressive); jcc_ir::verify runs after
every pass in debug builds.
Accepted flags (representative; the full matrix is in
docs/cli-compat.md): -E -S -c -o -x -emit-jcc-ir -emit-llvm, -O0..-O3 -Os -Oz, -D -U -I -isystem -include -nostdinc,
-std=c11|gnu11|c23|gnu23 (c11 default), -m64 (-m32 accepted, no effect for
now), --version --help -v -###, -Wall -Wextra -Werror -w, -MD -MMD -MF -MT
(parsed and recorded; depfile emission is a documented deferred item),
-L -l -Wl, -Xlinker -shared, -fPIC -ffreestanding -fuse-ld= -resource-dir -Qunused-arguments -fdiagnostics-color=, response files @file,
-target/--target, -march= -mtune=. Recognized but rejected with a clean
"unsupported option" error: -ansi, -std=c99/c17/…, -fsyntax-only,
-fopenmp*, -fsanitize=*. Not implemented (absent from the flag tables;
"unknown argument" error): -imacros -undef -save-temps --sysroot.
Point your build system at the jcc binary as the C compiler:
- CMake:
set(CMAKE_C_COMPILER /path/to/jcc)(or pass-DCMAKE_C_COMPILER=/path/to/jcc). - Make / Ninja / Meson:
export CC=/path/to/jcc(orCC=jccwith jcc onPATH).
jcc responds to --version with a clang-style layout so CMake-style compiler
detection works. Dependency-generation flags (-MD/-MMD/-MF/-MT) are
accepted and recorded, though depfile emission is a documented deferred item
(see docs/cli-compat.md); -M/-MM are accepted without
effect for now. Linking integrates with mold, lld, or the system ld — the
driver probes in that order; override with -fuse-ld= (e.g. -fuse-ld=mold).
jcc implements no libc: the bundled runtime/include/ headers declare the C11
standard library surface ABI-compatible with the host libc (Linux/glibc first),
so programs link against the system libc as usual.
Milestone gates and their harnesses (all under tools/, python3 stdlib-only).
Numbers as of August 2026, verified against the current tree:
| Milestone | Gate | Status |
|---|---|---|
| M0 | Workspace skeleton, CONTEXT tree, CI green | DONE |
| M1 | Walking skeleton: -E/-S/-c/-emit-jcc-ir/-emit-llvm on C11; ELF x86_64 objects link & run |
DONE — gate green |
| M2 | Full C11 frontend + missing codegen (floats, atomics, VLAs, bit-fields, jump tables, record values, F80, K&R, #pragma pack, stmt-exprs, range designators, …) |
LANDED (honest leftovers documented above) |
| M3 | Correctness-first CIR optimizer (const-fold/dce/gvn/unroll) | in progress |
| M4 | c-testsuite 100% — tools/c-testsuite/run.py (upstream --std=c11 -O2 flags) |
DONE — 220/220 PASS |
| M5 | Csmith differential fuzzing — tools/csmith/run.py (100 seeds, -O1); LLVM test suite — tools/llvm-suite/run.py (SingleSource/Regression/C, 36 tests) |
Csmith 93 pass / 0 fail / 7 skip (skips = both-compiler timeout); LLVM suite 32/36 (4 documented GNU policy gates) |
| M6 | lz4 — tools/bench/lz4.py; sqlite3.c — tools/bench/sqlite.py |
lz4 full green (build + tests:essentials 8/8 + bench); sqlite: parse + lower clean, full-file gate run in final verification |
| M7 | AArch64, Mach-O/COFF, bitcode export, LSP groundwork | Groundwork: ELF .init_array/.fini_array emission landed (ctor/dtor end-to-end); AArch64/Mach-O/COFF/bitcode/LSP not started |
The workspace gate: ~2,700 unit + integration tests across 8 crates all
pass (1 intentional ignore), cargo clippy --workspace --all-targets -- -D warnings is clean, and cargo fmt is clean. The end-to-end corpus
(tests/, 105 cases: 86 compile-run + 19 compile-fail) is 105 passed /
0 skipped / 0 failed.
- M3 — Correctness-first CIR optimizer: in progress — const-fold, dce, gvn,
and unroll are implemented (vectorize remains interface-reserved only);
jcc_ir::verifyruns after every pass in debug builds. - M4 — c-testsuite 100%: done — 220/220 PASS.
- M5 — LLVM test suite + Csmith: csmith 93/0/7; LLVM suite 32/36 — the 4 remaining failures are documented GNU-extension policy gates (colon designators, transparent unions, computed goto, long-double FPExt), not regressions.
- M6 — lz4 + sqlite3.c: lz4 full green; sqlite3.c (v3.54.0 amalgamation) parses and lowers clean — the full-file gate run is in final verification.
- M7 — AArch64, Mach-O/COFF, LLVM bitcode export, LSP groundwork: ELF
.init_array/.fini_arraygroundwork landed; the rest is designed, not implemented.-m32is accepted no-effect.
See docs/roadmap.md — the authoritative milestone tracker — for details and acceptance criteria.
cargo test --workspace # unit + integration tests (~2,700) + end-to-end corpus (tests/)The end-to-end corpus (tests/, 105 cases across compile-run and
compile-fail suites) is currently 105 passed / 0 skipped / 0 failed; the
suite activates automatically once target/debug/jcc exists.
External validation harnesses live in tools/ (c-testsuite runner, LLVM test
suite hookup, Csmith fuzzer, lz4/SQLite benchmarks) — all python3 stdlib-only,
each self-tests with --compiler cc.
- docs/architecture.md — pipeline and design
- docs/roadmap.md — milestones M0–M7 (authoritative tracker)
- docs/c11-compliance.md — C11 conformance matrix, UB diagnostics catalog, extension policy
- docs/cli-compat.md — Clang flag compatibility matrix
- docs/testing.md — test strategy and gate definitions
- docs/coding-standards.md — engineering rules
- Pure, idiomatic Rust:
#![forbid(unsafe_code)]workspace-wide. - CI enforces
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings, build and test, plus a python3 syntax check ontools/. - No panics on user input; diagnostics are first-class and deterministic.
- Clean-room engineering: no LLVM/Clang source code is copied or translated; running Clang to observe reference behavior and compare outputs is encouraged.
- All validation must run within 32 GB RAM on consumer hardware.
No license file is present in the repository yet; do not redistribute without the maintainers' consent.