c4x86 - JIT compiler for x86 in 86 lines
github.com
github.com
Jack Crenshaw's "Let's build a compiler" tutorial series uses the same code generation method but with eax/edx (http://www.pp4s.co.uk/main/tu-trans-comp-jc-intro.html ); not sure if he was the first one to come up with it, however. Incidentally, I think his tutorial series is one of the best ones I've read for understanding how compilers work, even better than all the "traditional" literature like the Dragon Book.
The other article that'll probably be very helpful for those understanding how the rest of this compiler works is http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm#climbing which describes the "precedence climbing" way of parsing expressions.
Compilers are often thought of as "magic" that only very few people can understand, but I don't think that has to be true in general. While "production-quality" compilers like gcc are certainly very complex, the essence of a compiler is really quite simple. However, this wouldn't be the impression one gets by reading a lot of the compiler books out there --- the heavy emphasis on theory in the majority of them has a somewhat obfuscating effect. They also tend to focus a lot more on compiler-compilers (Lex, Yacc) and more general parsing techniques like LR, while spending very little on the simple methods of syntax-directed translation and recursive descent. AFAIK precedence-climbing is not even described in the Dragon Book.
Crenshaw's series turned me off when the first parser he showed would incorrectly accept incorrect inputs, and it could've been done rightly just as easily -- or so it looked to me. I did not test it or read further, and since it's so often recommended I seem to've missed something.
P.S. precedence climbing in Python: https://github.com/darius/sketchbook/blob/master/parsing/pre... . Pratt's top-down operator precedence parsing is essentially an object-oriented way to express the same algorithm: https://github.com/darius/sketchbook/blob/master/parsing/pra...
Totally agree. I was interested in how compilers work when in high school - long before I heard of the dragon book and had no idea how to even start on making a parser and code generator.
When he walked through a basic recursive descent parser, it was like a light bulb went off over my head - such a simple and elegant solution to a otherwise seemingly tricky problem.
Looks like this is a fork of that.
P.S. Otherwise, it is ready to run itself, work in progress.
Was looking into changing the order of arguments to go the right way 'round. Also changing address refs to be PC-relative, to avoid the relocation phase. Seems pretty straightforward.
Now I see that the first argument can be NULL, that approach is feasible.
How different would the implementation be for x64? Would it primarily be a matter of translating opcodes and calling conventions? For example, pop ecx is 59 [1], and on x64 it looks like it would be pop rcx, which is also 59 [2][3].
[1] - http://sparksandflames.com/file/x86InstructionChart.html
[2] - https://defuse.ca/online-x86-assembler.htm#disassembly
[3] - http://msdn.microsoft.com/en-us/library/windows/hardware/ff5...
But still, trying to fit the x64 version in 64 lines is probably going to be the harder problem. ;-)
I took an hour to read through it and comment the hell out of it, and it was some of the most pleasant reading I've done all year. I really, really like this code.
#!/usr/bin/tcc -run
Or does doing that require weird stdin-related Magic?