Working with functions and control flow graphs

Many of the plugin events are called for each function within the source code being compiled. Each time, the plugin passes a gcc.Function instance as a parameter to your callback, so that you can work on it.

You can get at the control flow graph of a gcc.Function via its cfg attribute. This is an instance of gcc.Cfg.

class gcc.Function

Wrapper around one of GCC’s struct function *

cfg

An instance of gcc.Cfg for this function (or None during early passes)

decl

The declaration of this function, as a gcc.FunctionDecl

local_decls

List of gcc.VarDecl for the function’s local variables. It does not contain arguments; for those see the arguments property of the function’s decl.

Note that for locals with initializers, initial only seems to get set on those local_decls that are static variables. For other locals, it appears that you have to go into the gimple representation to locate assignments.

start

The gcc.Location of the beginning of the function

end

The gcc.Location of the end of the function

funcdef_no

Integer: a sequence number for profiling, debugging, etc.

class gcc.Cfg

A gcc.Cfg is a wrapper around GCC’s struct control_flow_graph.

basic_blocks

List of gcc.BasicBlock, giving all of the basic blocks within this CFG

entry

Instance of gcc.BasicBlock: the entrypoint for this CFG

exit

Instance of gcc.BasicBlock: the final one within this CFG

get_block_for_label(labeldecl)

Given a gcc.LabelDecl, get the corresponding gcc.BasicBlock

You can use gccutils.cfg_to_dot to render a gcc.Cfg as a graphviz diagram. It will render the diagram, showing each basic block, with source code on the left-hand side, interleaved with the “gimple” representation on the right-hand side. Each block is labelled with its index, and edges are labelled with appropriate flags.

For example, given this sample C code:

int
main(int argc, char **argv)
{
    int i;

    printf("argc: %i\n", argc);

    for (i = 0; i < argc; i++) {
        printf("argv[%i]: %s\n", argv[i]);
    }

    helper_function();

    return 0;
}

then the following Python code:

dot = gccutils.cfg_to_dot(fun.cfg)
gccutils.invoke_dot(dot)

will render a CFG bitmap like this:

image of a control flow graph
class gcc.BasicBlock

A gcc.BasicBlock is a wrapper around GCC’s basic_block type.

index

The index of the block (an int), as seen in the cfg_to_dot rendering.

preds

The list of predecessor gcc.Edge instances leading into this block

succs

The list of successor gcc.Edge instances leading out of this block

phi_nodes

The list of gcc.GimplePhi phoney functions at the top of this block, if appropriate for this pass, or None

gimple

The list of gcc.Gimple instructions, if appropriate for this pass, or None

rtl

The list of gcc.Rtl expressions, if appropriate for this pass, or None

class gcc.Edge

A wrapper around GCC’s edge type.

src

The source gcc.BasicBlock of this edge

dest

The destination gcc.BasicBlock of this edge

true_value

Boolean: True if this edge is taken when a gcc.GimpleCond conditional is true, False otherwise

false_value

Boolean: True if this edge is taken when a gcc.GimpleCond conditional is false, False otherwise

complex

Boolean: True if this edge is “special” e.g. due to exception-handling, or some other kind of “strange” control flow transfer, False otherwise