C Frontend (.c)

PXX features a C frontend that compiles C source files directly to native ELF executables in a single pass. There is no separate assembly or linkage step. The compiler handles preprocessing, syntax parsing, type-checking, IR lowering, and machine code generation, producing a self-contained binary.

[!NOTE] The C frontend is an alternative frontend sharing the PXX compiler backend. It supports compiling substantial real-world programs (e.g., tiny-regex, Lua, and SQLite) directly from C source.


Dialect and Language Features

The C frontend targets a C99-class dialect (__STDC_VERSION__ is 199901L) suitable for compiling standard systems code and libraries — it is the frontend that passes the full c-testsuite conformance battery and compiles real corpora such as SQLite, Lua, zlib, cJSON, and tcc (see compatibility status).

Supported Syntax & Types

Preprocessor Support

PXX includes an integrated preprocessor that handles:

[!NOTE] #error and #warning are currently parsed and silently ignored — a .c file containing #error "message" on an active branch compiles clean instead of failing. Don't rely on #error to gate a build.

Not (yet) supported

No VLAs (variable-length arrays), no computed goto, no _Complex / _Atomic / <stdatomic.h>, no C11 <threads.h>, and no vector-extension intrinsics.


To allow C programs to compile into compact, self-contained binaries, PXX provides its own C runtime library (CRTL) in lib/crtl/ and uses an automated linking mechanism known as the Magic Link:

  1. Header Inclusion: When a C program includes a standard header (such as #include <math.h>), the preprocessor maps this to lib/crtl/include/math.h.
  2. Auto-Pulling Implementation: Immediately after loading the declarations, the preprocessor automatically pulls the corresponding implementation file from lib/crtl/src/math.c.
  3. Unity Compilation: Symbol definitions from the .c implementations are compiled directly with the program. Undesired/unused symbols are discarded during dead-code elimination, resulting in a libc-free, zero-dependency (zero DT_NEEDED) binary.
  4. Deduplication: Implementations are pulled at most once per compilation, preventing duplicate symbol definition conflicts and handling recursive includes.

System Libraries Opt-Out

If a C program requires the host's actual libraries (e.g., standard glibc or libm) instead of PXX's bundled runtime, you can configure linking behavior using command-line options.

1. Global Opt-Out (--system-libs)

Using the --system-libs option tells the compiler to disable the magic-link auto-pull mechanism for all standard libraries. Declarations in <header.h> then map to external symbols, and the compiler emits standard DT_NEEDED metadata pointing to the host's shared libraries (e.g., libc.so.6, libm.so.6).

2. Granular Opt-Out (--system-libs=<list>)

You can specify a comma-separated list of soname stems (e.g., --system-libs=m or --system-libs=m,pthread) to opt out of the magic link only for specific libraries:

# Compile using system math library but magic-linked string/stdio
./pxx --system-libs=m program.c program

3. Integration Libraries Default

Libraries that PXX does not emulate (such as GTK, zlib, sqlite, pthread, and dl) are modeled as system libraries by default. Symbols imported from these headers will resolve via DT_NEEDED to the host system libraries unless explicit wrappers are configured.


CRTL Header Coverage

lib/crtl/ bundles both the headers (lib/crtl/include/) and libc-free implementations (lib/crtl/src/) that back the Magic Link. Implemented, with a real .c body behind the header (not just declarations): assert.h, ctype.h, fcntl.h, locale.h, math.h (the largest, ~1200 lines), pthread.h (a real but partial threading subset — see below), signal.h, stdio.h (~1000 lines), stdlib.h, string.h, time.h, unistd.h, and socket-related headers. setjmp.h is backed by compiler intrinsics rather than a .c file. wchar.h/wctype.h headers exist but have no implementation file behind them yet — treat wide-character support as unimplemented even though the header is present.

pthread.h is a genuine subset, not a glibc-ABI-compatible implementation: mutexes, pthread_self/pthread_equal, create/join, pthread_once, and condition variables — no TLS keys, no thread cancellation, no scheduler attributes. Threaded C code needs --threadsafe.


Known Limitations


Next