1 /* Miscellaneous utilities for GIMPLE streaming. Things that are used 2 in both input and output are here. 3 4 Copyright 2009, 2010 Free Software Foundation, Inc. 5 Contributed by Doug Kwan <dougkwan@google.com> 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free 11 Software Foundation; either version 3, or (at your option) any later 12 version. 13 14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15 WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GCC; see the file COPYING3. If not see 21 <http://www.gnu.org/licenses/>. */ 22 23 #include "config.h" 24 #include "system.h" 25 #include "coretypes.h" 26 #include "tm.h" 27 #include "toplev.h" 28 #include "flags.h" 29 #include "tree.h" 30 #include "gimple.h" 31 #include "tree-flow.h" 32 #include "diagnostic-core.h" 33 #include "bitmap.h" 34 #include "vec.h" 35 #include "tree-streamer.h" 36 #include "lto-streamer.h" 37 #include "streamer-hooks.h" 38 39 /* Statistics gathered during LTO, WPA and LTRANS. */ 40 struct lto_stats_d lto_stats; 41 42 /* LTO uses bitmaps with different life-times. So use a seperate 43 obstack for all LTO bitmaps. */ 44 static bitmap_obstack lto_obstack; 45 static bool lto_obstack_initialized; 46 47 48 /* Return a string representing LTO tag TAG. */ 49 50 const char * 51 lto_tag_name (enum LTO_tags tag) 52 { 53 if (lto_tag_is_tree_code_p (tag)) 54 { 55 /* For tags representing tree nodes, return the name of the 56 associated tree code. */ 57 return tree_code_name[lto_tag_to_tree_code (tag)]; 58 } 59 60 if (lto_tag_is_gimple_code_p (tag)) 61 { 62 /* For tags representing gimple statements, return the name of 63 the associated gimple code. */ 64 return gimple_code_name[lto_tag_to_gimple_code (tag)]; 65 } 66 67 switch (tag) 68 { 69 case LTO_null: 70 return "LTO_null"; 71 case LTO_bb0: 72 return "LTO_bb0"; 73 case LTO_bb1: 74 return "LTO_bb1"; 75 case LTO_eh_region: 76 return "LTO_eh_region"; 77 case LTO_function: 78 return "LTO_function"; 79 case LTO_eh_table: 80 return "LTO_eh_table"; 81 case LTO_ert_cleanup: 82 return "LTO_ert_cleanup"; 83 case LTO_ert_try: 84 return "LTO_ert_try"; 85 case LTO_ert_allowed_exceptions: 86 return "LTO_ert_allowed_exceptions"; 87 case LTO_ert_must_not_throw: 88 return "LTO_ert_must_not_throw"; 89 case LTO_tree_pickle_reference: 90 return "LTO_tree_pickle_reference"; 91 case LTO_field_decl_ref: 92 return "LTO_field_decl_ref"; 93 case LTO_function_decl_ref: 94 return "LTO_function_decl_ref"; 95 case LTO_label_decl_ref: 96 return "LTO_label_decl_ref"; 97 case LTO_namespace_decl_ref: 98 return "LTO_namespace_decl_ref"; 99 case LTO_result_decl_ref: 100 return "LTO_result_decl_ref"; 101 case LTO_ssa_name_ref: 102 return "LTO_ssa_name_ref"; 103 case LTO_type_decl_ref: 104 return "LTO_type_decl_ref"; 105 case LTO_type_ref: 106 return "LTO_type_ref"; 107 case LTO_global_decl_ref: 108 return "LTO_global_decl_ref"; 109 default: 110 return "LTO_UNKNOWN"; 111 } 112 } 113 114 115 /* Allocate a bitmap from heap. Initializes the LTO obstack if necessary. */ 116 117 bitmap 118 lto_bitmap_alloc (void) 119 { 120 if (!lto_obstack_initialized) 121 { 122 bitmap_obstack_initialize (<o_obstack); 123 lto_obstack_initialized = true; 124 } 125 return BITMAP_ALLOC (<o_obstack); 126 } 127 128 /* Free bitmap B. */ 129 130 void 131 lto_bitmap_free (bitmap b) 132 { 133 BITMAP_FREE (b); 134 } 135 136 137 /* Get a section name for a particular type or name. The NAME field 138 is only used if SECTION_TYPE is LTO_section_function_body. For all 139 others it is ignored. The callee of this function is responsible 140 to free the returned name. */ 141 142 char * 143 lto_get_section_name (int section_type, const char *name, struct lto_file_decl_data *f) 144 { 145 const char *add; 146 char post[32]; 147 const char *sep; 148 149 if (section_type == LTO_section_function_body) 150 { 151 gcc_assert (name != NULL); 152 if (name[0] == '*') 153 name++; 154 add = name; 155 sep = ""; 156 } 157 else if (section_type < LTO_N_SECTION_TYPES) 158 { 159 add = lto_section_name[section_type]; 160 sep = "."; 161 } 162 else 163 internal_error ("bytecode stream: unexpected LTO section %s", name); 164 165 /* Make the section name unique so that ld -r combining sections 166 doesn't confuse the reader with merged sections. 167 168 For options don't add a ID, the option reader cannot deal with them 169 and merging should be ok here. */ 170 if (section_type == LTO_section_opts) 171 strcpy (post, ""); 172 else if (f != NULL) 173 sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id); 174 else 175 sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false)); 176 return concat (LTO_SECTION_NAME_PREFIX, sep, add, post, NULL); 177 } 178 179 180 /* Show various memory usage statistics related to LTO. */ 181 182 void 183 print_lto_report (void) 184 { 185 const char *s = (flag_lto) ? "LTO" : (flag_wpa) ? "WPA" : "LTRANS"; 186 unsigned i; 187 188 fprintf (stderr, "%s statistics\n", s); 189 fprintf (stderr, "[%s] # of input files: " 190 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, lto_stats.num_input_files); 191 192 fprintf (stderr, "[%s] # of input cgraph nodes: " 193 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 194 lto_stats.num_input_cgraph_nodes); 195 196 fprintf (stderr, "[%s] # of function bodies: " 197 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 198 lto_stats.num_function_bodies); 199 200 fprintf (stderr, "[%s] ", s); 201 print_gimple_types_stats (); 202 203 for (i = 0; i < NUM_TREE_CODES; i++) 204 if (lto_stats.num_trees[i]) 205 fprintf (stderr, "[%s] # of '%s' objects read: " 206 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 207 tree_code_name[i], lto_stats.num_trees[i]); 208 209 if (flag_lto) 210 { 211 fprintf (stderr, "[%s] Compression: " 212 HOST_WIDE_INT_PRINT_UNSIGNED " output bytes, " 213 HOST_WIDE_INT_PRINT_UNSIGNED " compressed bytes", s, 214 lto_stats.num_output_il_bytes, 215 lto_stats.num_compressed_il_bytes); 216 if (lto_stats.num_output_il_bytes > 0) 217 { 218 const float dividend = (float) lto_stats.num_compressed_il_bytes; 219 const float divisor = (float) lto_stats.num_output_il_bytes; 220 fprintf (stderr, " (ratio: %f)", dividend / divisor); 221 } 222 fprintf (stderr, "\n"); 223 } 224 225 if (flag_wpa) 226 { 227 fprintf (stderr, "[%s] # of output files: " 228 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 229 lto_stats.num_output_files); 230 231 fprintf (stderr, "[%s] # of output cgraph nodes: " 232 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 233 lto_stats.num_output_cgraph_nodes); 234 235 fprintf (stderr, "[%s] # callgraph partitions: " 236 HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, 237 lto_stats.num_cgraph_partitions); 238 239 fprintf (stderr, "[%s] Compression: " 240 HOST_WIDE_INT_PRINT_UNSIGNED " input bytes, " 241 HOST_WIDE_INT_PRINT_UNSIGNED " uncompressed bytes", s, 242 lto_stats.num_input_il_bytes, 243 lto_stats.num_uncompressed_il_bytes); 244 if (lto_stats.num_input_il_bytes > 0) 245 { 246 const float dividend = (float) lto_stats.num_uncompressed_il_bytes; 247 const float divisor = (float) lto_stats.num_input_il_bytes; 248 fprintf (stderr, " (ratio: %f)", dividend / divisor); 249 } 250 fprintf (stderr, "\n"); 251 } 252 253 for (i = 0; i < LTO_N_SECTION_TYPES; i++) 254 fprintf (stderr, "[%s] Size of mmap'd section %s: " 255 HOST_WIDE_INT_PRINT_UNSIGNED " bytes\n", s, 256 lto_section_name[i], lto_stats.section_size[i]); 257 } 258 259 260 #ifdef LTO_STREAMER_DEBUG 261 static htab_t tree_htab; 262 263 struct tree_hash_entry 264 { 265 tree key; 266 intptr_t value; 267 }; 268 269 static hashval_t 270 hash_tree (const void *p) 271 { 272 const struct tree_hash_entry *e = (const struct tree_hash_entry *) p; 273 return htab_hash_pointer (e->key); 274 } 275 276 static int 277 eq_tree (const void *p1, const void *p2) 278 { 279 const struct tree_hash_entry *e1 = (const struct tree_hash_entry *) p1; 280 const struct tree_hash_entry *e2 = (const struct tree_hash_entry *) p2; 281 return (e1->key == e2->key); 282 } 283 #endif 284 285 /* Initialization common to the LTO reader and writer. */ 286 287 void 288 lto_streamer_init (void) 289 { 290 /* Check that all the TS_* handled by the reader and writer routines 291 match exactly the structures defined in treestruct.def. When a 292 new TS_* astructure is added, the streamer should be updated to 293 handle it. */ 294 streamer_check_handled_ts_structures (); 295 296 #ifdef LTO_STREAMER_DEBUG 297 tree_htab = htab_create (31, hash_tree, eq_tree, NULL); 298 #endif 299 } 300 301 302 /* Gate function for all LTO streaming passes. */ 303 304 bool 305 gate_lto_out (void) 306 { 307 return ((flag_generate_lto || in_lto_p) 308 /* Don't bother doing anything if the program has errors. */ 309 && !seen_error ()); 310 } 311 312 313 #ifdef LTO_STREAMER_DEBUG 314 /* Add a mapping between T and ORIG_T, which is the numeric value of 315 the original address of T as it was seen by the LTO writer. This 316 mapping is useful when debugging streaming problems. A debugging 317 session can be started on both reader and writer using ORIG_T 318 as a breakpoint value in both sessions. 319 320 Note that this mapping is transient and only valid while T is 321 being reconstructed. Once T is fully built, the mapping is 322 removed. */ 323 324 void 325 lto_orig_address_map (tree t, intptr_t orig_t) 326 { 327 struct tree_hash_entry ent; 328 struct tree_hash_entry **slot; 329 330 ent.key = t; 331 ent.value = orig_t; 332 slot 333 = (struct tree_hash_entry **) htab_find_slot (tree_htab, &ent, INSERT); 334 gcc_assert (!*slot); 335 *slot = XNEW (struct tree_hash_entry); 336 **slot = ent; 337 } 338 339 340 /* Get the original address of T as it was seen by the writer. This 341 is only valid while T is being reconstructed. */ 342 343 intptr_t 344 lto_orig_address_get (tree t) 345 { 346 struct tree_hash_entry ent; 347 struct tree_hash_entry **slot; 348 349 ent.key = t; 350 slot 351 = (struct tree_hash_entry **) htab_find_slot (tree_htab, &ent, NO_INSERT); 352 return (slot ? (*slot)->value : 0); 353 } 354 355 356 /* Clear the mapping of T to its original address. */ 357 358 void 359 lto_orig_address_remove (tree t) 360 { 361 struct tree_hash_entry ent; 362 struct tree_hash_entry **slot; 363 364 ent.key = t; 365 slot 366 = (struct tree_hash_entry **) htab_find_slot (tree_htab, &ent, NO_INSERT); 367 gcc_assert (slot); 368 free (*slot); 369 htab_clear_slot (tree_htab, (PTR *)slot); 370 } 371 #endif 372 373 374 /* Check that the version MAJOR.MINOR is the correct version number. */ 375 376 void 377 lto_check_version (int major, int minor) 378 { 379 if (major != LTO_major_version || minor != LTO_minor_version) 380 fatal_error ("bytecode stream generated with LTO version %d.%d instead " 381 "of the expected %d.%d", 382 major, minor, 383 LTO_major_version, LTO_minor_version); 384 } 385 386 387 /* Initialize all the streamer hooks used for streaming GIMPLE. */ 388 389 void 390 lto_streamer_hooks_init (void) 391 { 392 streamer_hooks_init (); 393 streamer_hooks.write_tree = lto_output_tree; 394 streamer_hooks.read_tree = lto_input_tree; 395 } 396