This is the mail archive of the
mailing list for the GCC project.
Re: DECL_STRUCT_FUNCTION(cgraphnode->decl) == NULL when attempting Link-Time Optimization in plugin
On Mon, 2012-10-08 at 18:21 +0200, Richard Guenther wrote:
> On Mon, Oct 8, 2012 at 5:17 PM, David Malcolm <email@example.com> wrote:
> > I'm working on a static analysis extension to GCC via my
> > gcc-python-plugin 
> > The analysis is interprocedural (memory leak detection, as it happens).
> > I have it working on one translation unit at a time, and I'm attempting
> > to get it to work within Link Time Optimization so that it can see the
> > interactions of all of the functions within a program or library, but
> > I'm running what might be a bug (or I could be misunderstanding LTO).
> > I have my plugin working within lto1, using "-flto" and "-fplugin"; my
> > command line looks like:
> > $ gcc -fPIC -shared -flto -g
> > -fplugin=/home/david/coding/gcc-python/gcc-python/sm/python.so
> > -fplugin-arg-python-script=examples/show-lto-supergraph.py
> > tests/sm/lto/input-*.c --save-temps
> > lto1 appears to be invoked twice by gcc. The first time, there are two
> > passes:
> > IPA_PASS named "whole-program"
> > IPA_PASS named "inline"
> > and "in_lto_p" is true.
> > The second invocation has these passes, called per-function:
> > GIMPLE_PASS "*free_cfg_annotations"
> > GIMPLE_PASS "cplxlower0"
> > GIMPLE_PASS "optimized"
> > RTL_PASS "expand"
> > GIMPLE_PASS "*rest_of_compilation"
> > RTL_PASS "*init_function"
> > ...etc.., normal rest of compilation from RTL stage onwards
> > and "in_lto_p" is false.
> > I've attempted to wire in my interprocedural analysis as a new IPA pass
> > before or after "whole-program" and "inline" within the first invocation
> > of lto1. In each case it is able to walk the callgraph, and the
> > callgraph it sees appears to be correct: walking the linked list of
> > cgraph_nodes the various cgraph_edge and cgraph_node are as expected,
> > and for each cgraph_node, cgraph_node->decl is a non-NULL tree instance
> > of type FUNCTION_DECL (as expected); I'm able to generate a graphviz
> > rendering of the whole-program callgraph within lto1 from my plugin.
> > However, for every cgraph_node, the
> > DECL_STRUCT_FUNCTION(cgraph_node->decl) is (struct function*)NULL, which
> > thwarts my code's attempt to look up the CFG of each underlying function
> > and work on the underlying gimple.
> > Looking with eu-readelf at the .o files shows these lto sections are
> > present ("f" is the name of one of the functions that I'd like to access
> > the gimple CFG of):
> > $ eu-readelf -a input-f.o|grep lto
> > [ 5] .gnu.lto_.inline.c8904cb9a96e7417 PROGBITS 0000000000000000 0000006c 00000026 0 E 0 0 1
> > [ 6] .gnu.lto_f.c8904cb9a96e7417 PROGBITS 0000000000000000 00000092 00000164 0 E 0 0 1
> > [ 7] .gnu.lto_.cgraph.c8904cb9a96e7417 PROGBITS 0000000000000000 000001f6 00000032 0 E 0 0 1
> > [ 8] .gnu.lto_.vars.c8904cb9a96e7417 PROGBITS 0000000000000000 00000228 00000012 0 E 0 0 1
> > [ 9] .gnu.lto_.refs.c8904cb9a96e7417 PROGBITS 0000000000000000 0000023a 00000013 0 E 0 0 1
> >  .gnu.lto_.statics.c8904cb9a96e7417 PROGBITS 0000000000000000 0000024d 00000014 0 E 0 0 1
> >  .gnu.lto_.decls.c8904cb9a96e7417 PROGBITS 0000000000000000 00000261 000001f3 0 E 0 0 1
> >  .gnu.lto_.symtab.c8904cb9a96e7417 PROGBITS 0000000000000000 00000454 00000011 0 E 0 0 1
> >  .gnu.lto_.opts PROGBITS 0000000000000000 00000465 000000e9 0 E 0 0 1
> > 25: 0000000000000001 1 OBJECT GLOBAL DEFAULT COMMON __gnu_lto_v1
> > [ 2a] __gnu_lto_v1
> > Are the (struct function*) and CFG meant to exist at this stage, and be
> > in gimple form, and is DECL_STRUCT_FUNCTION meant to be non-NULL for
> > functions in translation units that were compiled with -flto? (or have
> > I misunderstood LTO?)
> It depends if you are in the WPA stage (lto1 was invoked with -fwpa)
> in which case
> no function bodies and thus no CFG is available at all, or if you are in LTRANS
> stage (lto1 was invoked with -fltrans) which see _part_ of the whole programs
> callgraph and function bodies (and thus CFGs). As a workaround you probably
> can make your example work by using -flto-partition=none which merges WPA
> and LTRANS stages and pull in the wole program into a single link-time TU.
Many thanks: "-fwpa" was indeed being passed by "gcc" to "lto1", and on
adding "-flto-partition=none" to the gcc command line -fwpa goes away,
and my plugin is able to see all of the gimple CFG from all of the .o
files (and thus generate pretty graphviz renderings of the supergraph of
all CFGs etc).
FWIW the -fwpa behavior was surprising to me, and felt like something of
a "gotcha". Based on my reading of
I had assumed that "LTO mode" was the default when setting "-flto", and
that "WHOPR mode" was something that I had to add an extra option to
enable (and thus I merely skimmed those parts of the docs), whereas it
seems to be the other way around. In my defense, the sentence "WHOPR
can be seen as an extension of the usual LTO mode of compilation" on
that page does give the impression (to me, at least), incorrectly, that
unpartitioned LTO is the default - should that be reworded? (That page
could really use some diagrams; does the docs toolchain support this?)
BTW, if I'm reading the code correctly there's a minor docs error
Looking at 4.7.0, gcc/lto-streamer.c:lto_get_section_name() sets the
name of sections of type "LTO_section_function_body" to contain the name
of their function *without* adding the corresponding entry from the
lto_section_name table (aka "function_body").
So the relevant part of that page should (I believe) read:
"Function bodies (.gnu.lto_.<function_name>)"
"Function bodies (.gnu.lto_.function_body.<name>)"
Thanks again; hope the above is helpful.