10 GCC Extensions
The CIL parser handles most of the gcc
and compiles them to CIL. The following extensions are not handled (note that
we are able to compile a large number of programs, including the Linux kernel,
without encountering these):
Nested function definitions.
- Constructing function calls.
- Naming an expression’s type.
- Complex numbers
- Hex floats
- Subscripts on non-lvalue arrays.
- Forward function parameter declarations
The following extensions are handled, typically by compiling them away:
Attributes for functions, variables and types. In fact, we have a clear
specification (see Section 6.4) of how attributes are interpreted. The
specification extends that of gcc.
- Old-style function definitions and prototypes. These are translated to
- Locally-declared labels. As part of the translation to CIL, we generate
new labels as needed.
- Labels as values and computed goto. This allows a program to take the
address of a label and to manipulate it as any value and also to perform a
computed goto. We compile this by assigning each label whose address is taken
a small integer that acts as its address. Every computed goto in the body
of the function is replaced with a switch statement. If you want to invoke
the label from another function, you are on your own (the gcc
documentation says the same.)
- Generalized lvalues. You can write code like (a, b) += 5 and it gets
translated to CIL.
- Conditionals with omitted operands. Things like x ? : y are
translated to CIL.
- Double word integers. The type long long and the LL suffix on
constants is understood. This is currently interpreted as 64-bit integers.
- Local arrays of variable length. These are converted to uses of
alloca, the array variable is replaced with a pointer to the allocated
array and the instances of sizeof(a) are adjusted to return the size of
the array and not the size of the pointer.
- Non-constant local initializers. Like all local initializers these are
compiled into assignments.
- Compound literals. These are also turned into assignments.
- Designated initializers. The CIL parser actually supports the full ISO
syntax for initializers, which is more than both gcc and MSVC. I
(George) think that this is the most complicated part of the C language and
whoever designed it should be banned from ever designing languages again.
- Case ranges. These are compiled into separate cases. There is no code
duplication, just a larger number of case statements.
- Transparent unions. This is a strange feature that allows you to define
a function whose formal argument has a (tranparent) union type, but the
argument is called as if it were the first element of the union. This is
compiled away by saying that the type of the formal argument is that of the
first field, and the first thing in the function body we copy the formal into
- Inline assembly-language. The full syntax is supported and it is carried
as such in CIL.
- Function names as strings. The identifiers __FUNCTION__ and
__PRETTY_FUNCTION__ are replaced with string literals.
- Keywords typeof, alignof, inline are supported.