Overview

GX is a procedural, statically-typed programming language inspired by C. It compiles through a pluggable backend architecture, with three native output paths:

  • C transpiler (default) — --backend=c. Emits portable C, links via bundled TCC or a system clang/gcc. Zero build-time dependency on libLLVM; the default cmake -S . -B build always has it.
  • Native LLVM C++ API backend--backend=llvm. Builds an llvm::Module in process, runs the LLVM verifier, optional -O1/-O2/-O3 passes, emits a native object via TargetMachine, and emits DWARF debug info under -g. Requires GX built with -DGX_ENABLE_LLVM=ON.
  • Text-emitting LLVM variant--backend=llvm-clang. Writes textual .ll and shells out to clang to PARSE it back and link. Needs only a clang binary at runtime — no libLLVM linked into GX.exe, so it’s available in every build of GX.

--backend=llvm-api remains a silent alias for --backend=llvm.

Design Goals

  • Deterministic behavior
  • Zero hidden allocations
  • C-compatible layout and ABI
  • UTF-8 native strings
  • Clean and predictable syntax
  • Direct interoperability with C libraries
  • Pluggable backends for different targets

Non-Goals

  • No borrow checker
  • No hidden runtime
  • No garbage collector
  • No inheritance-based OOP

GX assumes the programmer is responsible and values clarity over cleverness.

Compilation Model

GX Source → Frontend (Lex/Parse/Resolve/TypeCheck) → Backend → Output

Three production pipelines (one for each backend):

GX → C  → Native executable     (C backend, default — GX → .c → TCC/clang/gcc)
GX → IR → Native executable     (LLVM API — in-process IRBuilder → .o → clang link)
GX → IR → Native executable     (LLVM text — GX → .ll + user_glue.c → clang)

The compiler’s frontend and backend are cleanly separated. The frontend produces a resolved, typed AST. The backend consumes it through a pluggable Backend interface. Switch backends via --backend=c (default), --backend=llvm, or --backend=llvm-clang. A source file can also declare a preferred backend via @backend("llvm"); the CLI flag, when given, always wins.

C Transpiler (default): generates portable, readable C code. Best for integration with existing C toolchains, fast incremental builds via bundled TCC, and portability to platforms without an LLVM development install.

LLVM (native API): the optimising / debugging path. Lowers GX directly to LLVM IR via IRBuilder, runs the verifier in process, then takes the IR through LLVM’s pass pipeline at the chosen -O level before the codegen emits a native object file. Under -g it emits DWARF (compile unit, per-function DISubprogram, statement-level line table, dbg.declare for every local and parameter), preserved through the link so lldb / gdb / llvm-dwarfdump can step the program and inspect variables. Aggregate values across the C-FFI boundary go through generated pointer-explicit shims, so the IR never has to replicate the platform’s struct ABI.

LLVM (text-emitting): writes textual .ll plus a tiny generated user_glue.c with shim wrappers for any extern fn, then invokes clang to link. Aligned feature set with the C backend; ships against the same module corpus. Useful when you want LLVM IR you can inspect, or when you can’t / don’t want to rebuild GX itself with libLLVM linked in.

Future backends: GPU compute (NVPTX / AMDGPU / SPIR-V) and CPU vectorization (<N x T> IR via LLVM’s vectorizer) — both natural extensions of the native API backend.

Standard Modules

GX ships with reusable modules in the modules/ directory:

  • math — Scalar math (trig, sqrt, clamp, lerp), vector utilities (length, normalize, distance), and matrix transforms (perspective, look_at, multiply). See 07_Math_Module.
  • io / random / time — File I/O, PRNG + simplex noise, clock/date/sleep.
  • json / xml — yyjson-backed JSON, ezxml-backed XML.
  • raylib — Raylib bindings (graphics / input / audio). See 11_Raylib_Module.
  • sokol — Bindings for Sokol graphics/app/input libraries. See 17_Sokol_Module.
  • clay — Clay UI layout, with raylib and sokol renderer adapters.
  • microaudio — Audio playback. See 20_Microaudio_Module.
  • enet — UDP networking via lsalzman/enet 1.3.18 (new in v0.8.3).
  • threading — Win32 / pthread threads + atomics (new in v0.8.3).
  • sdl3 — SDL 3.2.18: window, events, renderer (new in v0.8.3).
  • cimgui — Dear ImGui v1.92.7 via cimgui (new in v0.8.3).

Import with import math.scalar, import math.vec, import math.mat. See What’s New in v0.8.3 for the latest module additions and compiler changes.

Architecture

src/
  frontend/       Lexer, Parser, Resolver, Type Checker, Module Loader, Comptime
  backend/c/      C transpiler + C compiler invocation
  backend/llvm/   Both LLVM backends:
                    llvm_api_backend.cpp — native C++ API (--backend=llvm)
                    llvm_backend.cpp     — text emitter (--backend=llvm-clang)
                    llvm_codegen.cpp     — text-emitter codegen
  driver/         CLI argument parsing
include/gx/
  backend/        Abstract Backend interface (backend.h)
                  + llvm_api_backend.h, llvm_backend.h
  llvm_codegen.h  Text-emitter codegen class
  version.h       Single-source version definition
runtime/
  gx_runtime.h    Shared runtime (ec_str, ec_array, ec_map, etc.)
  gx_runtime_glue.c Linker-visible copies for both LLVM backends
modules/
  math/gx/        Math module (scalar, vec, mat)
  io/gx/          File I/O, filesystem, paths
  random/gx/      PRNG and simplex noise
  time/gx/        Clock, date/time, sleep
  json/gx/        JSON parsing / building (yyjson-backed)
  xml/gx/         XML parsing
  clay/           Clay UI layout
  raylib/         Raylib bindings
  sokol/          Sokol bindings (app, gfx, glue, gp)
  microaudio/     Audio playback
  enet/           UDP networking (v0.8.3)
  threading/      Threads + atomics (v0.8.3)
  sdl3/           SDL3 window/events/renderer (v0.8.3)
  cimgui/         Dear ImGui via cimgui (v0.8.3)

Versioning

GX follows Semantic Versioning. The version is defined once in include/gx/version.h and propagated to all compiler output and generated code automatically.