A Gcc Frontend

When writing the gccgo frontend I had to figure out how to write a new gcc frontend. This is a largely undocumented procedure. Unfortunately, I did not take notes as I went along. However, here are some retrospective comments.

Every gcc frontend needs a set of language hooks. This is done by including "langhooks-def.h" and writing struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;. The specific language hooks are defined via various LANG_HOOKS_xxx macros.

Some language hooks are required even though for a language like Go there is nothing for them to do: LANG_HOOKS_GLOBAL_BINDINGS_P, LANG_HOOKS_PUSHDECL, LANG_HOOKS_GETDECLS. Also LANG_HOOKS_TYPE_FOR_MODE and LANG_HOOKS_TYPE_FOR_SIZE must be defined and must do something reasonable. The LANG_HOOKS_INIT function must call some functions: build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, build_common_builtin_nodes. It must also set the global variable void_list_node. As far as I know all these steps are required and none of them are documented. The LANG_HOOKS_POST_OPTIONS hook must set flag_excess_precision_cmdline.

The main language hook is LANG_HOOKS_PARSE_FILE. It will find the input file names in the global variables in_fnames and num_in_fnames. At that point the frontend can take over and do the actual parsing and initial compilation.

After LANG_HOOKS_PARSE_FILE creates a complete parse tree (in a global variable) and returns, the rest of the work is done by LANG_HOOKS_WRITE_GLOBALS. The gccgo frontend generates GENERIC, although these days it could be modified to generate GIMPLE instead. This basically means creating appropriate DECL nodes for all the global types, variables, and functions. For a function, the frontend must create a cfun structure via push_struct_function or similar, and it must set current_function_decl. The frontend must not only create the FUNCTION_DECL, it must fill in the DECL_RESULT field with a RESULT_DECL. After creating the GENERIC or GIMPLE, it should call cgraph_finalize_function.

After all the functions have been finalized and the global variables created, the frontend must call cgraph_finalize_compilation_unit. That is where the middle-end really takes over and generates code. The frontend must finish by calling wrapup_global_declarations, check_global_declarations, and emit_debug_global_declarations.

The above is probably slightly inaccurate, and I’m sure I’ve left out some details. And, of course, the frontend interfaces changes with each new gcc release. However, if you are interested in writing a gcc frontend, I hope this will give you a start.

2 Comments »

  1. Samuel Tardieu said,

    December 9, 2009 @ 7:11 am

    As I understand it, Go has been primarily designed for server-side applications. Servers usually use mainstream processors, which are well supported by LLVM. And LLVM documentation to create new front-ends is better than GCC one.

    So why did you choose GCC as a back-end rather than LLVM? Is that because you were more familiar with GCC infrastructure?

  2. Ian Lance Taylor said,

    December 9, 2009 @ 10:42 pm

    Yes. I have long experience with gcc and none with LLVM.

RSS feed for comments on this post · TrackBack URI

Leave a Comment

You must be logged in to post a comment.