Writing a GCC Front End

Language designers rejoice! Now it's easier to put a front end for your language onto GCC.
Expr

Many kinds of expr trees are available that represent the various kinds of expressions in a program. These are similar to C expressions but are more general in some ways. For instance, trees do not distinguish between if statements and conditional expressions—both are represented by a COND_EXPR, with the only difference being that an if statement has void type. Here's how we can build an expression that adds our variable to itself:

tree addition = build2 (PLUS_EXPR, type_jchar, local, local);

Trees that represent statements are linked together using a special iterator API. Here is how we would chain together two statements, s1 and s2:


tree result = alloc_stmt_list ();
tree_stmt_iterator out = tsi_start (result);

tsi_link_after (&out, s1, TSI_CONTINUE_LINKING);
tsi_link_after (&out, s2, TSI_CONTINUE_LINKING);

// Now `result' holds the list of statements.

Other kinds of tree nodes exist; read tree.def and the manual for a more complete understanding. It also is possible for a front end to define its own tree codes; however, if you have your own AST, you should not need to do this.

The overall structure of the program you generate probably is going to resemble a translation unit decl, which would contain types, variables and functions.

Handoff

Once you've built the trees representing a function, a global variable or a type for which you want to generate debugging information, you need to pass the tree to the appropriate function to handle the rest of compilation. Three such functions are available at present: rest_of_decl_compilation handles compilation for a decl node, cgraph_finalize_function handles compilation for a function and rest_of_type_compilation handles compilation for a type.

Debugging

Although GCC has a fair number of internal consistency checks, it still is too easy to provoke crashes in code that are unrelated to your front end. In many cases, you can move up the stack, printing whatever trees are being manipulated, until you find some discrepancy caused by incorrect tree generation. This technique requires surprisingly little general GCC knowledge in order to effectively debug your code.

GCC has some handy debug functionality. In the debugger you can call the debug_tree function to print a tree. You also can use the -fdump-tree family of command-line options to print trees after various passes have been run.

Experience

My experience writing gcjx has been that lowering its strongly typed intermediate representation to trees is quite simple. The tree back end to gcjx, one back end among several, represents roughly 10% of the total code of the compiler. Although unfinished, it currently weighs in at 6,000 lines of code (raw wc -l count)—around the same size as the bytecode back end. One inference to draw from this is if you already have a compiler, the task of attaching it to GCC can be accomplished easily.

As trees are high-level, I haven't looked at any RTL while writing this front end. I haven't spent any time at all thinking about or dealing with processor-specific issues. Unless your language has some esoteric requirements, this ought to hold for you as well.

The statically typed AST in gcjx is easily reused. Currently, there are four back ends, and I expect to write more later. For instance, it would be simple to build a back end that writes a cross-reference representation of the program to a database. Or, it would be possible to write a back end that walks the AST searching for typical errors, akin to the FindBugs program. This consideration would be even more compelling for languages, which, unlike Java, don't already have a wealth of analysis tools.

Future Directions

The process of writing a front end certainly could be made even easier. For instance, there is no need to require lang-specs.h. Instead, a front end could install a description file that the GCC driver would read at startup. Similarly, lang.opt probably could be dispensed with. With more work, it even would be possible to compile front ends separately from the rest of GCC.

Resources for this article: /article/8138.

Tom Tromey has been involved with free software since 1991 and has worked on many different programs. He currently is employed as an engineer at Red Hat, working on GCJ.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Incremental development of a gcc front end from source.

Joe Garvey's picture

Tom Tromey reported herein 2005...April 6th
"Writing the Driver
Currently GCC requires your front end to be visible at build time—there is no way to write a front end that is built separately and linked against an installed GCC. "

Has that situation change or is it still so that if I even change one variable declaration in a new frontend source , that the WHOLE (if only core) gcc would need to be rebuilt from sources?

Any idea of best resources for writing such a frontEnd?

Perl

dude's picture

For years the Perl compiler has always been "any day now".
I wonder how hard it would be make a perl front-end to GCC.

Actually since Perl 6 is to be translated into Parrot
you only need to make a Parrot front end.

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState