====== 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 in ''tree-pass.h'');
- A class which defines a ''gimple_opt_pass'' and includes the public methods ''gate'' and ''execute''.
- 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 the ''gimple_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 the ''OBJS ='' (object files) section. For example, if your source file is ''tree-footest.cc'', add ''tree-footest.o'' to the OBJS list.
* Add ''make_pass_//name//'' to the ''tree-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.
==== On this Wiki ====
* [[Building GCC]]
==== On the Web ====
* [[https://gcc.gnu.org/onlinedocs/gccint/|GCC Internals Manual]]