commit facb66fd92715f106ca1a693426c46418856ab30
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jul 27 14:47:58 2011 -0400
Improvements to the example scripts
Move the two example scripts below a new "examples" script, and clean them
up
Add:
examples/show-gimple.py
examples/show-passes.py
Document the example scripts
Makefile | 2 +-
docs/basics.rst | 37 +++++++++-
docs/examples.rst | 125 +++++++++++++++++++++++++++++++
docs/gcc-overview.rst | 4 +-
show-docs.py => examples/show-docs.py | 0
show-ssa.py => examples/show-gimple.py | 24 ++----
show-docs.py => examples/show-passes.py | 10 ++-
show-ssa.py => examples/show-ssa.py | 19 +----
8 files changed, 183 insertions(+), 38 deletions(-)
---
diff --git a/Makefile b/Makefile
index 3b85d3a..c378595 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-suite: plugin
$(PYTHON) run-test-suite.py
show-ssa: plugin
- ./gcc-with-python show-ssa.py test.c
+ ./gcc-with-python examples/show-ssa.py test.c
html: docs/tables-of-passes.rst docs/passes.svg
cd docs && $(MAKE) html
diff --git a/docs/basics.rst b/docs/basics.rst
index e84fd09..5a2b63e 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -86,7 +86,7 @@ internals of each function in `test.c` (within its SSA representation):
.. code-block:: bash
- ./gcc-with-python show-ssa.py test.c
+ ./gcc-with-python examples/show-ssa.py test.c
Most of the rest of this document describes the Python API visible for
@@ -216,7 +216,7 @@ Currently useful callback events
.. py:data:: gcc.PLUGIN_PASS_EXECUTION
- Called when GCC runs one of its passes on a function
+ Called when GCC is about to run one of its passes.
Arguments passed to the callback are:
@@ -227,6 +227,39 @@ Currently useful callback events
and each can be invoked zero or more times per function (in the code being
compiled)
+ More precisely, some passes have a "gate check": the pass first checks a
+ condition, and only executes if the condition is true.
+
+ Any callback registered with `gcc.PLUGIN_PASS_EXECUTION` will get called
+ if this condition succeeds.
+
+ The actual work of the pass is done after the callbacks return.
+
+ In pseudocode::
+
+ if pass.has_gate_condition:
+ if !pass.test_gate_condition():
+ return
+ invoke_all_callbacks()
+ actually_do_the_pass()
+
+ For passes working on individual functions, all of the above is done
+ per-function.
+
+ To connect to a specific pass, you can simply add a conditional based on the
+ name of the pass::
+
+ def my_callback(ps, fun):
+ if ps.name != '*warn_function_return':
+ # Not the pass we want
+ return
+ # Do something here
+ print(fun.decl.name)
+
+ gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
+ my_callback)
+
+
.. py:data:: gcc.PLUGIN_PRE_GENERICIZE
Arguments passed to the callback are:
diff --git a/docs/examples.rst b/docs/examples.rst
index eb8251e..c31fea5 100644
--- a/docs/examples.rst
+++ b/docs/examples.rst
@@ -46,3 +46,128 @@ Here's the expected output:
Notice how the call to `printf` has already been optimized into a call
to `__builtin_puts`.
+
+Example scripts
+===============
+
+There are various sample scripts located in the `examples` subdirectory.
+
+Once you've built the plugin (with `make`), you can run them via:
+
+ .. code-block:: bash
+
+ $ ./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:
+
+ .. code-block:: bash
+
+ $ ./gcc-with-python examples/show-docs.py test.c
+
+ with this source:
+
+ .. literalinclude:: ../examples/show-docs.py
+ :lines: 17-
+ :language: python
+
+ 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:
+
+ .. code-block:: bash
+
+ $ ./gcc-with-python examples/show-passes.py test.c
+
+This is a simple script that registers a trivial callback:
+
+ .. literalinclude:: ../examples/show-passes.py
+ :lines: 17-
+ :language: python
+
+Sample output, showing passes being called on two different functions (`main`
+and `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:
+
+ .. code-block:: bash
+
+ $ ./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.
+
+ .. figure:: sample-gimple-cfg.png
+ :scale: 50 %
+ :alt: image of a control flow graph in GIMPLE form
+
+The Python code for this is:
+
+ .. literalinclude:: ../examples/show-gimple.py
+ :lines: 19-
+ :language: python
+
+`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"):
+
+ .. code-block:: bash
+
+ $ ./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.
+
+.. figure:: sample-gimple-ssa-cfg.png
+ :scale: 50 %
+ :alt: image of a control flow graph in GIMPLE SSA form
+
+The Python code for this is:
+
+ .. literalinclude:: ../examples/show-ssa.py
+ :lines: 17-
+ :language: python
diff --git a/docs/gcc-overview.rst b/docs/gcc-overview.rst
index 84a361a..014d3ae 100644
--- a/docs/gcc-overview.rst
+++ b/docs/gcc-overview.rst
@@ -99,7 +99,7 @@ It's far easier to see the GIMPLE using:
.. code-block:: bash
- ./gcc-with-python show-gimple.py test.c
+ ./gcc-with-python examples/show-gimple.py test.c
which generates bitmaps showing the "control flow graph" of the functions in
the file, with source on the left-hand side, and GIMPLE on the right-hand side:
@@ -153,7 +153,7 @@ Here's our example function, after conversion to GIMPLE SSA:
.. code-block:: bash
- ./gcc-with-python show-ssa.py test.c
+ ./gcc-with-python examples/show-ssa.py test.c
.. figure:: sample-gimple-ssa-cfg.png
:scale: 50 %
diff --git a/show-docs.py b/examples/show-docs.py
similarity index 100%
copy from show-docs.py
copy to examples/show-docs.py
diff --git a/show-ssa.py b/examples/show-gimple.py
similarity index 58%
copy from show-ssa.py
copy to examples/show-gimple.py
index 7ede514..c4a6a9d 100644
--- a/show-ssa.py
+++ b/examples/show-gimple.py
@@ -15,29 +15,19 @@
# along with this program. If not, see
# <
http://www.gnu.org/licenses/>.
-# Sample python script, to be run by our gcc plugin (see "make test")
-# Show the SSA form of each function, using GraphViz
+# Sample python script, to be run by our gcc plugin
+# Show the GIMPLE form of each function, using GraphViz
import gcc
from gccutils import get_src_for_loc, cfg_to_dot, invoke_dot
def my_pass_execution_callback(*args, **kwargs):
- #print('my_pass_execution_callback was called: args=%r kwargs=%r' % (args,
kwargs))
- #help(args[0])
(optpass, fun) = args
- if not optpass.properties_required & (1<<5):
- return
- if fun:
- print('fun.cfg: %r' % fun.cfg)
- if fun.cfg:
- #print help(fun.cfg)
- print('fun.cfg.basic_blocks: %r' % fun.cfg.basic_blocks)
- print('fun.cfg.entry: %r' % fun.cfg.entry)
- print('fun.cfg.exit: %r' % fun.cfg.exit)
- print('fun.cfg.entry.succs: %r' % fun.cfg.entry.succs)
- print('fun.cfg.exit.preds: %r' % fun.cfg.exit.preds)
-
+ if optpass.name == '*warn_function_return':
+ # (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)
+ # print dot
invoke_dot(dot)
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
diff --git a/show-docs.py b/examples/show-passes.py
similarity index 72%
rename from show-docs.py
rename to examples/show-passes.py
index 29897cd..e083bde 100644
--- a/show-docs.py
+++ b/examples/show-passes.py
@@ -15,5 +15,13 @@
# along with this program. If not, see
# <
http://www.gnu.org/licenses/>.
+# Sample python script, to be run by our gcc plugin
+# Show all the passes that get executed
+
import gcc
-help(gcc)
+def my_pass_execution_callback(*args, **kwargs):
+ (optpass, fun) = args
+ print(args)
+
+gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
+ my_pass_execution_callback)
diff --git a/show-ssa.py b/examples/show-ssa.py
similarity index 63%
rename from show-ssa.py
rename to examples/show-ssa.py
index 7ede514..c289412 100644
--- a/show-ssa.py
+++ b/examples/show-ssa.py
@@ -15,27 +15,16 @@
# along with this program. If not, see
# <
http://www.gnu.org/licenses/>.
-# Sample python script, to be run by our gcc plugin (see "make test")
+# 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
def my_pass_execution_callback(*args, **kwargs):
- #print('my_pass_execution_callback was called: args=%r kwargs=%r' % (args,
kwargs))
- #help(args[0])
(optpass, fun) = args
- if not optpass.properties_required & (1<<5):
- return
- if fun:
- print('fun.cfg: %r' % fun.cfg)
- if fun.cfg:
- #print help(fun.cfg)
- print('fun.cfg.basic_blocks: %r' % fun.cfg.basic_blocks)
- print('fun.cfg.entry: %r' % fun.cfg.entry)
- print('fun.cfg.exit: %r' % fun.cfg.exit)
- print('fun.cfg.entry.succs: %r' % fun.cfg.entry.succs)
- print('fun.cfg.exit.preds: %r' % fun.cfg.exit.preds)
-
+ if optpass.name == 'veclower':
+ # (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)