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 - bar
binary only)foo * bar
)foo < bar
, foo <= bar
)// foo
and /* foo */
)foo; bar
)if (foo) { bar }
, no else
yet)int
only, function scope only, must be
initialised)int
only)while (foo) { bar }
)int foo()
i.e. no arguments, returning int)GPL v2 license.
You will need clang
, lex
and yacc
installed. 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