On Mon, 2013-09-30 at 15:49 +0200, Basile Starynkevitch wrote: > Hello, > > I want to insert, thru a plugin, a new IPA pass which won't change any > internal representation but will just count Gimples and functions at the IPA > level. > > (for what it is worth, the plugin is MELT http://gcc-melt.org/ > and the IPA pass is coded in MELT; but we can safely pretend > all this is C++ code - which in fact it is, > since MELT generates C++ code). > > > BTW, -fdump-passes show me notably: > > > tree-cfg : ON > *warn_function_return : ON > tree-ompexp : OFF > *build_cgraph_edges : ON > *free_lang_data : ON > ipa-visibility : ON > ipa-early_local_cleanups : ON > > I have some issues finding the right place for such a pass. I was thinking of > passing > as the reference_pass_name of some struct register_pass_info either the > "ipa-visibility" string or the "visibility" string, but somehow that does not > work. > > It is a pity that, AFAIK, a plugin cannot insert its pass in front of > the all_small_ipa_passes (the variable inside passes.c) - or of the > all_regular_ipa_passes; it would be > nice if we had some plugin API for such things. What do you think?
I had a go at implementing this using the python plugin, and I was successful: it worked for me (with gcc 4.7.2 fwiw) as a SIMPLE_IPA_PASS, registering before "*free_lang_data", or as an IPA_PASS, registering before "whole-program". I'm attaching the script I wrote, though obviously it will need translating from Python to MELT. Hope this is helpful. Here's the output: it's tallying the kinds of gimple statements since, by function, within "demo.c": $ LD_LIBRARY_PATH=gcc-c-api ./gcc-with-python show-stats.py demo.c -I/usr/include/python2.7 -c make_a_list_of_random_ints_badly: [(<type 'gcc.GimpleAssign'>, 6), (<type 'gcc.GimpleCall'>, 5), (<type 'gcc.GimpleCond'>, 2), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] buggy_converter: [(<type 'gcc.GimpleAssign'>, 6), (<type 'gcc.GimpleCall'>, 1), (<type 'gcc.GimpleCond'>, 1), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] kwargs_example: [(<type 'gcc.GimpleAssign'>, 10), (<type 'gcc.GimpleCall'>, 1), (<type 'gcc.GimpleCond'>, 1), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] too_many_varargs: [(<type 'gcc.GimpleAssign'>, 7), (<type 'gcc.GimpleCall'>, 1), (<type 'gcc.GimpleCond'>, 1), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] not_enough_varargs: [(<type 'gcc.GimpleAssign'>, 5), (<type 'gcc.GimpleCall'>, 1), (<type 'gcc.GimpleCond'>, 1), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] socket_htons: [(<type 'gcc.GimpleAssign'>, 7), (<type 'gcc.GimpleCall'>, 3), (<type 'gcc.GimpleCond'>, 1), (<type 'gcc.GimpleReturn'>, 1), (<type 'gcc.GimpleLabel'>, 1)] > BTW, I also have a suggestion. We have some (relatively new) code > (perhaps from 4.8) which suggest names in error messages when an > identifier is misspelled.. > > Can't we use the same code (or at least same algorithm) to suggest > a pass name when given a mispelled pass name from a plugin? > > > In general, I find that we are a bit lacking documentation about where > and how a plugin can insert its own passes. Agreed. FWIW I find this map very helpful for this kind of thing: https://gcc-python-plugin.readthedocs.org/en/latest/tables-of-passes.html Perhaps it can somehow be integrated into GCC's own documentation. > Regards. > > PS. See also http://gcc.gnu.org/ml/gcc/2010-11/msg00638.html Hope this is constructive Dave
from collections import Counter import gcc # We'll implement this as a custom pass, to be called directly before # 'whole-program' # See https://gcc-python-plugin.readthedocs.org/en/latest/tables-of-passes.html # for a map showing how GCC's passes (actually for GCC 4.6) class CountingPass(gcc.SimpleIpaPass): def execute(self): for node in gcc.get_callgraph_nodes(): # Tally gimple statements by type: stmt_kinds = Counter() fun = node.decl.function if fun: for bb in fun.cfg.basic_blocks: if bb.gimple: for stmt in bb.gimple: stmt_kinds[type(stmt)] += 1 print('%s: %s' % (fun.decl.name, stmt_kinds.most_common(5))) ps = CountingPass(name='counting-pass') ps.register_before('*free_lang_data') # This also works registering before "whole-program", but one has to change the # base class to a gcc.IpaPass, rather than a gcc.SimpleIpaPass