Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

jcc — just c compiler

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-llvm all 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:essentials 8/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.

Highlights

  • 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 with mold / 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 (lz4 green, the sqlite3.c amalgamation in final verification — M6).
  • Targets: x86 and x86_64 (mandatory), AArch64 (high priority, M7).

Feature status

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.

Building

Requires a stable Rust toolchain (see rust-toolchain.toml).

cargo build --release

The 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 with RUSTUP_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 need TMPDIR on a writable, roomy filesystem (e.g. TMPDIR=/home/bill/.cache/jcc_tmp).

Using jcc

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.c

Optimization 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.

Using jcc with build systems

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 (or CC=jcc with jcc on PATH).

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.

Validation

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.

Roadmap

  • M3 — Correctness-first CIR optimizer: in progress — const-fold, dce, gvn, and unroll are implemented (vectorize remains interface-reserved only); jcc_ir::verify runs 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_array groundwork landed; the rest is designed, not implemented. -m32 is accepted no-effect.

See docs/roadmap.md — the authoritative milestone tracker — for details and acceptance criteria.

Testing

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.

Documentation

Development principles

  • 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 on tools/.
  • 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.

License

No license file is present in the repository yet; do not redistribute without the maintainers' consent.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages