gbforth includes a Forth cross-compiler. The cross-compiler is missing many optimizations and functionality but it is quite easy to work with. This document gives an overview of how to improve it.
The entrypoint of the gbforth compiler can be found at
This file implements the equivalent of the “outer interpreter” in Forth. In
particular, the word
x] (cross-version of
]), will switch to cross-compiling
mode, reading words and cross-compiling them. Note that this does not reuse the
host Forth outer interpreter.
gbforth compiles words into an intermediate representation (IR). This represents the code as a graph of IR components, each of them being a sequence of IR nodes (e.g: CALL node to call another word), corresponding to the traditional basic blocks in compiler terminology. Control flow like conditionals and loops are implemented as links between those IR components.
This intermediate representation are saved together with cross-words, as defined in xname.fs. However, the code is not actually compiled into assembler in the ROM just yet.
On the intermediate representation, some optimizations can take place. There are no optimizations in place yet, but you can see an example of how tail-call optimization could be implemented.
Once the whole game source code has been processed, we have a collection of
xnames, linked to IR or code primitives. In order to produce the ROM, the
is invoked on the special word
main. This, in turn, will invoke recursively
the code generator for any word that is required by main, and so on. This means
that only words that you actually use are included in the ROM, saving
considerable space. There are other ways of forcing a word code to be generated,
for example, trying to get its address (
' dup constant dup-addr).
As a consequence, we are free to define as many words in libraries as we like without affecting users that are not using them.
Playing with the compiler
You can see the intermediate representation of a word with the word
There is a file
src/compiler/debug.fs which you can change easily and run it
gforth src/compiler/debug.fs while you make changes to the compiler.