WARNING: This is a work in progress and shouldn't be used for any serious work
JCC is a JIT C11 Compiler. The preprocessor/lexer/parser is built from chibicc and the VM was built from c4 and write-a-C-interpreter.
The goal of this project is correctness and safety. This is just a toy, and won't be ππ₯ BLAZING FAST π₯π. I wouldn't recommend using this for anything important or in any production code. I'm not an expert, so safety features may not be perfect and will have minimal to significant performance overhead (depending on which features are enabled).
Status: All C11 language features are supported (minus <threads.h> and _Thread_local, see Thread Support). There is also partial C23 support (mostly parser/preprocessor features).
See here for some basic documentation on the API.
- GDB-like debugger (see DEBUGGER.md)
- Export source maps as JSON
cc_output_source_map_json
- Export source maps as JSON
- Tonnes of memory safety features (see SAFETY.md)
- Includes preset safety levels,
-0, -1, -2, 3(0 is no safety, and is default) - Safety features come with an overhead
- Includes preset safety levels,
- Bytecode optimization passes (see OPTIMIZATION.md)
--optimize[=LEVEL]with levels 0-3 (disabled by default)- Constant folding, peephole optimization, dead code elimination
- Optional libcurl integration, include headers from URL
#include <https://raw.githubusercontent.com/user/repo/main/header.h>- Build with
make JCC_HAS_CURL=1
- Output JSON files containing all function, struct, union, enums, and globals definitions
- Useful for generating wrapper for FFI
./jcc --json -o lib.json lib.h
- Built in memory allocation using
--vm-heap(enabled by some safety features)- All
malloc/calloc/realloc/freecalls are routed through an internal allocator - No need to use standard library for heap allocations
- All
- Arithmetic:
+,-,*,/,%, unary- - Bitwise:
&,|,^,~,<<,>> - Comparison:
==,!=,<,>,<=,>= - Logical:
&&,||,! - Assignment:
=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>= - Increment/decrement:
++,--(both prefix and postfix) - Ternary:
? : - Comma:
,
if,elsefor,while,do-whileswitch,case,defaultgoto label,goto *expr;,&&labelbreak,continue
- Function declarations and definitions
- Function calls (direct and indirect via function pointers)
- Recursion
- Parameters and return values
- Function pointers (declaration, assignment, indirect calls)
- Variadic functions (
<stdarg.h>support withva_start,va_arg,va_end)
- Basic types:
void,char,short,int,long,float,double,_Bool - Pointers (declaration, dereference
*, address-of&, pointer arithmetic) - Arrays (fixed-size, initialization, multidimensional, indexing)
- Array decay (in function parameters and expressions)
- Zero-length arrays (
int arr[0];GNU extension for flexible array members) - Strings (literals with data segment storage)
- Structs (declaration, member access
., nested structs, initialization, flexible array members, anonymous structs/unions) - Bitfields (bit-level struct member access with
: widthsyntax, signed/unsigned, read-modify-write operations) - Unions (declaration, member access, initialization, anonymous unions)
- Enums (declaration, explicit values, in expressions and switches)
- Variable-length arrays (VLA with runtime allocation via VM heap)
static(static locals, static globals, static functions)extern(external linkage for multi-file projects)const(const-correctness in type system and codegen)inline(parsed and generated normally, behaves like static, no special optimization)volatile(tracked in type system, prevents optimization of accesses)register(accepted and ignored, no special optimization)restrict(accepted and ignored, aliasing not tracked)
typedef(all types including function pointers)sizeofoperator (compile-time evaluation for all types)- Forward declarations (incomplete types, self-referential structs)
- Floating-point arithmetic (double precision with full operations)
- Compound literals (scalars, arrays, structs)
- Designated initializers (arrays and structs)
- Cast expressions (explicit type conversions)
#include(with intelligent search path handling)- Standard library headers (
<stdio.h>,<stdlib.h>, etc.) automatically use JCC's./includedirectory - User headers with
"quotes"search-Ipaths - Non-standard angle-bracket headers require
--isystempaths (system headers not searched by default) - Full paths work directly
- No
-I./includeflag needed - added automatically
- Standard library headers (
#define(object-like and function-like macros)#ifdef,#ifndef,#if,#elif,#else,#endif#elifdef,#elifndef#undef#pragma once#error,#warning- Macro expansion and stringification
__VA_OPT__for conditional variadic macro expansion (C23)#embed- Binary resource inclusion (C23)- Embeds binary files as comma-separated integer literals (0-255)
#embed "file.bin"- Quoted form (searches include paths)#embed <file.bin>- Angle bracket form (searches system paths)limit(N)parameter - Restricts number of bytes embedded__has_embed("file")- Check file availability (returns 0=not found, 1=non-empty, 2=empty)- Files >10MB trigger warnings by default (50MB for secondary warning)
--embed-limit=SIZE- Customize warning threshold (e.g.,--embed-limit=100MB)--embed-hard-limit- Make limit violations hard errors instead of warningsprefix(...),suffix(...)- Pre/append parameters to dataif_empty(...)- Handle empty resources
- String literal concatenation (adjacent strings automatically combined)
- Multiple input files
- Symbol resolution
- Duplicate definition detection
JCC provides two modes for variadic foreign functions:
- Native Inline Assembly
- AAPCS64 (macOS ARM64)
- TODO: x86_64 (System V AMD64)
- TODO: x86_64 (Windows x64)
- TODO: x86_32 (Legacy 32-bit System V)
- Optional libffi support (Other platforms)
- Build with
make JCC_HAS_FFI=1to enable libffi support (see BUILD) - Use libffi if your platform isn't supported
- Build with
asm("...")statements via callback mechanism- Not executed in the VM (no-op by default)
- Callback can emit custom bytecode or perform logging
- Universal character names
\uXXXX,\UXXXXXXXX- Unicode escapes in strings _Generictype-generic expressions (compile-time type selection)_Alignofoperator (query type/variable alignment)_Alignasspecifier (control variable alignment)static_assertand_Static_assert(compile-time assertions with custom error messages)Bitfields- Bit-level struct member access (e.g.,unsigned int flags : 3;)Anonymous structs/unions- Direct member access without intermediate name- Variable length arrays
int arr[] = { 1, 2, 3 };
typeofoperator (compile-time type inquiry for variables and expressions)typeof_unqual- typeof that removes type qualifiers[[...]]- C23 attributes, like GNU attributes, are parsed but ignored- Binary literals (0b10101010)
- Digit separators with single quotes (1'000'000)
#embeddirective (C23) - Binary resource inclusion
- Statement expressions
({...}) __attribute__((...))for functions and variables (currently ignored, parsed only)- Labels as values
&&label- Get the address of a label for computed goto - Computed goto
goto *expr;- Jump to an address computed at runtime - Switch case ranges
case 1 ... 5:- Match ranges of values in switch statements - Zero-length arrays
int arr[0];- Flexible array member alternative - Nested functions - Define functions inside other functions with access to parent variables
Not supported (yet)
JCC is single-threaded and does not implement any threading or atomic operations yet. Registering pthread as a dynamic library amd loading the functions may work but is untested.
JCC includes embedded standard library headers that are compiled directly into the binary:
stdio.h,stdlib.h,string.h,math.h,time.h,ctype.h, etc.stdarg.h,setjmp.h- JCC-specific implementations for VM calling convention
Headers are embedded using std.py which generates src/std.c. This means:
- No external header files needed at runtime
- Headers are read from strings instead of disk
- Consistent behavior across platforms
To regenerate embedded headers after modifying files in include/:
python3 std.py
makeNote: The
--use-system-headersflag is available but experimental. Apple's system headers contain macros and runtime dependencies that JCC cannot fully support.
- Support for
_Deferstatement - Support for
_Pragmastatement - Support for (some) C23
[[...]]and GNU__attribute__((...))attributes - Proper inlining support
- Support more architectures for native FFI
- x86_64 (System V + Windows) + x86_64 (legacy System V only)
- No plans for any other systems, but will accept patches
- Support for pthread + internal thread support
- Thread safety features (race condition checks, etc)
make jcc # Build jcc compiler
make all # Build everything (jcc, libjcc.dylib) and run tests
# Optional: Build with libffi support for true variadic foreign functions
make JCC_HAS_FFI=1
# Optional: Build with libcurl support for URL header imports
make JCC_HAS_CURL=1This produces:
jcc- Full compiler executable (C source β bytecode β execute)libjcc.dylib- Shared library for embedding
# Compile C source to bytecode file
./jcc -o program.bin program.c
# With multiple files
./jcc -o app.bin main.c utils.c helpers.c
# With preprocessor flags
./jcc -I./include -DDEBUG -o debug.bin main.cAll test files are located in the tests/ directory. To run the complete test suite:
./run_testsThis will run all test files and report:
- Total number of tests
- Number of passed tests
- Number of failed tests
- List of any failed tests
Test runner options:
# Run only tests matching a pattern
./run_tests --match "*embed*" # Runs test_embed_basic.c, test_embed_empty.c, etc.
./run_tests --match "test_ptr*" # Runs test_ptr_arithmetic.c, test_ptr_deref.c, etc.
# Enable memory leak detection (platform-specific: leaks on macOS, valgrind on Linux, drmemory on Windows)
./run_tests --leaks
# Pass additional flags to jcc (all non-option arguments are forwarded)
./run_tests -2 # Run tests with standard safety level
./run_tests --vm-heap # Run tests with VM heap enabledIndividual tests can be run directly:
./jcc tests/test_simple.c
echo $status # Check exit code, should be 42jcc
Copyright (C) 2025 George Watson
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.