Table of Contents
Creating a GCC Pass
These are rough notes only! Unfortunately, this part of the GCC codebase is poorly documented at this point in time.
Structure of a Pass
GCC passes are used to transform code. Initially, the input source code is transformed into GLIMPSE, then into GIMPLE, then into RTL, and finally into assembly for the target system.
Passes are defined in the gcc
subdirectory. (It is important to note that both the top-level directory and the gcc subdirectory share the gcc
name, so we're specifically referring to the second-level directory here!).
Passes are controlled by the pass manager, which handles sequencing of passes, creation of dump files, and various setup/cleanup operations.
Pass Definition
The pass manager uses the file passes.def
to define the order in which passes are called. This file is processed by the script gen-pass-instances.awk
to create the file pass-instances.def
, which is then subject to macro expansion (using macros defined in pass_manager.h
) and included into passes.cc
.
The macros used in this file permit both passes and sub-passes to be defined.
The most basic way to add a new pass into this file is to define NEXT_PASS (name_of_pass)
to insert a pass at a specific point in the pass list, or as a sub-pass within a pass group.
Pass Code
Each pass provides a C++ source file which provides:
- A
pass_data
structure which defines the pass details (defined intree-pass.h
); - A class which defines a
gimple_opt_pass
and includes the public methodsgate
andexecute
.- The
gate
method controls whether the pass is active. It can consider multiple factors, including command-line arguments, source language, and target. This method returns a boolean. - The
execute
method executes the pass. It accepts a pointer to a function object and will be called once for each function in the unit being compiled (which is not always what you want!).
- A method in the anon namespace named
make_pass_name
which returns a pointer to thegimple_opt_pass
described above.
Build System Changes
In order to cause a new pass to be built and used, after having added the source code for your pass and adding the pass to passes.def
, you must:
- Add the object file for your pass to the file
Makefile.in
in theOBJS =
(object files) section. For example, if your source file istree-footest.cc
, addtree-footest.o
to the OBJS list. - Add
make_pass_name
to thetree-pass.h
header file.
Important: you must re-create the Makefile
in the gcc subdirectory of your build tree in order for changes in the Makefile.in
to be recognized – the build system will not automatically detect changes to the Makefile.in
. The easiest way to do this without rebuilding everything is to delete the Makefile
in the gcc subdirectory of your build tree. You do not need to do this unless you have made changes to the Makefile.in
.
Tools for Constructing Passes
Macros
There are a number of macros defined in cgraph.h
which may be used to walk through the callgraph of the IR tree:
- FOR_EACH_ALIAS(NODE, ALIAS)
- FOR_EACH_SYMBOL(node)
- FOR_EACH_DEFINED_SYMBOL(node)
- FOR_EACH_VARIABLE(node)
- FOR_EACH_STATIC_INITIALIZER(node)
- FOR_EACH_DEFINED_VARIABLE(node)
- FOR_EACH_DEFINED_FUNCTION(node)
- FOR_EACH_FUNCTION(node)
- FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node)
There are also a number of macros defined in basic-block.h
which may be used to interate through the basic blocks of a function:
- FOR_EACH_BB_FN(BB, FN)
- FOR_EACH_BB_REVERSE_FN(BB, FN)
- FOR_EACH_EDGE(EDGE,ITER,EDGE_VEC)
Gimple Interators
There are a group of functions defined in gimple-iterator.h
which may be used to constuct for( , , )
loops that iterate through gimple statements. For example:
for ( gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next(&gsi) )
Dump Files
- Dump files are created for all passes where the name in the
pass_data
structure does not start with an astrisk (*). - The dump file will, by default, contain a dump of the IR at the end of your pass.
- You may add additional text into the file by accessing the
dump_file
file descriptor like this:
if (dump_file) { fprintf (dump_file, ... ); }
Resources
This section will be extended – watch for changes.