The back end lower half originated in the NYU / Bell Labs MLRISC project .
A different lower half is generated for each supported architecture, using generics to share common code.
For clarity and simplicity, the following will discuss only the intel32 back end; The others are similar.
In a general sense, the root of the lower half is
This is a simple wrapper supplying platform-appropriate arguments to low_end_toplevel_loop_g, which is defined in
This contains the function compile which is the the toplevel driver for the backend, selecting which optimization phases to run and in what order per user options or else compiled-in defaults.
The lion’s share of the detail work is delegated to translate_fate_passing_style_to_binary_g, which is defined in
whose principal export is the function translate_fate_passing_style_to_binary which encapsulates the complete process of compiling FPS intermediate code all the way down to native machine code for the intel32 architecture. At runtime, this function gets called from translate_anormcode_to_binary in
this constituting the runtime transition from the back end upper half to lower half.
The original and still primary code representation used in the back end is a simple register transfer level language defined in
A (currently unused) high-level intermediate representation API is defined in
A (also currently unused) control-flow graph representation is defined in:
Later an (again, currently unused) additional SSA ("Static Single Assignment") representation was added, defined in
SSA optimizations have their own driver, implemented in
which is currently nowhere invoked.