xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/lto/lto-dump.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 /* Functions for LTO dump tool.
2    Copyright (C) 2018-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "function.h"
25 #include "basic-block.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "cfg.h"
29 #include "tree-cfg.h"
30 #include "tree-pass.h"
31 #include "tree-streamer.h"
32 #include "cgraph.h"
33 #include "opts.h"
34 #include "debug.h"
35 #include "lto-partition.h"
36 #include "tree-pretty-print.h"
37 #include "lto-common.h"
38 
39 /* Stores details of symbols for dumping symbol list.  */
40 
41 class symbol_entry
42 {
43 public:
44   symtab_node *node;
symbol_entry(symtab_node * node_)45   symbol_entry (symtab_node *node_): node (node_)
46   {}
47 
~symbol_entry()48   virtual ~symbol_entry ()
49   {}
50 
get_name()51   char* get_name () const
52   {
53     if (flag_lto_dump_demangle)
54       return xstrdup (node->name ());
55     else
56       return xstrdup (node->asm_name ());
57   }
58 
59   virtual size_t get_size () const = 0;
60 
dump()61   virtual void dump ()
62   {
63     const char *name = get_name ();
64     const char *type_name = node->get_symtab_type_string ();
65     const char *visibility = node->get_visibility_string ();
66     size_t sz = get_size ();
67     printf ("%s  %s  %4" PRIu64 "  %s  ", type_name, visibility, (uint64_t) sz,
68 	    name);
69   }
70 };
71 
72 /* Stores variable specific details of symbols for dumping symbol list.  */
73 
74 class variable_entry: public symbol_entry
75 {
76 public:
variable_entry(varpool_node * node_)77   variable_entry (varpool_node *node_): symbol_entry (node_)
78   {}
79 
~variable_entry()80   virtual ~variable_entry ()
81   {}
82 
get_size()83   virtual size_t get_size () const
84   {
85     varpool_node *vnode = dyn_cast<varpool_node *> (node);
86     if (DECL_SIZE (vnode->decl) && tree_fits_shwi_p (DECL_SIZE (vnode->decl)))
87       return tree_to_shwi (DECL_SIZE (vnode->decl));
88     return 0;
89   }
90 
dump()91   virtual void dump ()
92   {
93     symbol_entry :: dump ();
94     varpool_node *vnode = dyn_cast<varpool_node *> (node);
95     vnode->get_constructor ();
96     tree value_tree = DECL_INITIAL (vnode->decl);
97     if (flag_lto_print_value && value_tree)
98       print_generic_expr (stdout, value_tree, TDF_NONE);
99     printf ("\n");
100   }
101 };
102 
103 /* Stores function specific details of symbols for dumping symbol list.  */
104 
105 class function_entry: public symbol_entry
106 {
107 public:
function_entry(cgraph_node * node_)108   function_entry (cgraph_node *node_): symbol_entry (node_)
109   {}
110 
~function_entry()111   virtual ~function_entry ()
112   {}
113 
dump()114   virtual void dump ()
115   {
116     symbol_entry :: dump ();
117     printf ("\n");
118   }
119 
get_size()120   virtual size_t get_size () const
121   {
122     cgraph_node *cnode = dyn_cast<cgraph_node *> (node);
123     gcc_assert (cnode);
124 
125     return (cnode->definition && !cnode->alias)
126      ? n_basic_blocks_for_fn (DECL_STRUCT_FUNCTION (cnode->decl))
127      : 0;
128   }
129 };
130 
131 /* Comparing symbols based on size.  */
132 
size_compare(const void * a,const void * b)133 int size_compare (const void *a, const void *b)
134 {
135   const symbol_entry *e1 = *(const symbol_entry * const*) a;
136   const symbol_entry *e2 = *(const symbol_entry * const*) b;
137 
138   return e1->get_size () - e2->get_size ();
139 }
140 
141 /* Comparing symbols based on name.  */
142 
name_compare(const void * a,const void * b)143 int name_compare (const void *a, const void *b)
144 {
145   const symbol_entry *e1 = *(const symbol_entry * const*) a;
146   const symbol_entry *e2 = *(const symbol_entry * const*) b;
147 
148   return strcmp (e1->get_name (), e2->get_name ());
149 }
150 
151 /* Dump list of functions and their details.  */
152 
dump_list_functions(void)153 void dump_list_functions (void)
154 {
155   auto_vec<symbol_entry *> v;
156 
157   cgraph_node *cnode;
158   FOR_EACH_FUNCTION (cnode)
159   {
160     if (cnode->definition && !cnode->alias)
161       cnode->get_untransformed_body ();
162     symbol_entry *e = new function_entry (cnode);
163     if (!flag_lto_dump_defined || (cnode->definition && !cnode->alias))
164       v.safe_push (e);
165   }
166 
167   if (flag_lto_size_sort)
168     v.qsort (size_compare);
169   else if (flag_lto_name_sort)
170     v.qsort (name_compare);
171   if (flag_lto_reverse_sort)
172     v.reverse ();
173 
174   printf ("Type   Visibility  Size  Name");
175   if (flag_lto_print_value)
176     printf ("  Value");
177   printf ("\n");
178   int i=0;
179   symbol_entry* e;
180   FOR_EACH_VEC_ELT (v, i, e)
181     {
182       e->dump ();
183       delete e;
184     }
185 }
186 
187 /* Dump list of variables and their details.  */
188 
dump_list_variables(void)189 void dump_list_variables (void)
190 {
191   auto_vec<symbol_entry *> v;
192 
193   varpool_node *vnode;
194   FOR_EACH_VARIABLE (vnode)
195   {
196     symbol_entry *e = new variable_entry (vnode);
197     if (!flag_lto_dump_defined || vnode->definition)
198       v.safe_push (e);
199   }
200 
201   if (flag_lto_size_sort)
202     v.qsort (size_compare);
203   else if (flag_lto_name_sort)
204     v.qsort (name_compare);
205   if (flag_lto_reverse_sort)
206     v.reverse ();
207 
208   printf ("\n");
209   int i=0;
210   symbol_entry* e;
211   FOR_EACH_VEC_ELT (v, i, e)
212     {
213       e->dump ();
214       delete e;
215     }
216 }
217 
218 /* Dump symbol table in graphviz format.  */
dump_symtab_graphviz(void)219 void dump_symtab_graphviz (void)
220 {
221   symtab->dump_graphviz (stdout);
222 }
223 
224 /* Dump symbol list.  */
225 
dump_list(void)226 void dump_list (void)
227 {
228   dump_list_functions ();
229   dump_list_variables ();
230   return;
231 }
232 
233 /* Dump specific variables and functions used in IL.  */
dump_symbol()234 void dump_symbol ()
235 {
236   symtab_node *node;
237   printf ("Symbol: %s\n", flag_lto_dump_symbol);
238   FOR_EACH_SYMBOL (node)
239     {
240       if (!strcmp (flag_lto_dump_symbol, node->name ()))
241 	{
242 	  node->debug ();
243 	  printf ("\n");
244 	}
245     }
246   return;
247 }
248 
249 /* Dump specific gimple body of specified function.  */
dump_body()250 void dump_body ()
251 {
252   int flag = 0;
253   dump_flags_t flags = TDF_NONE;
254   if (flag_dump_level)
255     flags = parse_dump_option (flag_dump_level, NULL);
256   if (flags == TDF_ERROR)
257   {
258     error_at (input_location, "Level not found, use none, slim, blocks, vops.");
259     return;
260   }
261   cgraph_node *cnode;
262   FOR_EACH_FUNCTION (cnode)
263     if (cnode->definition
264 	&& !cnode->alias
265 	&& !strcmp (cnode->name (), flag_dump_body))
266       {
267 	printf ("Gimple Body of Function: %s\n", cnode->name ());
268 	cnode->get_untransformed_body ();
269 	debug_function (cnode->decl, flags);
270 	flag = 1;
271       }
272   if (!flag)
273     error_at (input_location, "Function not found.");
274   return;
275 }
276 
277 /* List of command line options for dumping.  */
dump_tool_help()278 void dump_tool_help ()
279 {
280   const char *msg =
281     "Usage: lto-dump [OPTION]... SUB_COMMAND [OPTION]...\n\n"
282     "LTO dump tool command line options.\n\n"
283     "  -list [options]           Dump the symbol list.\n"
284     "    -demangle               Dump the demangled output.\n"
285     "    -defined-only           Dump only the defined symbols.\n"
286     "    -print-value            Dump initial values of the variables.\n"
287     "    -name-sort              Sort the symbols alphabetically.\n"
288     "    -size-sort              Sort the symbols according to size.\n"
289     "    -reverse-sort           Dump the symbols in reverse order.\n"
290     "  -symbol=                  Dump the details of specific symbol.\n"
291     "  -objects                  Dump the details of LTO objects.\n"
292     "  -callgraph                Dump the callgraph in graphviz format.\n"
293     "  -type-stats               Dump statistics of tree types.\n"
294     "  -tree-stats               Dump statistics of trees.\n"
295     "  -gimple-stats             Dump statistics of gimple statements.\n"
296     "  -dump-body=               Dump the specific gimple body.\n"
297     "  -dump-level=              Deciding the optimization level of body.\n"
298     "  -help                     Display the dump tool help.\n";
299 
300   fputs (msg, stdout);
301   return;
302 }
303 
304 unsigned int
lto_option_lang_mask(void)305 lto_option_lang_mask (void)
306 {
307   return CL_LTODump;
308 }
309 
310 /* Functions for dumping various details in LTO dump tool are called
311    in lto_main(). The purpose of this dump tool is to analyze the LTO
312    object files.  */
313 
314 void
lto_main(void)315 lto_main (void)
316 {
317   quiet_flag = true;
318   if (flag_lto_dump_tool_help)
319     dump_tool_help ();
320 
321   /* LTO is called as a front end, even though it is not a front end.
322      Because it is called as a front end, TV_PHASE_PARSING and
323      TV_PARSE_GLOBAL are active, and we need to turn them off while
324      doing LTO.  Later we turn them back on so they are active up in
325      toplev.c.  */
326 
327   /* Initialize the LTO front end.  */
328   lto_fe_init ();
329   g_timer = NULL;
330   /* Read all the symbols and call graph from all the files in the
331      command line.  */
332   read_cgraph_and_symbols (num_in_fnames, in_fnames);
333 
334   /* Dump symbol list.  */
335   if (flag_lto_dump_list)
336     dump_list ();
337   else if (flag_lto_dump_symbol)
338     {
339       /* Dump specific variables and functions used in IL.  */
340       dump_symbol ();
341     }
342   else if (flag_lto_gimple_stats)
343     {
344       /* Dump gimple statement statistics.  */
345       cgraph_node *node;
346       FOR_EACH_DEFINED_FUNCTION (node)
347 	node->get_untransformed_body ();
348       if (!GATHER_STATISTICS)
349 	warning_at (input_location, 0,
350 		    "Not configured with "
351 		    "%<--enable-gather-detailed-mem-stats%>.");
352       else
353 	dump_gimple_statistics ();
354     }
355   else if (flag_lto_tree_stats)
356     {
357       /* Dump tree statistics.  */
358       if (!GATHER_STATISTICS)
359 	warning_at (input_location, 0,
360 		    "Not configured with "
361 		    "%<--enable-gather-detailed-mem-stats%>.");
362       else
363 	{
364 	  printf ("Tree Statistics\n");
365 	  dump_tree_statistics ();
366 	}
367     }
368   else if (flag_dump_body)
369     {
370       /* Dump specific gimple body of specified function.  */
371       dump_body ();
372       return;
373     }
374   else if (flag_dump_callgraph)
375     {
376       dump_symtab_graphviz ();
377       return;
378     }
379 }
380