A C90 compiler that complies. Feed it C, it hands back RISC-V assembly.
Written in C++ around a Flex lexer and a Bison grammar, with a hand-rolled AST and code generator behind them. No LLVM, no borrowed intermediate representation: every construct lowers itself to RV32 assembly directly.
program.c --> lexer.flex --> tokens --> parser.y --> AST --> codegen --> program.s
- Front end. Flex tokenises, Bison parses the C90 grammar and builds the tree.
- AST. Each language construct (declarations, operators, control flow,
function calls) is a node class in
include/, and each node knows how to emit its own assembly. - Context. A single context object threads through code generation and keeps track of scopes, types, the stack frame, and which registers are live, so the nodes can stay small and dumb.
int,unsigned,char,floatanddoublearithmetic- pointers, arrays, and strings
- control flow:
if/else,while,for,switch,break,continue - function definitions, calls, and recursion
- local and global variables with proper scoping
Correctness is checked against a suite of 86 C programs, each compiled to assembly, assembled for RISC-V, and executed against a reference driver. complier currently passes 55 of the 86.
make
bin/c_compiler -S program.c -o program.sscripts/test.py builds the compiler and runs the whole test suite with a
progress bar. If you don't have a RISC-V cross-toolchain lying around, the
provided Dockerfile pins everything you need.
Built by Sam Barber and lolzio5. The build skeleton and test harness come from Imperial College's langproc infrastructure, visible in the early history.