A toy C compiler
An educational foray into compiler writing. Written in C, compiling C to x86 assembly (handy x86 reference site, assembly directives reference, System V ABI reference).
Technically targeting C11 (standard PDF), but we will implement such a small subset of C that it's academic.
Table of Contents
!FOO)
~FOO)
foo + bar)
foo - barbinary only)
foo * bar)
foo < bar,
foo <= bar)
// fooand
/* foo */)
foo; bar)
if (foo) { bar }, no
elseyet)
intonly, function scope only, must be initialised)
intonly)
while (foo) { bar })
int foo()i.e. no arguments, returning int)
GPL v2 license.
You will need
clang,
lexand
yaccinstalled. GNU Bison is known to work, other yacc implementations may not.
Compiling babyc:
# Compile the compiler. $ make
Usage:
# Run it, producing an assembly file. $ build/babyc test_programs/immediate__return_1.c # Use the GNU toolchain to assemble and link. $ ./link
Viewing the code after preprocessing:
$ build/babyc --dump-expansion test_programs/if_false__return_2.c
Viewing the AST:
$ build/babyc --dump-ast test_programs/if_false__return_2.c
Running tests:
$ make test
If you're debugging a compiled program that segfaults, you may want to simply read the out.s file.
To use gdb (given we have no signal table, function prologues or other conveniences), do the following:
$ gdb out (gdb) run ... it segfaults (gdb) layout asm ... shows which line the segfault occurred on (gdb) info registers ... shows the current state of the registers (`layout reg' also ... provides this data)
If you want to debug a program that doesn't segfault, you can set a breakpoint to the entrypoint:
$ gdb out (gdb) info files ... Entry point: 0x80000000 ... (gdb) break *0x80000000 (gdb) run
The make command will generate warnings, fix them. You can also run with clang-analyzer to catch further issues:
$ scan-build make
For code formatting, run:
$ make format