Example scripts — gcc-python-plugin 0.16 documentation (original) (raw)
There are various sample scripts located in the examples subdirectory.
Once you’ve built the plugin (with make), you can run them via:
$ ./gcc-with-python examples/NAME-OF-SCRIPT.py test.c
show-docs.py¶
A trivial script to make it easy to read the builtin documentation for the gcc API:
$ ./gcc-with-python examples/show-docs.py test.c
with this source:
giving output:
Help on built-in module gcc:
NAME gcc
FILE (built-in)
CLASSES builtin.object BasicBlock Cfg Edge Function Gimple (truncated)
show-passes.py¶
You can see the passes being executed via:
$ ./gcc-with-python examples/show-passes.py test.c
This is a simple script that registers a trivial callback:
Sample python script, to be run by our gcc plugin
Show all the passes that get executed
import gcc
def my_pass_execution_callback(*args, **kwargs): (optpass, fun) = args print(args)
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION, my_pass_execution_callback)
Sample output, showing passes being called on two different functions (mainand helper_function):
(gcc.GimplePass(name='*warn_unused_result'), gcc.Function('main')) (gcc.GimplePass(name='omplower'), gcc.Function('main')) (gcc.GimplePass(name='lower'), gcc.Function('main')) (gcc.GimplePass(name='eh'), gcc.Function('main')) (gcc.GimplePass(name='cfg'), gcc.Function('main')) (gcc.GimplePass(name='*warn_function_return'), gcc.Function('main')) (gcc.GimplePass(name='*build_cgraph_edges'), gcc.Function('main')) (gcc.GimplePass(name='*warn_unused_result'), gcc.Function('helper_function')) (gcc.GimplePass(name='omplower'), gcc.Function('helper_function')) (gcc.GimplePass(name='lower'), gcc.Function('helper_function')) (gcc.GimplePass(name='eh'), gcc.Function('helper_function')) (gcc.GimplePass(name='cfg'), gcc.Function('helper_function')) [...truncated...]
show-gimple.py¶
A simple script for viewing each function in the source file after it’s been converted to “GIMPLE” form, using GraphViz to visualize the control flow graph:
$ ./gcc-with-python examples/show-gimple.py test.c
It will generate a file test.png for each function, and opens it in an image viewer.
The Python code for this is:
Show the GIMPLE form of each function, using GraphViz
import gcc from gccutils import get_src_for_loc, cfg_to_dot, invoke_dot
We'll implement this as a custom pass, to be called directly after the
builtin "cfg" pass, which generates the CFG:
class ShowGimple(gcc.GimplePass): def execute(self, fun): # (the CFG should be set up by this point, and the GIMPLE is not yet # in SSA form) if fun and fun.cfg: dot = cfg_to_dot(fun.cfg, fun.decl.name) # print dot invoke_dot(dot, name=fun.decl.name)
ps = ShowGimple(name='show-gimple') ps.register_after('cfg')
show-ssa.py¶
This is similar to show-gimple.py, but shows each function after the GIMPLE has been converted to Static Single Assignment form (“SSA”):
$ ./gcc-with-python examples/show-ssa.py test.c
As before, it generates an image file for each function and opens it in a viewer.
The Python code for this is:
Sample python script, to be run by our gcc plugin
Show the SSA form of each function, using GraphViz
import gcc from gccutils import get_src_for_loc, cfg_to_dot, invoke_dot
A custom GCC pass, to be called directly after the builtin "ssa" pass, which
generates the Static Single Assignment form of the GIMPLE within the CFG:
class ShowSsa(gcc.GimplePass): def execute(self, fun): # (the SSA form of each function should have just been set up) if fun and fun.cfg: dot = cfg_to_dot(fun.cfg, fun.decl.name) # print(dot) invoke_dot(dot, name=fun.decl.name)
ps = ShowSsa(name='show-ssa') ps.register_after('ssa')
show-callgraph.py¶
This simple script sends GCC’s interprocedural analysis data through GraphViz.
$ ./gcc-with-python examples/show-callgraph.py test.c
It generates an image file showing which functions call which other functions, and opens it in a viewer.
The Python code for this is:
Sample python script, to be run by our gcc plugin
Show the call graph (interprocedural analysis), using GraphViz
import gcc from gccutils import callgraph_to_dot, invoke_dot
In theory we could have done this with a custom gcc.Pass registered
directly after "*build_cgraph_edges". However, we can only register
relative to passes of the same kind, and that pass is a
gcc.GimplePass, which is called per-function, and we want a one-time
pass instead.
So we instead register a callback on the one-time pass that follows it
def on_pass_execution(p, fn): if p.name == '*free_lang_data': # The '*free_lang_data' pass is called once, rather than per-function, # and occurs immediately after "*build_cgraph_edges", which is the # pass that initially builds the callgraph # # So at this point we're likely to get a good view of the callgraph # before further optimization passes manipulate it dot = callgraph_to_dot() invoke_dot(dot)
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION, on_pass_execution)