The purpose of GENERIC is simply to provide a language-independent way of
representing an entire function in trees. To this end, it was necessary to
add a few new tree codes to the back end, but most everything was already
there. If you can express it with the codes in gcc/tree.def
, it's
GENERIC.
Early on, there was a great deal of debate about how to think about
statements in a tree IL. In GENERIC, a statement is defined as any
expression whose value, if any, is ignored. A statement will always
have TREE_SIDE_EFFECTS
set (or it will be discarded), but a
non-statement expression may also have side effects. A
CALL_EXPR
, for instance.
It would be possible for some local optimizations to work on the
GENERIC form of a function; indeed, the adapted tree inliner works
fine on GENERIC, but the current compiler performs inlining after
lowering to GIMPLE (a restricted form described in the next section).
Indeed, currently the frontends perform this lowering before handing
off to tree_rest_of_compilation
, but this seems inelegant.
If necessary, a front end can use some language-dependent tree codes in its GENERIC representation, so long as it provides a hook for converting them to GIMPLE and doesn't expect them to work with any (hypothetical) optimizers that run before the conversion to GIMPLE. The intermediate representation used while parsing C and C++ looks very little like GENERIC, but the C and C++ gimplifier hooks are perfectly happy to take it as input and spit out GIMPLE.