Writing a C Compiler, Part 2
norasandler.com
norasandler.com
IMHO there are plenty of good books on compiler construction. One of the best ones I ever got my hands on was a book by Niklaus Wirth (a now-retired professor, among other things, he created Pascal, Oberon and other languages). He explains all the details of creating your own compiler from the ground up.
It's available only here: https://www.inf.ethz.ch/personal/wirth/CompilerConstruction/...
In that book, he is creating a compiler for Oberon, a language that was more or less used for didactic purposes only. The book is also pretty dated, so there is not much to take away in terms of practically usable compiler code. But I can still recommend it to everyone, because I think it's didactically very good, and provides all the necessary details that make compiler construction so worthwhile (and annoying).
To showcase Wirth's approach, I wrote a self hosted Oberon compiler for the JVM: https://github.com/lboasso/oberonc
The compiler can also be used to compile and run the source code of Oberon0 provided in the book, all you need is a JVM installed.
The Oberon0 language, described in the compiler book, is just a toy to illustrate basic compiler techniques. The full Oberon language is a simple but powerful language, that inspired Go.
MOOC/Courses:
- https://cseweb.ucsd.edu/classes/sp17/cse131-a/
- http://cs.brown.edu/courses/cs173/2016/index.html
- https://lagunita.stanford.edu/courses/Engineering/Compilers/...
- http://www.craftinginterpreters.com/
Blog posts:
- An Intro to Compilers (https://nicoleorchard.com/blog/compilers) and the accompanying Hacker news comments (https://news.ycombinator.com/item?id=15005031)
- Resources for Amateur Compiler Writers (https://c9x.me/compile/bib/)
Other resources:
- Tweet (https://twitter.com/munificentbob/status/901543375945388032) by Bob Nystrom (works on Dart VM and creator of Crafting Interpreters) -
- Wren (http://wren.io/): another project by Bob Nystrom, a scripting language written in C with beautifully documented code (I recommend checking it out on GitHub (https://github.com/munificent/wren))
- Ask HN: Resources for building a programming language? (https://news.ycombinator.com/item?id=15171238)
- Mal – Make a Lisp, in 68 languages (https://news.ycombinator.com/item?id=15226110)
Your comment made me do a quick Google for "Awesome Compilers"
Sure enough: https://github.com/aalhour/awesome-compilers
(I didn't check if the links posted here are in the awesome-compilers repo though.)
Edit: I also want to thank OP for continuing part 2. I didn't read part 1 completely because I figured it had a chance to be an abandoned blog post series. Keep it up OP!
Markup ate your Wren source link [1].
It has been unmaintained for a while now, but it's still good as a starting point.
Interestingly enough it's a spin-off of a code submission for winning the international obfuscated C code contest (http://www.ioccc.org/).
Original code (covering just a subset of C) can be found here: https://bellard.org/otcc/
http://lists.nongnu.org/archive/html/tinycc-devel/2017-05/ms...
This is an important result for activities such as Diverse Double-Compiling (a response to the Trusting Trust attack), and as part of the exciting work being done towards bootstrapping a modern Linux environment from source and a hex/assembly base:
I was actually expecting the "classic" x86 idiom for !, which also happens to be 3 instructions, but is slightly shorter and likely faster than the sequence presented:
neg eax
sbb eax, eax
inc eax
As a bonus, it also works in 16-bit mode (using the 16-bit registers) on everything back to the 8086, since SETcc is 386+, and given that I've seen it in early DOS compiler output, this neg/sbb/inc idiom has likely been known for a very long time. Figuring out how it works is left as an exercise for the reader ;-) mov eax, 0
will be handled during register renaming and not actually issued. It will also eliminate the partial dependency of SETE on the other bits of EAX.It's also worth noting that his compiler creates an intermediate AST (As any sane compiler should), so it's really not that hard to write multiple backends if he wanted.
AST are better suitable for the frontend, and even then, they only became a thing after we started having tons of RAM available.
That said, if you want to do something more advanced or use or use something better then a basic AST, I agree go for it. But if you're actually writing the compiler for a project that isn't just a toy or as a learning experience, you're almost definitely better off just building a frontend on an existing platform like LLVM.
Besides, IR has always been around, it is a requirement for many optimization algorithms.
It was a really fun project, and I learned a lot from it.