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; 45 symbol_entry (symtab_node *node_): node (node_) 46 {} 47 48 virtual ~symbol_entry () 49 {} 50 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 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: 77 variable_entry (varpool_node *node_): symbol_entry (node_) 78 {} 79 80 virtual ~variable_entry () 81 {} 82 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 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: 108 function_entry (cgraph_node *node_): symbol_entry (node_) 109 {} 110 111 virtual ~function_entry () 112 {} 113 114 virtual void dump () 115 { 116 symbol_entry :: dump (); 117 printf ("\n"); 118 } 119 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 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 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 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 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. */ 219 void dump_symtab_graphviz (void) 220 { 221 symtab->dump_graphviz (stdout); 222 } 223 224 /* Dump symbol list. */ 225 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. */ 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. */ 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. */ 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 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 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