Mercurial > hg > CbC > CbC_gcc
comparison gcc/dumpfile.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Dump infrastructure for optimizations and intermediate representation. | 1 /* Dump infrastructure for optimizations and intermediate representation. |
2 Copyright (C) 2012-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2012-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 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 | 7 the terms of the GNU General Public License as published by the Free |
27 #include "dumpfile.h" | 27 #include "dumpfile.h" |
28 #include "context.h" | 28 #include "context.h" |
29 #include "profile-count.h" | 29 #include "profile-count.h" |
30 #include "tree-cfg.h" | 30 #include "tree-cfg.h" |
31 #include "langhooks.h" | 31 #include "langhooks.h" |
32 #include "backend.h" /* for gimple.h. */ | |
33 #include "gimple.h" /* for dump_user_location_t ctor. */ | |
34 #include "rtl.h" /* for dump_user_location_t ctor. */ | |
35 #include "selftest.h" | |
36 #include "optinfo.h" | |
37 #include "dump-context.h" | |
38 #include "cgraph.h" | |
39 #include "tree-pass.h" /* for "current_pass". */ | |
40 #include "optinfo-emit-json.h" | |
41 #include "stringpool.h" /* for get_identifier. */ | |
32 | 42 |
33 /* If non-NULL, return one past-the-end of the matching SUBPART of | 43 /* If non-NULL, return one past-the-end of the matching SUBPART of |
34 the WHOLE string. */ | 44 the WHOLE string. */ |
35 #define skip_leading_substring(whole, part) \ | 45 #define skip_leading_substring(whole, part) \ |
36 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) | 46 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) |
37 | 47 |
38 static dump_flags_t pflags; /* current dump_flags */ | 48 static dump_flags_t pflags; /* current dump_flags */ |
39 static dump_flags_t alt_flags; /* current opt_info flags */ | |
40 | 49 |
41 static void dump_loc (dump_flags_t, FILE *, source_location); | 50 static void dump_loc (dump_flags_t, FILE *, source_location); |
51 | |
52 /* Current -fopt-info output stream, if any, and flags. */ | |
53 static FILE *alt_dump_file = NULL; | |
54 static dump_flags_t alt_flags; | |
55 | |
42 static FILE *dump_open_alternate_stream (struct dump_file_info *); | 56 static FILE *dump_open_alternate_stream (struct dump_file_info *); |
43 | 57 |
44 /* These are currently used for communicating between passes. | 58 /* These are currently used for communicating between passes. |
45 However, instead of accessing them directly, the passes can use | 59 However, instead of accessing them directly, the passes can use |
46 dump_printf () for dumps. */ | 60 dump_printf () for dumps. */ |
47 FILE *dump_file = NULL; | 61 FILE *dump_file = NULL; |
48 FILE *alt_dump_file = NULL; | |
49 const char *dump_file_name; | 62 const char *dump_file_name; |
50 dump_flags_t dump_flags; | 63 dump_flags_t dump_flags; |
64 bool dumps_are_enabled = false; | |
65 | |
66 | |
67 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled" | |
68 global. */ | |
69 | |
70 void | |
71 set_dump_file (FILE *new_dump_file) | |
72 { | |
73 dumpfile_ensure_any_optinfo_are_flushed (); | |
74 dump_file = new_dump_file; | |
75 dump_context::get ().refresh_dumps_are_enabled (); | |
76 } | |
77 | |
78 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled" | |
79 global. */ | |
80 | |
81 static void | |
82 set_alt_dump_file (FILE *new_alt_dump_file) | |
83 { | |
84 dumpfile_ensure_any_optinfo_are_flushed (); | |
85 alt_dump_file = new_alt_dump_file; | |
86 dump_context::get ().refresh_dumps_are_enabled (); | |
87 } | |
51 | 88 |
52 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \ | 89 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \ |
53 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, 0, 0, 0, 0, 0, num, \ | 90 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \ |
54 false, false} | 91 OPTGROUP_NONE, 0, 0, num, false, false} |
55 | 92 |
56 /* Table of tree dump switches. This must be consistent with the | 93 /* Table of tree dump switches. This must be consistent with the |
57 TREE_DUMP_INDEX enumeration in dumpfile.h. */ | 94 TREE_DUMP_INDEX enumeration in dumpfile.h. */ |
58 static struct dump_file_info dump_files[TDI_end] = | 95 static struct dump_file_info dump_files[TDI_end] = |
59 { | 96 { |
62 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0), | 99 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0), |
63 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0), | 100 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0), |
64 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0), | 101 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0), |
65 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0), | 102 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0), |
66 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0), | 103 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0), |
104 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0), | |
67 #define FIRST_AUTO_NUMBERED_DUMP 1 | 105 #define FIRST_AUTO_NUMBERED_DUMP 1 |
68 #define FIRST_ME_AUTO_NUMBERED_DUMP 3 | 106 #define FIRST_ME_AUTO_NUMBERED_DUMP 4 |
69 | 107 |
70 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0), | 108 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0), |
71 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0), | 109 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0), |
72 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0), | 110 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0), |
73 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0), | 111 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0), |
74 }; | 112 }; |
75 | 113 |
76 /* Define a name->number mapping for a dump flag value. */ | |
77 struct dump_option_value_info | |
78 { | |
79 const char *const name; /* the name of the value */ | |
80 const dump_flags_t value; /* the value of the name */ | |
81 }; | |
82 | |
83 /* Table of dump options. This must be consistent with the TDF_* flags | 114 /* Table of dump options. This must be consistent with the TDF_* flags |
84 in dumpfile.h and opt_info_options below. */ | 115 in dumpfile.h and opt_info_options below. */ |
85 static const struct dump_option_value_info dump_options[] = | 116 static const kv_pair<dump_flags_t> dump_options[] = |
86 { | 117 { |
87 {"address", TDF_ADDRESS}, | 118 {"address", TDF_ADDRESS}, |
88 {"asmname", TDF_ASMNAME}, | 119 {"asmname", TDF_ASMNAME}, |
89 {"slim", TDF_SLIM}, | 120 {"slim", TDF_SLIM}, |
90 {"raw", TDF_RAW}, | 121 {"raw", TDF_RAW}, |
108 {"gimple", TDF_GIMPLE}, | 139 {"gimple", TDF_GIMPLE}, |
109 {"folding", TDF_FOLDING}, | 140 {"folding", TDF_FOLDING}, |
110 {"optimized", MSG_OPTIMIZED_LOCATIONS}, | 141 {"optimized", MSG_OPTIMIZED_LOCATIONS}, |
111 {"missed", MSG_MISSED_OPTIMIZATION}, | 142 {"missed", MSG_MISSED_OPTIMIZATION}, |
112 {"note", MSG_NOTE}, | 143 {"note", MSG_NOTE}, |
113 {"optall", MSG_ALL}, | 144 {"optall", MSG_ALL_KINDS}, |
114 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH | 145 {"all", dump_flags_t (TDF_ALL_VALUES |
115 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID | 146 & ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH |
116 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))}, | 147 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID |
117 {NULL, 0} | 148 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))}, |
149 {NULL, TDF_NONE} | |
118 }; | 150 }; |
119 | 151 |
120 /* A subset of the dump_options table which is used for -fopt-info | 152 /* A subset of the dump_options table which is used for -fopt-info |
121 types. This must be consistent with the MSG_* flags in dumpfile.h. | 153 types. This must be consistent with the MSG_* flags in dumpfile.h. |
122 */ | 154 */ |
123 static const struct dump_option_value_info optinfo_verbosity_options[] = | 155 static const kv_pair<dump_flags_t> optinfo_verbosity_options[] = |
124 { | 156 { |
125 {"optimized", MSG_OPTIMIZED_LOCATIONS}, | 157 {"optimized", MSG_OPTIMIZED_LOCATIONS}, |
126 {"missed", MSG_MISSED_OPTIMIZATION}, | 158 {"missed", MSG_MISSED_OPTIMIZATION}, |
127 {"note", MSG_NOTE}, | 159 {"note", MSG_NOTE}, |
128 {"all", MSG_ALL}, | 160 {"all", MSG_ALL_KINDS}, |
129 {NULL, 0} | 161 {"internals", MSG_PRIORITY_INTERNALS}, |
162 {NULL, TDF_NONE} | |
130 }; | 163 }; |
131 | 164 |
132 /* Flags used for -fopt-info groups. */ | 165 /* Flags used for -fopt-info groups. */ |
133 static const struct dump_option_value_info optgroup_options[] = | 166 const kv_pair<optgroup_flags_t> optgroup_options[] = |
134 { | 167 { |
135 {"ipa", OPTGROUP_IPA}, | 168 {"ipa", OPTGROUP_IPA}, |
136 {"loop", OPTGROUP_LOOP}, | 169 {"loop", OPTGROUP_LOOP}, |
137 {"inline", OPTGROUP_INLINE}, | 170 {"inline", OPTGROUP_INLINE}, |
138 {"omp", OPTGROUP_OMP}, | 171 {"omp", OPTGROUP_OMP}, |
139 {"vec", OPTGROUP_VEC}, | 172 {"vec", OPTGROUP_VEC}, |
140 {"optall", OPTGROUP_ALL}, | 173 {"optall", OPTGROUP_ALL}, |
141 {NULL, 0} | 174 {NULL, OPTGROUP_NONE} |
142 }; | 175 }; |
143 | 176 |
144 gcc::dump_manager::dump_manager (): | 177 gcc::dump_manager::dump_manager (): |
145 m_next_dump (FIRST_AUTO_NUMBERED_DUMP), | 178 m_next_dump (FIRST_AUTO_NUMBERED_DUMP), |
146 m_extra_dump_files (NULL), | 179 m_extra_dump_files (NULL), |
147 m_extra_dump_files_in_use (0), | 180 m_extra_dump_files_in_use (0), |
148 m_extra_dump_files_alloced (0) | 181 m_extra_dump_files_alloced (0), |
182 m_optgroup_flags (OPTGROUP_NONE), | |
183 m_optinfo_flags (TDF_NONE), | |
184 m_optinfo_filename (NULL) | |
149 { | 185 { |
150 } | 186 } |
151 | 187 |
152 gcc::dump_manager::~dump_manager () | 188 gcc::dump_manager::~dump_manager () |
153 { | 189 { |
190 free (m_optinfo_filename); | |
154 for (size_t i = 0; i < m_extra_dump_files_in_use; i++) | 191 for (size_t i = 0; i < m_extra_dump_files_in_use; i++) |
155 { | 192 { |
156 dump_file_info *dfi = &m_extra_dump_files[i]; | 193 dump_file_info *dfi = &m_extra_dump_files[i]; |
157 /* suffix, swtch, glob are statically allocated for the entries | 194 /* suffix, swtch, glob are statically allocated for the entries |
158 in dump_files, and for statistics, but are dynamically allocated | 195 in dump_files, and for statistics, but are dynamically allocated |
171 } | 208 } |
172 | 209 |
173 unsigned int | 210 unsigned int |
174 gcc::dump_manager:: | 211 gcc::dump_manager:: |
175 dump_register (const char *suffix, const char *swtch, const char *glob, | 212 dump_register (const char *suffix, const char *swtch, const char *glob, |
176 dump_kind dkind, int optgroup_flags, bool take_ownership) | 213 dump_kind dkind, optgroup_flags_t optgroup_flags, |
214 bool take_ownership) | |
177 { | 215 { |
178 int num = m_next_dump++; | 216 int num = m_next_dump++; |
179 | 217 |
180 size_t count = m_extra_dump_files_in_use++; | 218 size_t count = m_extra_dump_files_in_use++; |
181 | 219 |
249 struct dump_file_info * | 287 struct dump_file_info * |
250 gcc::dump_manager:: | 288 gcc::dump_manager:: |
251 get_dump_file_info_by_switch (const char *swtch) const | 289 get_dump_file_info_by_switch (const char *swtch) const |
252 { | 290 { |
253 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++) | 291 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++) |
254 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch)) | 292 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0) |
255 return &m_extra_dump_files[i]; | 293 return &m_extra_dump_files[i]; |
256 | 294 |
257 /* Not found. */ | 295 /* Not found. */ |
258 return NULL; | 296 return NULL; |
259 } | 297 } |
264 buffer. | 302 buffer. |
265 If the dump is not enabled, returns NULL. */ | 303 If the dump is not enabled, returns NULL. */ |
266 | 304 |
267 char * | 305 char * |
268 gcc::dump_manager:: | 306 gcc::dump_manager:: |
269 get_dump_file_name (int phase) const | 307 get_dump_file_name (int phase, int part) const |
270 { | 308 { |
271 struct dump_file_info *dfi; | 309 struct dump_file_info *dfi; |
272 | 310 |
273 if (phase == TDI_none) | 311 if (phase == TDI_none) |
274 return NULL; | 312 return NULL; |
275 | 313 |
276 dfi = get_dump_file_info (phase); | 314 dfi = get_dump_file_info (phase); |
277 | 315 |
278 return get_dump_file_name (dfi); | 316 return get_dump_file_name (dfi, part); |
279 } | 317 } |
280 | 318 |
281 /* Return the name of the dump file for the given dump_file_info. | 319 /* Return the name of the dump file for the given dump_file_info. |
282 The caller is responsible for calling free on the returned | 320 The caller is responsible for calling free on the returned |
283 buffer. | 321 buffer. |
284 If the dump is not enabled, returns NULL. */ | 322 If the dump is not enabled, returns NULL. */ |
285 | 323 |
286 char * | 324 char * |
287 gcc::dump_manager:: | 325 gcc::dump_manager:: |
288 get_dump_file_name (struct dump_file_info *dfi) const | 326 get_dump_file_name (struct dump_file_info *dfi, int part) const |
289 { | 327 { |
290 char dump_id[10]; | 328 char dump_id[10]; |
291 | 329 |
292 gcc_assert (dfi); | 330 gcc_assert (dfi); |
293 | 331 |
307 | 345 |
308 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) | 346 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) |
309 dump_id[0] = '\0'; | 347 dump_id[0] = '\0'; |
310 } | 348 } |
311 | 349 |
312 return concat (dump_base_name, dump_id, dfi->suffix, NULL); | 350 if (part != -1) |
351 { | |
352 char part_id[8]; | |
353 snprintf (part_id, sizeof (part_id), ".%i", part); | |
354 return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL); | |
355 } | |
356 else | |
357 return concat (dump_base_name, dump_id, dfi->suffix, NULL); | |
358 } | |
359 | |
360 /* Open a dump file called FILENAME. Some filenames are special and | |
361 refer to the standard streams. TRUNC indicates whether this is the | |
362 first open (so the file should be truncated, rather than appended). | |
363 An error message is emitted in the event of failure. */ | |
364 | |
365 static FILE * | |
366 dump_open (const char *filename, bool trunc) | |
367 { | |
368 if (strcmp ("stderr", filename) == 0) | |
369 return stderr; | |
370 | |
371 if (strcmp ("stdout", filename) == 0 | |
372 || strcmp ("-", filename) == 0) | |
373 return stdout; | |
374 | |
375 FILE *stream = fopen (filename, trunc ? "w" : "a"); | |
376 | |
377 if (!stream) | |
378 error ("could not open dump file %qs: %m", filename); | |
379 return stream; | |
313 } | 380 } |
314 | 381 |
315 /* For a given DFI, open an alternate dump filename (which could also | 382 /* For a given DFI, open an alternate dump filename (which could also |
316 be a standard stream such as stdout/stderr). If the alternate dump | 383 be a standard stream such as stdout/stderr). If the alternate dump |
317 file cannot be opened, return NULL. */ | 384 file cannot be opened, return NULL. */ |
318 | 385 |
319 static FILE * | 386 static FILE * |
320 dump_open_alternate_stream (struct dump_file_info *dfi) | 387 dump_open_alternate_stream (struct dump_file_info *dfi) |
321 { | 388 { |
322 FILE *stream ; | |
323 if (!dfi->alt_filename) | 389 if (!dfi->alt_filename) |
324 return NULL; | 390 return NULL; |
325 | 391 |
326 if (dfi->alt_stream) | 392 if (dfi->alt_stream) |
327 return dfi->alt_stream; | 393 return dfi->alt_stream; |
328 | 394 |
329 stream = strcmp ("stderr", dfi->alt_filename) == 0 | 395 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0); |
330 ? stderr | 396 |
331 : strcmp ("stdout", dfi->alt_filename) == 0 | 397 if (stream) |
332 ? stdout | |
333 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a"); | |
334 | |
335 if (!stream) | |
336 error ("could not open dump file %qs: %m", dfi->alt_filename); | |
337 else | |
338 dfi->alt_state = 1; | 398 dfi->alt_state = 1; |
339 | 399 |
340 return stream; | 400 return stream; |
341 } | 401 } |
342 | 402 |
403 /* Construct a dump_user_location_t from STMT (using its location and | |
404 hotness). */ | |
405 | |
406 dump_user_location_t::dump_user_location_t (const gimple *stmt) | |
407 : m_count (), m_loc (UNKNOWN_LOCATION) | |
408 { | |
409 if (stmt) | |
410 { | |
411 if (stmt->bb) | |
412 m_count = stmt->bb->count; | |
413 m_loc = gimple_location (stmt); | |
414 } | |
415 } | |
416 | |
417 /* Construct a dump_user_location_t from an RTL instruction (using its | |
418 location and hotness). */ | |
419 | |
420 dump_user_location_t::dump_user_location_t (const rtx_insn *insn) | |
421 : m_count (), m_loc (UNKNOWN_LOCATION) | |
422 { | |
423 if (insn) | |
424 { | |
425 basic_block bb = BLOCK_FOR_INSN (insn); | |
426 if (bb) | |
427 m_count = bb->count; | |
428 m_loc = INSN_LOCATION (insn); | |
429 } | |
430 } | |
431 | |
432 /* Construct from a function declaration. This one requires spelling out | |
433 to avoid accidentally constructing from other kinds of tree. */ | |
434 | |
435 dump_user_location_t | |
436 dump_user_location_t::from_function_decl (tree fndecl) | |
437 { | |
438 gcc_assert (fndecl); | |
439 | |
440 // FIXME: profile count for function? | |
441 return dump_user_location_t (profile_count (), | |
442 DECL_SOURCE_LOCATION (fndecl)); | |
443 } | |
444 | |
445 /* Extract the MSG_* component from DUMP_KIND and return a string for use | |
446 as a prefix to dump messages. | |
447 These match the strings in optinfo_verbosity_options and thus the | |
448 "OPTIONS" within "-fopt-info-OPTIONS". */ | |
449 | |
450 static const char * | |
451 kind_as_string (dump_flags_t dump_kind) | |
452 { | |
453 switch (dump_kind & MSG_ALL_KINDS) | |
454 { | |
455 default: | |
456 gcc_unreachable (); | |
457 case MSG_OPTIMIZED_LOCATIONS: | |
458 return "optimized"; | |
459 case MSG_MISSED_OPTIMIZATION: | |
460 return "missed"; | |
461 case MSG_NOTE: | |
462 return "note"; | |
463 } | |
464 } | |
465 | |
343 /* Print source location on DFILE if enabled. */ | 466 /* Print source location on DFILE if enabled. */ |
344 | 467 |
345 void | 468 static void |
346 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc) | 469 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc) |
347 { | 470 { |
348 if (dump_kind) | 471 if (dump_kind) |
349 { | 472 { |
350 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION) | 473 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION) |
351 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc), | 474 fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc), |
352 LOCATION_LINE (loc), LOCATION_COLUMN (loc)); | 475 LOCATION_LINE (loc), LOCATION_COLUMN (loc)); |
353 else if (current_function_decl) | 476 else if (current_function_decl) |
354 fprintf (dfile, "%s:%d:%d: note: ", | 477 fprintf (dfile, "%s:%d:%d: ", |
355 DECL_SOURCE_FILE (current_function_decl), | 478 DECL_SOURCE_FILE (current_function_decl), |
356 DECL_SOURCE_LINE (current_function_decl), | 479 DECL_SOURCE_LINE (current_function_decl), |
357 DECL_SOURCE_COLUMN (current_function_decl)); | 480 DECL_SOURCE_COLUMN (current_function_decl)); |
358 } | 481 fprintf (dfile, "%s: ", kind_as_string (dump_kind)); |
482 /* Indentation based on scope depth. */ | |
483 fprintf (dfile, "%*s", get_dump_scope_depth (), ""); | |
484 } | |
485 } | |
486 | |
487 /* Print source location to PP if enabled. */ | |
488 | |
489 static void | |
490 dump_loc (dump_flags_t dump_kind, pretty_printer *pp, source_location loc) | |
491 { | |
492 if (dump_kind) | |
493 { | |
494 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION) | |
495 pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc), | |
496 LOCATION_LINE (loc), LOCATION_COLUMN (loc)); | |
497 else if (current_function_decl) | |
498 pp_printf (pp, "%s:%d:%d: ", | |
499 DECL_SOURCE_FILE (current_function_decl), | |
500 DECL_SOURCE_LINE (current_function_decl), | |
501 DECL_SOURCE_COLUMN (current_function_decl)); | |
502 pp_printf (pp, "%s: ", kind_as_string (dump_kind)); | |
503 /* Indentation based on scope depth. */ | |
504 for (unsigned i = 0; i < get_dump_scope_depth (); i++) | |
505 pp_character (pp, ' '); | |
506 } | |
507 } | |
508 | |
509 /* Implementation of dump_context member functions. */ | |
510 | |
511 /* dump_context's dtor. */ | |
512 | |
513 dump_context::~dump_context () | |
514 { | |
515 delete m_pending; | |
516 } | |
517 | |
518 /* Update the "dumps_are_enabled" global; to be called whenever dump_file | |
519 or alt_dump_file change, or when changing dump_context in selftests. */ | |
520 | |
521 void | |
522 dump_context::refresh_dumps_are_enabled () | |
523 { | |
524 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p () | |
525 || m_test_pp); | |
526 } | |
527 | |
528 /* Determine if a message of kind DUMP_KIND and at the current scope depth | |
529 should be printed. | |
530 | |
531 Only show messages that match FILTER both on their kind *and* | |
532 their priority. */ | |
533 | |
534 bool | |
535 dump_context::apply_dump_filter_p (dump_flags_t dump_kind, | |
536 dump_flags_t filter) const | |
537 { | |
538 /* Few messages, if any, have an explicit MSG_PRIORITY. | |
539 If DUMP_KIND does, we'll use it. | |
540 Otherwise, generate an implicit priority value for the message based | |
541 on the current scope depth. | |
542 Messages at the top-level scope are MSG_PRIORITY_USER_FACING, | |
543 whereas those in nested scopes are MSG_PRIORITY_INTERNALS. */ | |
544 if (!(dump_kind & MSG_ALL_PRIORITIES)) | |
545 { | |
546 dump_flags_t implicit_priority | |
547 = (m_scope_depth > 0 | |
548 ? MSG_PRIORITY_INTERNALS | |
549 : MSG_PRIORITY_USER_FACING); | |
550 dump_kind |= implicit_priority; | |
551 } | |
552 | |
553 return (dump_kind & (filter & MSG_ALL_KINDS) | |
554 && dump_kind & (filter & MSG_ALL_PRIORITIES)); | |
555 } | |
556 | |
557 /* Print LOC to the appropriate dump destinations, given DUMP_KIND. | |
558 If optinfos are enabled, begin a new optinfo. */ | |
559 | |
560 void | |
561 dump_context::dump_loc (dump_flags_t dump_kind, const dump_location_t &loc) | |
562 { | |
563 end_any_optinfo (); | |
564 | |
565 dump_loc_immediate (dump_kind, loc); | |
566 | |
567 if (optinfo_enabled_p ()) | |
568 { | |
569 optinfo &info = begin_next_optinfo (loc); | |
570 info.handle_dump_file_kind (dump_kind); | |
571 } | |
572 } | |
573 | |
574 /* As dump_loc above, but without starting a new optinfo. */ | |
575 | |
576 void | |
577 dump_context::dump_loc_immediate (dump_flags_t dump_kind, | |
578 const dump_location_t &loc) | |
579 { | |
580 location_t srcloc = loc.get_location_t (); | |
581 | |
582 if (dump_file && apply_dump_filter_p (dump_kind, pflags)) | |
583 ::dump_loc (dump_kind, dump_file, srcloc); | |
584 | |
585 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags)) | |
586 ::dump_loc (dump_kind, alt_dump_file, srcloc); | |
587 | |
588 /* Support for temp_dump_context in selftests. */ | |
589 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags)) | |
590 ::dump_loc (dump_kind, m_test_pp, srcloc); | |
591 } | |
592 | |
593 /* Make an item for the given dump call, equivalent to print_gimple_stmt. */ | |
594 | |
595 static optinfo_item * | |
596 make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags) | |
597 { | |
598 pretty_printer pp; | |
599 pp_needs_newline (&pp) = true; | |
600 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags); | |
601 pp_newline (&pp); | |
602 | |
603 optinfo_item *item | |
604 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt), | |
605 xstrdup (pp_formatted_text (&pp))); | |
606 return item; | |
359 } | 607 } |
360 | 608 |
361 /* Dump gimple statement GS with SPC indentation spaces and | 609 /* Dump gimple statement GS with SPC indentation spaces and |
362 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */ | 610 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */ |
363 | 611 |
364 void | 612 void |
613 dump_context::dump_gimple_stmt (dump_flags_t dump_kind, | |
614 dump_flags_t extra_dump_flags, | |
615 gimple *gs, int spc) | |
616 { | |
617 optinfo_item *item | |
618 = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags); | |
619 emit_item (item, dump_kind); | |
620 | |
621 if (optinfo_enabled_p ()) | |
622 { | |
623 optinfo &info = ensure_pending_optinfo (); | |
624 info.handle_dump_file_kind (dump_kind); | |
625 info.add_item (item); | |
626 } | |
627 else | |
628 delete item; | |
629 } | |
630 | |
631 /* Similar to dump_gimple_stmt, except additionally print source location. */ | |
632 | |
633 void | |
634 dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind, | |
635 const dump_location_t &loc, | |
636 dump_flags_t extra_dump_flags, | |
637 gimple *gs, int spc) | |
638 { | |
639 dump_loc (dump_kind, loc); | |
640 dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc); | |
641 } | |
642 | |
643 /* Make an item for the given dump call, equivalent to print_gimple_expr. */ | |
644 | |
645 static optinfo_item * | |
646 make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags) | |
647 { | |
648 dump_flags |= TDF_RHS_ONLY; | |
649 pretty_printer pp; | |
650 pp_needs_newline (&pp) = true; | |
651 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags); | |
652 | |
653 optinfo_item *item | |
654 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt), | |
655 xstrdup (pp_formatted_text (&pp))); | |
656 return item; | |
657 } | |
658 | |
659 /* Dump gimple statement GS with SPC indentation spaces and | |
660 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. | |
661 Do not terminate with a newline or semicolon. */ | |
662 | |
663 void | |
664 dump_context::dump_gimple_expr (dump_flags_t dump_kind, | |
665 dump_flags_t extra_dump_flags, | |
666 gimple *gs, int spc) | |
667 { | |
668 optinfo_item *item | |
669 = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags); | |
670 emit_item (item, dump_kind); | |
671 | |
672 if (optinfo_enabled_p ()) | |
673 { | |
674 optinfo &info = ensure_pending_optinfo (); | |
675 info.handle_dump_file_kind (dump_kind); | |
676 info.add_item (item); | |
677 } | |
678 else | |
679 delete item; | |
680 } | |
681 | |
682 /* Similar to dump_gimple_expr, except additionally print source location. */ | |
683 | |
684 void | |
685 dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind, | |
686 const dump_location_t &loc, | |
687 dump_flags_t extra_dump_flags, | |
688 gimple *gs, | |
689 int spc) | |
690 { | |
691 dump_loc (dump_kind, loc); | |
692 dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc); | |
693 } | |
694 | |
695 /* Make an item for the given dump call, equivalent to print_generic_expr. */ | |
696 | |
697 static optinfo_item * | |
698 make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags) | |
699 { | |
700 pretty_printer pp; | |
701 pp_needs_newline (&pp) = true; | |
702 pp_translate_identifiers (&pp) = false; | |
703 dump_generic_node (&pp, node, 0, dump_flags, false); | |
704 | |
705 location_t loc = UNKNOWN_LOCATION; | |
706 if (EXPR_HAS_LOCATION (node)) | |
707 loc = EXPR_LOCATION (node); | |
708 | |
709 optinfo_item *item | |
710 = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc, | |
711 xstrdup (pp_formatted_text (&pp))); | |
712 return item; | |
713 } | |
714 | |
715 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if | |
716 DUMP_KIND is enabled. */ | |
717 | |
718 void | |
719 dump_context::dump_generic_expr (dump_flags_t dump_kind, | |
720 dump_flags_t extra_dump_flags, | |
721 tree t) | |
722 { | |
723 optinfo_item *item | |
724 = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags); | |
725 emit_item (item, dump_kind); | |
726 | |
727 if (optinfo_enabled_p ()) | |
728 { | |
729 optinfo &info = ensure_pending_optinfo (); | |
730 info.handle_dump_file_kind (dump_kind); | |
731 info.add_item (item); | |
732 } | |
733 else | |
734 delete item; | |
735 } | |
736 | |
737 | |
738 /* Similar to dump_generic_expr, except additionally print the source | |
739 location. */ | |
740 | |
741 void | |
742 dump_context::dump_generic_expr_loc (dump_flags_t dump_kind, | |
743 const dump_location_t &loc, | |
744 dump_flags_t extra_dump_flags, | |
745 tree t) | |
746 { | |
747 dump_loc (dump_kind, loc); | |
748 dump_generic_expr (dump_kind, extra_dump_flags, t); | |
749 } | |
750 | |
751 /* dump_pretty_printer's ctor. */ | |
752 | |
753 dump_pretty_printer::dump_pretty_printer (dump_context *context, | |
754 dump_flags_t dump_kind) | |
755 : pretty_printer (), m_context (context), m_dump_kind (dump_kind), | |
756 m_stashed_items () | |
757 { | |
758 pp_format_decoder (this) = format_decoder_cb; | |
759 } | |
760 | |
761 /* Phase 3 of formatting; compare with pp_output_formatted_text. | |
762 | |
763 Emit optinfo_item instances for the various formatted chunks from phases | |
764 1 and 2 (i.e. pp_format). | |
765 | |
766 Some chunks may already have had their items built (during decode_format). | |
767 These chunks have been stashed into m_stashed_items; we emit them here. | |
768 | |
769 For all other purely textual chunks, they are printed into | |
770 buffer->formatted_obstack, and then emitted as a textual optinfo_item. | |
771 This consolidates multiple adjacent text chunks into a single text | |
772 optinfo_item. */ | |
773 | |
774 void | |
775 dump_pretty_printer::emit_items (optinfo *dest) | |
776 { | |
777 output_buffer *buffer = pp_buffer (this); | |
778 struct chunk_info *chunk_array = buffer->cur_chunk_array; | |
779 const char **args = chunk_array->args; | |
780 | |
781 gcc_assert (buffer->obstack == &buffer->formatted_obstack); | |
782 gcc_assert (buffer->line_length == 0); | |
783 | |
784 unsigned stashed_item_idx = 0; | |
785 for (unsigned chunk = 0; args[chunk]; chunk++) | |
786 { | |
787 if (stashed_item_idx < m_stashed_items.length () | |
788 && args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr) | |
789 { | |
790 emit_any_pending_textual_chunks (dest); | |
791 /* This chunk has a stashed item: use it. */ | |
792 emit_item (m_stashed_items[stashed_item_idx++].item, dest); | |
793 } | |
794 else | |
795 /* This chunk is purely textual. Print it (to | |
796 buffer->formatted_obstack), so that we can consolidate adjacent | |
797 chunks into one textual optinfo_item. */ | |
798 pp_string (this, args[chunk]); | |
799 } | |
800 | |
801 emit_any_pending_textual_chunks (dest); | |
802 | |
803 /* Ensure that we consumed all of stashed_items. */ | |
804 gcc_assert (stashed_item_idx == m_stashed_items.length ()); | |
805 | |
806 /* Deallocate the chunk structure and everything after it (i.e. the | |
807 associated series of formatted strings). */ | |
808 buffer->cur_chunk_array = chunk_array->prev; | |
809 obstack_free (&buffer->chunk_obstack, chunk_array); | |
810 } | |
811 | |
812 /* Subroutine of dump_pretty_printer::emit_items | |
813 for consolidating multiple adjacent pure-text chunks into single | |
814 optinfo_items (in phase 3). */ | |
815 | |
816 void | |
817 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest) | |
818 { | |
819 gcc_assert (buffer->obstack == &buffer->formatted_obstack); | |
820 | |
821 /* Don't emit an item if the pending text is empty. */ | |
822 if (output_buffer_last_position_in_text (buffer) == NULL) | |
823 return; | |
824 | |
825 char *formatted_text = xstrdup (pp_formatted_text (this)); | |
826 optinfo_item *item | |
827 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION, | |
828 formatted_text); | |
829 emit_item (item, dest); | |
830 | |
831 /* Clear the pending text by unwinding formatted_text back to the start | |
832 of the buffer (without deallocating). */ | |
833 obstack_free (&buffer->formatted_obstack, | |
834 buffer->formatted_obstack.object_base); | |
835 } | |
836 | |
837 /* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM | |
838 to DEST; otherwise delete ITEM. */ | |
839 | |
840 void | |
841 dump_pretty_printer::emit_item (optinfo_item *item, optinfo *dest) | |
842 { | |
843 m_context->emit_item (item, m_dump_kind); | |
844 if (dest) | |
845 dest->add_item (item); | |
846 else | |
847 delete item; | |
848 } | |
849 | |
850 /* Record that ITEM (generated in phase 2 of formatting) is to be used for | |
851 the chunk at BUFFER_PTR in phase 3 (by emit_items). */ | |
852 | |
853 void | |
854 dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item) | |
855 { | |
856 gcc_assert (buffer_ptr); | |
857 gcc_assert (item); | |
858 | |
859 m_stashed_items.safe_push (stashed_item (buffer_ptr, item)); | |
860 } | |
861 | |
862 /* pp_format_decoder callback for dump_pretty_printer, and thus for | |
863 dump_printf and dump_printf_loc. | |
864 | |
865 A wrapper around decode_format, for type-safety. */ | |
866 | |
867 bool | |
868 dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text, | |
869 const char *spec, int /*precision*/, | |
870 bool /*wide*/, bool /*set_locus*/, | |
871 bool /*verbose*/, bool */*quoted*/, | |
872 const char **buffer_ptr) | |
873 { | |
874 dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp); | |
875 return opp->decode_format (text, spec, buffer_ptr); | |
876 } | |
877 | |
878 /* Format decoder for dump_pretty_printer, and thus for dump_printf and | |
879 dump_printf_loc. | |
880 | |
881 Supported format codes (in addition to the standard pretty_printer ones) | |
882 are: | |
883 | |
884 %E: gimple *: | |
885 Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0) | |
886 %G: gimple *: | |
887 Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0) | |
888 %T: tree: | |
889 Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM). | |
890 | |
891 FIXME: add symtab_node? | |
892 | |
893 These format codes build optinfo_item instances, thus capturing metadata | |
894 about the arguments being dumped, as well as the textual output. */ | |
895 | |
896 bool | |
897 dump_pretty_printer::decode_format (text_info *text, const char *spec, | |
898 const char **buffer_ptr) | |
899 { | |
900 /* Various format codes that imply making an optinfo_item and stashed it | |
901 for later use (to capture metadata, rather than plain text). */ | |
902 switch (*spec) | |
903 { | |
904 case 'E': | |
905 { | |
906 gimple *stmt = va_arg (*text->args_ptr, gimple *); | |
907 | |
908 /* Make an item for the stmt, and stash it. */ | |
909 optinfo_item *item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM); | |
910 stash_item (buffer_ptr, item); | |
911 return true; | |
912 } | |
913 | |
914 case 'G': | |
915 { | |
916 gimple *stmt = va_arg (*text->args_ptr, gimple *); | |
917 | |
918 /* Make an item for the stmt, and stash it. */ | |
919 optinfo_item *item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM); | |
920 stash_item (buffer_ptr, item); | |
921 return true; | |
922 } | |
923 | |
924 case 'T': | |
925 { | |
926 tree t = va_arg (*text->args_ptr, tree); | |
927 | |
928 /* Make an item for the tree, and stash it. */ | |
929 optinfo_item *item = make_item_for_dump_generic_expr (t, TDF_SLIM); | |
930 stash_item (buffer_ptr, item); | |
931 return true; | |
932 } | |
933 | |
934 default: | |
935 return false; | |
936 } | |
937 } | |
938 | |
939 /* Output a formatted message using FORMAT on appropriate dump streams. */ | |
940 | |
941 void | |
942 dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format, | |
943 va_list *ap) | |
944 { | |
945 dump_pretty_printer pp (this, dump_kind); | |
946 | |
947 text_info text; | |
948 text.err_no = errno; | |
949 text.args_ptr = ap; | |
950 text.format_spec = format; | |
951 | |
952 /* Phases 1 and 2, using pp_format. */ | |
953 pp_format (&pp, &text); | |
954 | |
955 /* Phase 3. */ | |
956 if (optinfo_enabled_p ()) | |
957 { | |
958 optinfo &info = ensure_pending_optinfo (); | |
959 info.handle_dump_file_kind (dump_kind); | |
960 pp.emit_items (&info); | |
961 } | |
962 else | |
963 pp.emit_items (NULL); | |
964 } | |
965 | |
966 /* Similar to dump_printf, except source location is also printed, and | |
967 dump location captured. */ | |
968 | |
969 void | |
970 dump_context::dump_printf_loc_va (dump_flags_t dump_kind, | |
971 const dump_location_t &loc, | |
972 const char *format, va_list *ap) | |
973 { | |
974 dump_loc (dump_kind, loc); | |
975 dump_printf_va (dump_kind, format, ap); | |
976 } | |
977 | |
978 /* Make an item for the given dump call, equivalent to print_dec. */ | |
979 | |
980 template<unsigned int N, typename C> | |
981 static optinfo_item * | |
982 make_item_for_dump_dec (const poly_int<N, C> &value) | |
983 { | |
984 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0); | |
985 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED; | |
986 | |
987 pretty_printer pp; | |
988 | |
989 if (value.is_constant ()) | |
990 pp_wide_int (&pp, value.coeffs[0], sgn); | |
991 else | |
992 { | |
993 pp_character (&pp, '['); | |
994 for (unsigned int i = 0; i < N; ++i) | |
995 { | |
996 pp_wide_int (&pp, value.coeffs[i], sgn); | |
997 pp_character (&pp, i == N - 1 ? ']' : ','); | |
998 } | |
999 } | |
1000 | |
1001 optinfo_item *item | |
1002 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION, | |
1003 xstrdup (pp_formatted_text (&pp))); | |
1004 return item; | |
1005 } | |
1006 | |
1007 /* Output VALUE in decimal to appropriate dump streams. */ | |
1008 | |
1009 template<unsigned int N, typename C> | |
1010 void | |
1011 dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value) | |
1012 { | |
1013 optinfo_item *item = make_item_for_dump_dec (value); | |
1014 emit_item (item, dump_kind); | |
1015 | |
1016 if (optinfo_enabled_p ()) | |
1017 { | |
1018 optinfo &info = ensure_pending_optinfo (); | |
1019 info.handle_dump_file_kind (dump_kind); | |
1020 info.add_item (item); | |
1021 } | |
1022 else | |
1023 delete item; | |
1024 } | |
1025 | |
1026 /* Make an item for the given dump call. */ | |
1027 | |
1028 static optinfo_item * | |
1029 make_item_for_dump_symtab_node (symtab_node *node) | |
1030 { | |
1031 location_t loc = DECL_SOURCE_LOCATION (node->decl); | |
1032 optinfo_item *item | |
1033 = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc, | |
1034 xstrdup (node->dump_name ())); | |
1035 return item; | |
1036 } | |
1037 | |
1038 /* Output the name of NODE on appropriate dump streams. */ | |
1039 | |
1040 void | |
1041 dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node) | |
1042 { | |
1043 optinfo_item *item = make_item_for_dump_symtab_node (node); | |
1044 emit_item (item, dump_kind); | |
1045 | |
1046 if (optinfo_enabled_p ()) | |
1047 { | |
1048 optinfo &info = ensure_pending_optinfo (); | |
1049 info.handle_dump_file_kind (dump_kind); | |
1050 info.add_item (item); | |
1051 } | |
1052 else | |
1053 delete item; | |
1054 } | |
1055 | |
1056 /* Get the current dump scope-nesting depth. | |
1057 For use by -fopt-info (for showing nesting via indentation). */ | |
1058 | |
1059 unsigned int | |
1060 dump_context::get_scope_depth () const | |
1061 { | |
1062 return m_scope_depth; | |
1063 } | |
1064 | |
1065 /* Push a nested dump scope. | |
1066 Increment the scope depth. | |
1067 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info | |
1068 destination, if any. | |
1069 Emit a "scope" optinfo if optinfos are enabled. */ | |
1070 | |
1071 void | |
1072 dump_context::begin_scope (const char *name, const dump_location_t &loc) | |
1073 { | |
1074 m_scope_depth++; | |
1075 | |
1076 if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags)) | |
1077 ::dump_loc (MSG_NOTE, dump_file, loc.get_location_t ()); | |
1078 | |
1079 if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags)) | |
1080 ::dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ()); | |
1081 | |
1082 /* Support for temp_dump_context in selftests. */ | |
1083 if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags)) | |
1084 ::dump_loc (MSG_NOTE, m_test_pp, loc.get_location_t ()); | |
1085 | |
1086 pretty_printer pp; | |
1087 pp_printf (&pp, "=== %s ===\n", name); | |
1088 optinfo_item *item | |
1089 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION, | |
1090 xstrdup (pp_formatted_text (&pp))); | |
1091 emit_item (item, MSG_NOTE); | |
1092 | |
1093 if (optinfo_enabled_p ()) | |
1094 { | |
1095 optinfo &info = begin_next_optinfo (loc); | |
1096 info.m_kind = OPTINFO_KIND_SCOPE; | |
1097 info.add_item (item); | |
1098 } | |
1099 else | |
1100 delete item; | |
1101 } | |
1102 | |
1103 /* Pop a nested dump scope. */ | |
1104 | |
1105 void | |
1106 dump_context::end_scope () | |
1107 { | |
1108 end_any_optinfo (); | |
1109 m_scope_depth--; | |
1110 optimization_records_maybe_pop_dump_scope (); | |
1111 } | |
1112 | |
1113 /* Return the optinfo currently being accumulated, creating one if | |
1114 necessary. */ | |
1115 | |
1116 optinfo & | |
1117 dump_context::ensure_pending_optinfo () | |
1118 { | |
1119 if (!m_pending) | |
1120 return begin_next_optinfo (dump_location_t (dump_user_location_t ())); | |
1121 return *m_pending; | |
1122 } | |
1123 | |
1124 /* Start a new optinfo and return it, ending any optinfo that was already | |
1125 accumulated. */ | |
1126 | |
1127 optinfo & | |
1128 dump_context::begin_next_optinfo (const dump_location_t &loc) | |
1129 { | |
1130 end_any_optinfo (); | |
1131 gcc_assert (m_pending == NULL); | |
1132 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass); | |
1133 return *m_pending; | |
1134 } | |
1135 | |
1136 /* End any optinfo that has been accumulated within this context; emitting | |
1137 it to any destinations as appropriate, such as optimization records. */ | |
1138 | |
1139 void | |
1140 dump_context::end_any_optinfo () | |
1141 { | |
1142 if (m_pending) | |
1143 m_pending->emit (); | |
1144 delete m_pending; | |
1145 m_pending = NULL; | |
1146 } | |
1147 | |
1148 /* Emit ITEM to all item destinations (those that don't require | |
1149 consolidation into optinfo instances). */ | |
1150 | |
1151 void | |
1152 dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind) | |
1153 { | |
1154 if (dump_file && apply_dump_filter_p (dump_kind, pflags)) | |
1155 fprintf (dump_file, "%s", item->get_text ()); | |
1156 | |
1157 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags)) | |
1158 fprintf (alt_dump_file, "%s", item->get_text ()); | |
1159 | |
1160 /* Support for temp_dump_context in selftests. */ | |
1161 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags)) | |
1162 pp_string (m_test_pp, item->get_text ()); | |
1163 } | |
1164 | |
1165 /* The current singleton dump_context, and its default. */ | |
1166 | |
1167 dump_context *dump_context::s_current = &dump_context::s_default; | |
1168 dump_context dump_context::s_default; | |
1169 | |
1170 /* Implementation of dump_* API calls, calling into dump_context | |
1171 member functions. */ | |
1172 | |
1173 /* Dump gimple statement GS with SPC indentation spaces and | |
1174 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */ | |
1175 | |
1176 void | |
365 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags, | 1177 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags, |
366 gimple *gs, int spc) | 1178 gimple *gs, int spc) |
367 { | 1179 { |
368 if (dump_file && (dump_kind & pflags)) | 1180 dump_context::get ().dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc); |
369 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); | |
370 | |
371 if (alt_dump_file && (dump_kind & alt_flags)) | |
372 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); | |
373 } | 1181 } |
374 | 1182 |
375 /* Similar to dump_gimple_stmt, except additionally print source location. */ | 1183 /* Similar to dump_gimple_stmt, except additionally print source location. */ |
376 | 1184 |
377 void | 1185 void |
378 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc, | 1186 dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc, |
379 dump_flags_t extra_dump_flags, gimple *gs, int spc) | 1187 dump_flags_t extra_dump_flags, gimple *gs, int spc) |
380 { | 1188 { |
381 if (dump_file && (dump_kind & pflags)) | 1189 dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc, extra_dump_flags, |
382 { | 1190 gs, spc); |
383 dump_loc (dump_kind, dump_file, loc); | 1191 } |
384 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); | 1192 |
385 } | 1193 /* Dump gimple statement GS with SPC indentation spaces and |
386 | 1194 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. |
387 if (alt_dump_file && (dump_kind & alt_flags)) | 1195 Do not terminate with a newline or semicolon. */ |
388 { | 1196 |
389 dump_loc (dump_kind, alt_dump_file, loc); | 1197 void |
390 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); | 1198 dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags, |
391 } | 1199 gimple *gs, int spc) |
1200 { | |
1201 dump_context::get ().dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc); | |
1202 } | |
1203 | |
1204 /* Similar to dump_gimple_expr, except additionally print source location. */ | |
1205 | |
1206 void | |
1207 dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc, | |
1208 dump_flags_t extra_dump_flags, gimple *gs, int spc) | |
1209 { | |
1210 dump_context::get ().dump_gimple_expr_loc (dump_kind, loc, extra_dump_flags, | |
1211 gs, spc); | |
392 } | 1212 } |
393 | 1213 |
394 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if | 1214 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if |
395 DUMP_KIND is enabled. */ | 1215 DUMP_KIND is enabled. */ |
396 | 1216 |
397 void | 1217 void |
398 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags, | 1218 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags, |
399 tree t) | 1219 tree t) |
400 { | 1220 { |
401 if (dump_file && (dump_kind & pflags)) | 1221 dump_context::get ().dump_generic_expr (dump_kind, extra_dump_flags, t); |
402 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); | 1222 } |
403 | |
404 if (alt_dump_file && (dump_kind & alt_flags)) | |
405 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); | |
406 } | |
407 | |
408 | 1223 |
409 /* Similar to dump_generic_expr, except additionally print the source | 1224 /* Similar to dump_generic_expr, except additionally print the source |
410 location. */ | 1225 location. */ |
411 | 1226 |
412 void | 1227 void |
413 dump_generic_expr_loc (int dump_kind, source_location loc, | 1228 dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc, |
414 dump_flags_t extra_dump_flags, tree t) | 1229 dump_flags_t extra_dump_flags, tree t) |
415 { | 1230 { |
416 if (dump_file && (dump_kind & pflags)) | 1231 dump_context::get ().dump_generic_expr_loc (dump_kind, loc, extra_dump_flags, |
417 { | 1232 t); |
418 dump_loc (dump_kind, dump_file, loc); | |
419 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); | |
420 } | |
421 | |
422 if (alt_dump_file && (dump_kind & alt_flags)) | |
423 { | |
424 dump_loc (dump_kind, alt_dump_file, loc); | |
425 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); | |
426 } | |
427 } | 1233 } |
428 | 1234 |
429 /* Output a formatted message using FORMAT on appropriate dump streams. */ | 1235 /* Output a formatted message using FORMAT on appropriate dump streams. */ |
430 | 1236 |
431 void | 1237 void |
432 dump_printf (dump_flags_t dump_kind, const char *format, ...) | 1238 dump_printf (dump_flags_t dump_kind, const char *format, ...) |
433 { | 1239 { |
434 if (dump_file && (dump_kind & pflags)) | 1240 va_list ap; |
435 { | 1241 va_start (ap, format); |
436 va_list ap; | 1242 dump_context::get ().dump_printf_va (dump_kind, format, &ap); |
437 va_start (ap, format); | 1243 va_end (ap); |
438 vfprintf (dump_file, format, ap); | 1244 } |
439 va_end (ap); | 1245 |
440 } | 1246 /* Similar to dump_printf, except source location is also printed, and |
441 | 1247 dump location captured. */ |
442 if (alt_dump_file && (dump_kind & alt_flags)) | 1248 |
443 { | 1249 void |
444 va_list ap; | 1250 dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc, |
445 va_start (ap, format); | |
446 vfprintf (alt_dump_file, format, ap); | |
447 va_end (ap); | |
448 } | |
449 } | |
450 | |
451 /* Similar to dump_printf, except source location is also printed. */ | |
452 | |
453 void | |
454 dump_printf_loc (dump_flags_t dump_kind, source_location loc, | |
455 const char *format, ...) | 1251 const char *format, ...) |
456 { | 1252 { |
457 if (dump_file && (dump_kind & pflags)) | 1253 va_list ap; |
458 { | 1254 va_start (ap, format); |
459 va_list ap; | 1255 dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, &ap); |
460 dump_loc (dump_kind, dump_file, loc); | 1256 va_end (ap); |
461 va_start (ap, format); | 1257 } |
462 vfprintf (dump_file, format, ap); | 1258 |
463 va_end (ap); | 1259 /* Output VALUE in decimal to appropriate dump streams. */ |
464 } | 1260 |
465 | 1261 template<unsigned int N, typename C> |
466 if (alt_dump_file && (dump_kind & alt_flags)) | 1262 void |
467 { | 1263 dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value) |
468 va_list ap; | 1264 { |
469 dump_loc (dump_kind, alt_dump_file, loc); | 1265 dump_context::get ().dump_dec (dump_kind, value); |
470 va_start (ap, format); | 1266 } |
471 vfprintf (alt_dump_file, format, ap); | 1267 |
472 va_end (ap); | 1268 template void dump_dec (dump_flags_t, const poly_uint16 &); |
473 } | 1269 template void dump_dec (dump_flags_t, const poly_int64 &); |
1270 template void dump_dec (dump_flags_t, const poly_uint64 &); | |
1271 template void dump_dec (dump_flags_t, const poly_offset_int &); | |
1272 template void dump_dec (dump_flags_t, const poly_widest_int &); | |
1273 | |
1274 void | |
1275 dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn) | |
1276 { | |
1277 if (dump_file | |
1278 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags)) | |
1279 print_dec (value, dump_file, sgn); | |
1280 | |
1281 if (alt_dump_file | |
1282 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags)) | |
1283 print_dec (value, alt_dump_file, sgn); | |
1284 } | |
1285 | |
1286 /* Output VALUE in hexadecimal to appropriate dump streams. */ | |
1287 | |
1288 void | |
1289 dump_hex (dump_flags_t dump_kind, const poly_wide_int &value) | |
1290 { | |
1291 if (dump_file | |
1292 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags)) | |
1293 print_hex (value, dump_file); | |
1294 | |
1295 if (alt_dump_file | |
1296 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags)) | |
1297 print_hex (value, alt_dump_file); | |
1298 } | |
1299 | |
1300 /* Emit and delete the currently pending optinfo, if there is one, | |
1301 without the caller needing to know about class dump_context. */ | |
1302 | |
1303 void | |
1304 dumpfile_ensure_any_optinfo_are_flushed () | |
1305 { | |
1306 dump_context::get().end_any_optinfo (); | |
1307 } | |
1308 | |
1309 /* Output the name of NODE on appropriate dump streams. */ | |
1310 | |
1311 void | |
1312 dump_symtab_node (dump_flags_t dump_kind, symtab_node *node) | |
1313 { | |
1314 dump_context::get ().dump_symtab_node (dump_kind, node); | |
1315 } | |
1316 | |
1317 /* Get the current dump scope-nesting depth. | |
1318 For use by -fopt-info (for showing nesting via indentation). */ | |
1319 | |
1320 unsigned int | |
1321 get_dump_scope_depth () | |
1322 { | |
1323 return dump_context::get ().get_scope_depth (); | |
1324 } | |
1325 | |
1326 /* Push a nested dump scope. | |
1327 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info | |
1328 destination, if any. | |
1329 Emit a "scope" opinfo if optinfos are enabled. | |
1330 Increment the scope depth. */ | |
1331 | |
1332 void | |
1333 dump_begin_scope (const char *name, const dump_location_t &loc) | |
1334 { | |
1335 dump_context::get ().begin_scope (name, loc); | |
1336 } | |
1337 | |
1338 /* Pop a nested dump scope. */ | |
1339 | |
1340 void | |
1341 dump_end_scope () | |
1342 { | |
1343 dump_context::get ().end_scope (); | |
474 } | 1344 } |
475 | 1345 |
476 /* Start a dump for PHASE. Store user-supplied dump flags in | 1346 /* Start a dump for PHASE. Store user-supplied dump flags in |
477 *FLAG_PTR. Return the number of streams opened. Set globals | 1347 *FLAG_PTR. Return the number of streams opened. Set globals |
478 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and | 1348 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and |
492 | 1362 |
493 dfi = get_dump_file_info (phase); | 1363 dfi = get_dump_file_info (phase); |
494 name = get_dump_file_name (phase); | 1364 name = get_dump_file_name (phase); |
495 if (name) | 1365 if (name) |
496 { | 1366 { |
497 stream = strcmp ("stderr", name) == 0 | 1367 stream = dump_open (name, dfi->pstate < 0); |
498 ? stderr | 1368 if (stream) |
499 : strcmp ("stdout", name) == 0 | |
500 ? stdout | |
501 : fopen (name, dfi->pstate < 0 ? "w" : "a"); | |
502 if (!stream) | |
503 error ("could not open dump file %qs: %m", name); | |
504 else | |
505 { | 1369 { |
506 dfi->pstate = 1; | 1370 dfi->pstate = 1; |
507 count++; | 1371 count++; |
508 } | 1372 } |
509 free (name); | 1373 free (name); |
510 dfi->pstream = stream; | 1374 dfi->pstream = stream; |
511 dump_file = dfi->pstream; | 1375 set_dump_file (dfi->pstream); |
512 /* Initialize current dump flags. */ | 1376 /* Initialize current dump flags. */ |
513 pflags = dfi->pflags; | 1377 pflags = dfi->pflags; |
514 } | 1378 } |
515 | 1379 |
516 stream = dump_open_alternate_stream (dfi); | 1380 stream = dump_open_alternate_stream (dfi); |
517 if (stream) | 1381 if (stream) |
518 { | 1382 { |
519 dfi->alt_stream = stream; | 1383 dfi->alt_stream = stream; |
520 count++; | 1384 count++; |
521 alt_dump_file = dfi->alt_stream; | 1385 set_alt_dump_file (dfi->alt_stream); |
522 /* Initialize current -fopt-info flags. */ | 1386 /* Initialize current -fopt-info flags. */ |
523 alt_flags = dfi->alt_flags; | 1387 alt_flags = dfi->alt_flags; |
524 } | 1388 } |
525 | 1389 |
526 if (flag_ptr) | 1390 if (flag_ptr) |
539 struct dump_file_info *dfi; | 1403 struct dump_file_info *dfi; |
540 | 1404 |
541 if (phase < 0) | 1405 if (phase < 0) |
542 return; | 1406 return; |
543 dfi = get_dump_file_info (phase); | 1407 dfi = get_dump_file_info (phase); |
544 if (dfi->pstream && (!dfi->pfilename | 1408 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr) |
545 || (strcmp ("stderr", dfi->pfilename) != 0 | |
546 && strcmp ("stdout", dfi->pfilename) != 0))) | |
547 fclose (dfi->pstream); | 1409 fclose (dfi->pstream); |
548 | 1410 |
549 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0 | 1411 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr) |
550 && strcmp ("stdout", dfi->alt_filename) != 0) | |
551 fclose (dfi->alt_stream); | 1412 fclose (dfi->alt_stream); |
552 | 1413 |
553 dfi->alt_stream = NULL; | 1414 dfi->alt_stream = NULL; |
554 dfi->pstream = NULL; | 1415 dfi->pstream = NULL; |
555 dump_file = NULL; | 1416 set_dump_file (NULL); |
556 alt_dump_file = NULL; | 1417 set_alt_dump_file (NULL); |
557 dump_flags = TDI_none; | 1418 dump_flags = TDF_NONE; |
558 alt_flags = 0; | 1419 alt_flags = TDF_NONE; |
559 pflags = 0; | 1420 pflags = TDF_NONE; |
560 } | 1421 } |
561 | 1422 |
562 /* Begin a tree dump for PHASE. Stores any user supplied flag in | 1423 /* Begin a tree dump for PHASE. Stores any user supplied flag in |
563 *FLAG_PTR and returns a stream to write to. If the dump is not | 1424 *FLAG_PTR and returns a stream to write to. If the dump is not |
564 enabled, returns NULL. | 1425 enabled, returns NULL. |
565 Multiple calls will reopen and append to the dump file. */ | 1426 PART can be used for dump files which should be split to multiple |
1427 parts. PART == -1 indicates dump file with no parts. | |
1428 If PART is -1, multiple calls will reopen and append to the dump file. */ | |
566 | 1429 |
567 FILE * | 1430 FILE * |
568 dump_begin (int phase, dump_flags_t *flag_ptr) | 1431 dump_begin (int phase, dump_flags_t *flag_ptr, int part) |
569 { | 1432 { |
570 return g->get_dumps ()->dump_begin (phase, flag_ptr); | 1433 return g->get_dumps ()->dump_begin (phase, flag_ptr, part); |
571 } | 1434 } |
572 | 1435 |
573 FILE * | 1436 FILE * |
574 gcc::dump_manager:: | 1437 gcc::dump_manager:: |
575 dump_begin (int phase, dump_flags_t *flag_ptr) | 1438 dump_begin (int phase, dump_flags_t *flag_ptr, int part) |
576 { | 1439 { |
577 char *name; | 1440 char *name; |
578 struct dump_file_info *dfi; | 1441 struct dump_file_info *dfi; |
579 FILE *stream; | 1442 FILE *stream; |
580 | 1443 |
581 if (phase == TDI_none || !dump_phase_enabled_p (phase)) | 1444 if (phase == TDI_none || !dump_phase_enabled_p (phase)) |
582 return NULL; | 1445 return NULL; |
583 | 1446 |
584 name = get_dump_file_name (phase); | 1447 name = get_dump_file_name (phase, part); |
585 if (!name) | 1448 if (!name) |
586 return NULL; | 1449 return NULL; |
587 dfi = get_dump_file_info (phase); | 1450 dfi = get_dump_file_info (phase); |
588 | 1451 |
589 stream = strcmp ("stderr", name) == 0 | 1452 /* We do not support re-opening of dump files with parts. This would require |
590 ? stderr | 1453 tracking pstate per part of the dump file. */ |
591 : strcmp ("stdout", name) == 0 | 1454 stream = dump_open (name, part != -1 || dfi->pstate < 0); |
592 ? stdout | 1455 if (stream) |
593 : fopen (name, dfi->pstate < 0 ? "w" : "a"); | |
594 | |
595 if (!stream) | |
596 error ("could not open dump file %qs: %m", name); | |
597 else | |
598 dfi->pstate = 1; | 1456 dfi->pstate = 1; |
599 free (name); | 1457 free (name); |
600 | 1458 |
601 if (flag_ptr) | 1459 if (flag_ptr) |
602 *flag_ptr = dfi->pflags; | 1460 *flag_ptr = dfi->pflags; |
656 { | 1514 { |
657 struct dump_file_info *dfi = get_dump_file_info (phase); | 1515 struct dump_file_info *dfi = get_dump_file_info (phase); |
658 return dfi->swtch; | 1516 return dfi->swtch; |
659 } | 1517 } |
660 | 1518 |
1519 /* Handle -fdump-* and -fopt-info for a pass added after | |
1520 command-line options are parsed (those from plugins and | |
1521 those from backends). | |
1522 | |
1523 Because the registration of plugin/backend passes happens after the | |
1524 command-line options are parsed, the options that specify single | |
1525 pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new | |
1526 passes. Therefore we currently can only enable dumping of | |
1527 new passes when the 'dump-all' flags (e.g. -fdump-tree-all) | |
1528 are specified. This is done here. | |
1529 | |
1530 Similarly, the saved -fopt-info options are wired up to the new pass. */ | |
1531 | |
1532 void | |
1533 gcc::dump_manager::register_pass (opt_pass *pass) | |
1534 { | |
1535 gcc_assert (pass); | |
1536 | |
1537 register_one_dump_file (pass); | |
1538 | |
1539 dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number); | |
1540 gcc_assert (pass_dfi); | |
1541 | |
1542 enum tree_dump_index tdi; | |
1543 if (pass->type == SIMPLE_IPA_PASS | |
1544 || pass->type == IPA_PASS) | |
1545 tdi = TDI_ipa_all; | |
1546 else if (pass->type == GIMPLE_PASS) | |
1547 tdi = TDI_tree_all; | |
1548 else | |
1549 tdi = TDI_rtl_all; | |
1550 const dump_file_info *tdi_dfi = get_dump_file_info (tdi); | |
1551 gcc_assert (tdi_dfi); | |
1552 | |
1553 /* Check if dump-all flag is specified. */ | |
1554 if (tdi_dfi->pstate) | |
1555 { | |
1556 pass_dfi->pstate = tdi_dfi->pstate; | |
1557 pass_dfi->pflags = tdi_dfi->pflags; | |
1558 } | |
1559 | |
1560 update_dfi_for_opt_info (pass_dfi); | |
1561 } | |
1562 | |
661 /* Finish a tree dump for PHASE. STREAM is the stream created by | 1563 /* Finish a tree dump for PHASE. STREAM is the stream created by |
662 dump_begin. */ | 1564 dump_begin. */ |
663 | 1565 |
664 void | 1566 void |
665 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) | 1567 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) |
678 int n = 0; | 1580 int n = 0; |
679 size_t i; | 1581 size_t i; |
680 | 1582 |
681 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) | 1583 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) |
682 { | 1584 { |
683 if ((dump_files[i].dkind == dkind)) | 1585 if (dump_files[i].dkind == dkind) |
684 { | 1586 { |
685 const char *old_filename = dump_files[i].pfilename; | 1587 const char *old_filename = dump_files[i].pfilename; |
686 dump_files[i].pstate = -1; | 1588 dump_files[i].pstate = -1; |
687 dump_files[i].pflags |= flags; | 1589 dump_files[i].pflags |= flags; |
688 n++; | 1590 n++; |
699 } | 1601 } |
700 } | 1602 } |
701 | 1603 |
702 for (i = 0; i < m_extra_dump_files_in_use; i++) | 1604 for (i = 0; i < m_extra_dump_files_in_use; i++) |
703 { | 1605 { |
704 if ((m_extra_dump_files[i].dkind == dkind)) | 1606 if (m_extra_dump_files[i].dkind == dkind) |
705 { | 1607 { |
706 const char *old_filename = m_extra_dump_files[i].pfilename; | 1608 const char *old_filename = m_extra_dump_files[i].pfilename; |
707 m_extra_dump_files[i].pstate = -1; | 1609 m_extra_dump_files[i].pstate = -1; |
708 m_extra_dump_files[i].pflags |= flags; | 1610 m_extra_dump_files[i].pflags |= flags; |
709 n++; | 1611 n++; |
727 Enable dumps with FLAGS on FILENAME. Return the number of enabled | 1629 Enable dumps with FLAGS on FILENAME. Return the number of enabled |
728 dumps. */ | 1630 dumps. */ |
729 | 1631 |
730 int | 1632 int |
731 gcc::dump_manager:: | 1633 gcc::dump_manager:: |
732 opt_info_enable_passes (int optgroup_flags, dump_flags_t flags, | 1634 opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags, |
733 const char *filename) | 1635 const char *filename) |
734 { | 1636 { |
735 int n = 0; | 1637 int n = 0; |
736 size_t i; | 1638 |
737 | 1639 m_optgroup_flags = optgroup_flags; |
738 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) | 1640 m_optinfo_flags = flags; |
739 { | 1641 m_optinfo_filename = xstrdup (filename); |
740 if ((dump_files[i].optgroup_flags & optgroup_flags)) | 1642 |
741 { | 1643 for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++) |
742 const char *old_filename = dump_files[i].alt_filename; | 1644 if (update_dfi_for_opt_info (&dump_files[i])) |
743 /* Since this file is shared among different passes, it | 1645 n++; |
744 should be opened in append mode. */ | 1646 |
745 dump_files[i].alt_state = 1; | 1647 for (size_t i = 0; i < m_extra_dump_files_in_use; i++) |
746 dump_files[i].alt_flags |= flags; | 1648 if (update_dfi_for_opt_info (&m_extra_dump_files[i])) |
747 n++; | 1649 n++; |
748 /* Override the existing filename. */ | |
749 if (filename) | |
750 dump_files[i].alt_filename = xstrdup (filename); | |
751 if (old_filename && filename != old_filename) | |
752 free (CONST_CAST (char *, old_filename)); | |
753 } | |
754 } | |
755 | |
756 for (i = 0; i < m_extra_dump_files_in_use; i++) | |
757 { | |
758 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags)) | |
759 { | |
760 const char *old_filename = m_extra_dump_files[i].alt_filename; | |
761 /* Since this file is shared among different passes, it | |
762 should be opened in append mode. */ | |
763 m_extra_dump_files[i].alt_state = 1; | |
764 m_extra_dump_files[i].alt_flags |= flags; | |
765 n++; | |
766 /* Override the existing filename. */ | |
767 if (filename) | |
768 m_extra_dump_files[i].alt_filename = xstrdup (filename); | |
769 if (old_filename && filename != old_filename) | |
770 free (CONST_CAST (char *, old_filename)); | |
771 } | |
772 } | |
773 | 1650 |
774 return n; | 1651 return n; |
1652 } | |
1653 | |
1654 /* Use the saved -fopt-info options to update DFI. | |
1655 Return true if the dump is enabled. */ | |
1656 | |
1657 bool | |
1658 gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const | |
1659 { | |
1660 gcc_assert (dfi); | |
1661 | |
1662 if (!(dfi->optgroup_flags & m_optgroup_flags)) | |
1663 return false; | |
1664 | |
1665 const char *old_filename = dfi->alt_filename; | |
1666 /* Since this file is shared among different passes, it | |
1667 should be opened in append mode. */ | |
1668 dfi->alt_state = 1; | |
1669 dfi->alt_flags |= m_optinfo_flags; | |
1670 /* Override the existing filename. */ | |
1671 if (m_optinfo_filename) | |
1672 dfi->alt_filename = xstrdup (m_optinfo_filename); | |
1673 if (old_filename && m_optinfo_filename != old_filename) | |
1674 free (CONST_CAST (char *, old_filename)); | |
1675 | |
1676 return true; | |
775 } | 1677 } |
776 | 1678 |
777 /* Parse ARG as a dump switch. Return nonzero if it is, and store the | 1679 /* Parse ARG as a dump switch. Return nonzero if it is, and store the |
778 relevant details in the dump_files array. */ | 1680 relevant details in the dump_files array. */ |
779 | 1681 |
794 | 1696 |
795 if (*option_value && *option_value != '-' && *option_value != '=') | 1697 if (*option_value && *option_value != '-' && *option_value != '=') |
796 return 0; | 1698 return 0; |
797 | 1699 |
798 ptr = option_value; | 1700 ptr = option_value; |
799 flags = 0; | 1701 |
1702 /* Retain "user-facing" and "internals" messages, but filter out | |
1703 those from an opt_problem being re-emitted at the top level | |
1704 (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages | |
1705 messing up scan-tree-dump-times" in DejaGnu tests. */ | |
1706 flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_INTERNALS; | |
800 | 1707 |
801 while (*ptr) | 1708 while (*ptr) |
802 { | 1709 { |
803 const struct dump_option_value_info *option_ptr; | 1710 const struct kv_pair<dump_flags_t> *option_ptr; |
804 const char *end_ptr; | 1711 const char *end_ptr; |
805 const char *eq_ptr; | 1712 const char *eq_ptr; |
806 unsigned length; | 1713 unsigned length; |
807 | 1714 |
808 while (*ptr == '-') | 1715 while (*ptr == '-') |
880 | 1787 |
881 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags | 1788 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags |
882 and filename. Return non-zero if it is a recognized switch. */ | 1789 and filename. Return non-zero if it is a recognized switch. */ |
883 | 1790 |
884 static int | 1791 static int |
885 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags, | 1792 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, |
886 char **filename) | 1793 optgroup_flags_t *optgroup_flags, char **filename) |
887 { | 1794 { |
888 const char *option_value; | 1795 const char *option_value; |
889 const char *ptr; | 1796 const char *ptr; |
890 | 1797 |
891 option_value = arg; | 1798 option_value = arg; |
892 ptr = option_value; | 1799 ptr = option_value; |
893 | 1800 |
894 *filename = NULL; | 1801 *filename = NULL; |
895 *flags = 0; | 1802 |
896 *optgroup_flags = 0; | 1803 /* Default to filtering out "internals" messages, and retaining |
1804 "user-facing" messages, and those from an opt_problem being | |
1805 re-emitted at the top level. */ | |
1806 *flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_REEMITTED; | |
1807 | |
1808 *optgroup_flags = OPTGROUP_NONE; | |
897 | 1809 |
898 if (!ptr) | 1810 if (!ptr) |
899 return 1; /* Handle '-fopt-info' without any additional options. */ | 1811 return 1; /* Handle '-fopt-info' without any additional options. */ |
900 | 1812 |
901 while (*ptr) | 1813 while (*ptr) |
902 { | 1814 { |
903 const struct dump_option_value_info *option_ptr; | |
904 const char *end_ptr; | 1815 const char *end_ptr; |
905 const char *eq_ptr; | 1816 const char *eq_ptr; |
906 unsigned length; | 1817 unsigned length; |
907 | 1818 |
908 while (*ptr == '-') | 1819 while (*ptr == '-') |
915 | 1826 |
916 if (!end_ptr) | 1827 if (!end_ptr) |
917 end_ptr = ptr + strlen (ptr); | 1828 end_ptr = ptr + strlen (ptr); |
918 length = end_ptr - ptr; | 1829 length = end_ptr - ptr; |
919 | 1830 |
920 for (option_ptr = optinfo_verbosity_options; option_ptr->name; | 1831 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options; |
921 option_ptr++) | 1832 option_ptr->name; option_ptr++) |
922 if (strlen (option_ptr->name) == length | 1833 if (strlen (option_ptr->name) == length |
923 && !memcmp (option_ptr->name, ptr, length)) | 1834 && !memcmp (option_ptr->name, ptr, length)) |
924 { | 1835 { |
925 *flags |= option_ptr->value; | 1836 *flags |= option_ptr->value; |
926 goto found; | 1837 goto found; |
927 } | 1838 } |
928 | 1839 |
929 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++) | 1840 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options; |
1841 option_ptr->name; option_ptr++) | |
930 if (strlen (option_ptr->name) == length | 1842 if (strlen (option_ptr->name) == length |
931 && !memcmp (option_ptr->name, ptr, length)) | 1843 && !memcmp (option_ptr->name, ptr, length)) |
932 { | 1844 { |
933 *optgroup_flags |= option_ptr->value; | 1845 *optgroup_flags |= option_ptr->value; |
934 goto found; | 1846 goto found; |
959 | 1871 |
960 int | 1872 int |
961 opt_info_switch_p (const char *arg) | 1873 opt_info_switch_p (const char *arg) |
962 { | 1874 { |
963 dump_flags_t flags; | 1875 dump_flags_t flags; |
964 int optgroup_flags; | 1876 optgroup_flags_t optgroup_flags; |
965 char *filename; | 1877 char *filename; |
966 static char *file_seen = NULL; | 1878 static char *file_seen = NULL; |
967 gcc::dump_manager *dumps = g->get_dumps (); | 1879 gcc::dump_manager *dumps = g->get_dumps (); |
968 | 1880 |
969 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename)) | 1881 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename)) |
979 arg); | 1891 arg); |
980 return 1; | 1892 return 1; |
981 } | 1893 } |
982 | 1894 |
983 file_seen = xstrdup (filename); | 1895 file_seen = xstrdup (filename); |
984 if (!flags) | 1896 if (!(flags & MSG_ALL_KINDS)) |
985 flags = MSG_OPTIMIZED_LOCATIONS; | 1897 flags |= MSG_OPTIMIZED_LOCATIONS; |
986 if (!optgroup_flags) | 1898 if (!optgroup_flags) |
987 optgroup_flags = OPTGROUP_ALL; | 1899 optgroup_flags = OPTGROUP_ALL; |
988 | 1900 |
989 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename); | 1901 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename); |
990 } | 1902 } |
991 | 1903 |
992 /* Print basic block on the dump streams. */ | 1904 /* Print basic block on the dump streams. */ |
993 | 1905 |
994 void | 1906 void |
995 dump_basic_block (int dump_kind, basic_block bb, int indent) | 1907 dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent) |
996 { | 1908 { |
997 if (dump_file && (dump_kind & pflags)) | 1909 if (dump_file |
1910 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags)) | |
998 dump_bb (dump_file, bb, indent, TDF_DETAILS); | 1911 dump_bb (dump_file, bb, indent, TDF_DETAILS); |
999 if (alt_dump_file && (dump_kind & alt_flags)) | 1912 if (alt_dump_file |
1913 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags)) | |
1000 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS); | 1914 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS); |
1001 } | 1915 } |
1002 | 1916 |
1003 /* Dump FUNCTION_DECL FN as tree dump PHASE. */ | 1917 /* Dump FUNCTION_DECL FN as tree dump PHASE. */ |
1004 | 1918 |
1034 int num_enabled = | 1948 int num_enabled = |
1035 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS, | 1949 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS, |
1036 NULL); | 1950 NULL); |
1037 return num_enabled > 0; | 1951 return num_enabled > 0; |
1038 } | 1952 } |
1953 | |
1954 #if CHECKING_P | |
1955 | |
1956 namespace selftest { | |
1957 | |
1958 /* temp_dump_context's ctor. Temporarily override the dump_context | |
1959 (to forcibly enable optinfo-generation). */ | |
1960 | |
1961 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo, | |
1962 bool forcibly_enable_dumping, | |
1963 dump_flags_t test_pp_flags) | |
1964 : m_context (), | |
1965 m_saved (&dump_context ().get ()) | |
1966 { | |
1967 dump_context::s_current = &m_context; | |
1968 m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo; | |
1969 /* Conditionally enable the test dump, so that we can verify both the | |
1970 dump_enabled_p and the !dump_enabled_p cases in selftests. */ | |
1971 if (forcibly_enable_dumping) | |
1972 { | |
1973 m_context.m_test_pp = &m_pp; | |
1974 m_context.m_test_pp_flags = test_pp_flags; | |
1975 } | |
1976 | |
1977 dump_context::get ().refresh_dumps_are_enabled (); | |
1978 } | |
1979 | |
1980 /* temp_dump_context's dtor. Restore the saved dump_context. */ | |
1981 | |
1982 temp_dump_context::~temp_dump_context () | |
1983 { | |
1984 dump_context::s_current = m_saved; | |
1985 | |
1986 dump_context::get ().refresh_dumps_are_enabled (); | |
1987 } | |
1988 | |
1989 /* 0-terminate the text dumped so far, and return it. */ | |
1990 | |
1991 const char * | |
1992 temp_dump_context::get_dumped_text () | |
1993 { | |
1994 return pp_formatted_text (&m_pp); | |
1995 } | |
1996 | |
1997 /* Verify that the dump_location_t constructors capture the source location | |
1998 at which they were called (provided that the build compiler is sufficiently | |
1999 recent). */ | |
2000 | |
2001 static void | |
2002 test_impl_location () | |
2003 { | |
2004 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) | |
2005 /* Default ctor. */ | |
2006 { | |
2007 dump_location_t loc; | |
2008 const int expected_line = __LINE__ - 1; | |
2009 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c"); | |
2010 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line); | |
2011 } | |
2012 | |
2013 /* Constructing from a gimple. */ | |
2014 { | |
2015 dump_location_t loc ((gimple *)NULL); | |
2016 const int expected_line = __LINE__ - 1; | |
2017 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c"); | |
2018 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line); | |
2019 } | |
2020 | |
2021 /* Constructing from an rtx_insn. */ | |
2022 { | |
2023 dump_location_t loc ((rtx_insn *)NULL); | |
2024 const int expected_line = __LINE__ - 1; | |
2025 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c"); | |
2026 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line); | |
2027 } | |
2028 #endif | |
2029 } | |
2030 | |
2031 /* Verify that the text dumped so far in CONTEXT equals | |
2032 EXPECTED_TEXT, using LOC for the location of any failure. | |
2033 As a side-effect, the internal buffer is 0-terminated. */ | |
2034 | |
2035 void | |
2036 verify_dumped_text (const location &loc, | |
2037 temp_dump_context *context, | |
2038 const char *expected_text) | |
2039 { | |
2040 gcc_assert (context); | |
2041 ASSERT_STREQ_AT (loc, context->get_dumped_text (), | |
2042 expected_text); | |
2043 } | |
2044 | |
2045 /* Verify that ITEM has the expected values. */ | |
2046 | |
2047 void | |
2048 verify_item (const location &loc, | |
2049 const optinfo_item *item, | |
2050 enum optinfo_item_kind expected_kind, | |
2051 location_t expected_location, | |
2052 const char *expected_text) | |
2053 { | |
2054 ASSERT_EQ_AT (loc, item->get_kind (), expected_kind); | |
2055 ASSERT_EQ_AT (loc, item->get_location (), expected_location); | |
2056 ASSERT_STREQ_AT (loc, item->get_text (), expected_text); | |
2057 } | |
2058 | |
2059 /* Verify that calls to the dump_* API are captured and consolidated into | |
2060 optimization records. */ | |
2061 | |
2062 static void | |
2063 test_capture_of_dump_calls (const line_table_case &case_) | |
2064 { | |
2065 /* Generate a location_t for testing. */ | |
2066 line_table_test ltt (case_); | |
2067 linemap_add (line_table, LC_ENTER, false, "test.txt", 0); | |
2068 linemap_line_start (line_table, 5, 100); | |
2069 linemap_add (line_table, LC_LEAVE, false, NULL, 0); | |
2070 location_t where = linemap_position_for_column (line_table, 10); | |
2071 if (where > LINE_MAP_MAX_LOCATION_WITH_COLS) | |
2072 return; | |
2073 | |
2074 dump_location_t loc = dump_location_t::from_location_t (where); | |
2075 | |
2076 gimple *stmt = gimple_build_return (NULL); | |
2077 gimple_set_location (stmt, where); | |
2078 | |
2079 tree test_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, | |
2080 get_identifier ("test_decl"), | |
2081 integer_type_node); | |
2082 /* Run all tests twice, with and then without optinfo enabled, to ensure | |
2083 that immediate destinations vs optinfo-based destinations both | |
2084 work, independently of each other, with no leaks. */ | |
2085 for (int i = 0 ; i < 2; i++) | |
2086 { | |
2087 bool with_optinfo = (i == 0); | |
2088 | |
2089 /* Test of dump_printf. */ | |
2090 { | |
2091 temp_dump_context tmp (with_optinfo, true, | |
2092 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2093 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo"); | |
2094 | |
2095 ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo"); | |
2096 if (with_optinfo) | |
2097 { | |
2098 optinfo *info = tmp.get_pending_optinfo (); | |
2099 ASSERT_TRUE (info != NULL); | |
2100 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2101 ASSERT_EQ (info->num_items (), 1); | |
2102 ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo"); | |
2103 } | |
2104 } | |
2105 | |
2106 /* Test of dump_printf with %T. */ | |
2107 { | |
2108 temp_dump_context tmp (with_optinfo, true, | |
2109 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2110 dump_printf (MSG_NOTE, "tree: %T", integer_zero_node); | |
2111 | |
2112 ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0"); | |
2113 if (with_optinfo) | |
2114 { | |
2115 optinfo *info = tmp.get_pending_optinfo (); | |
2116 ASSERT_TRUE (info != NULL); | |
2117 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2118 ASSERT_EQ (info->num_items (), 2); | |
2119 ASSERT_IS_TEXT (info->get_item (0), "tree: "); | |
2120 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0"); | |
2121 } | |
2122 } | |
2123 | |
2124 /* Test of dump_printf with %E. */ | |
2125 { | |
2126 temp_dump_context tmp (with_optinfo, true, | |
2127 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2128 dump_printf (MSG_NOTE, "gimple: %E", stmt); | |
2129 | |
2130 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;"); | |
2131 if (with_optinfo) | |
2132 { | |
2133 optinfo *info = tmp.get_pending_optinfo (); | |
2134 ASSERT_TRUE (info != NULL); | |
2135 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2136 ASSERT_EQ (info->num_items (), 2); | |
2137 ASSERT_IS_TEXT (info->get_item (0), "gimple: "); | |
2138 ASSERT_IS_GIMPLE (info->get_item (1), where, "return;"); | |
2139 } | |
2140 } | |
2141 | |
2142 /* Test of dump_printf with %G. */ | |
2143 { | |
2144 temp_dump_context tmp (with_optinfo, true, | |
2145 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2146 dump_printf (MSG_NOTE, "gimple: %G", stmt); | |
2147 | |
2148 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n"); | |
2149 if (with_optinfo) | |
2150 { | |
2151 optinfo *info = tmp.get_pending_optinfo (); | |
2152 ASSERT_TRUE (info != NULL); | |
2153 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2154 ASSERT_EQ (info->num_items (), 2); | |
2155 ASSERT_IS_TEXT (info->get_item (0), "gimple: "); | |
2156 ASSERT_IS_GIMPLE (info->get_item (1), where, "return;\n"); | |
2157 } | |
2158 } | |
2159 | |
2160 /* dump_print_loc with multiple format codes. This tests various | |
2161 things: | |
2162 - intermingling of text, format codes handled by the base | |
2163 pretty_printer, and dump-specific format codes | |
2164 - multiple dump-specific format codes: some consecutive, others | |
2165 separated by text, trailing text after the final one. */ | |
2166 { | |
2167 temp_dump_context tmp (with_optinfo, true, | |
2168 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2169 dump_printf_loc (MSG_NOTE, loc, "before %T and %T" | |
2170 " %i consecutive %E%E after\n", | |
2171 integer_zero_node, test_decl, 42, stmt, stmt); | |
2172 | |
2173 ASSERT_DUMPED_TEXT_EQ (tmp, | |
2174 "test.txt:5:10: note: before 0 and test_decl" | |
2175 " 42 consecutive return;return; after\n"); | |
2176 if (with_optinfo) | |
2177 { | |
2178 optinfo *info = tmp.get_pending_optinfo (); | |
2179 ASSERT_TRUE (info != NULL); | |
2180 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2181 ASSERT_EQ (info->num_items (), 8); | |
2182 ASSERT_IS_TEXT (info->get_item (0), "before "); | |
2183 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0"); | |
2184 ASSERT_IS_TEXT (info->get_item (2), " and "); | |
2185 ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl"); | |
2186 ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive "); | |
2187 ASSERT_IS_GIMPLE (info->get_item (5), where, "return;"); | |
2188 ASSERT_IS_GIMPLE (info->get_item (6), where, "return;"); | |
2189 ASSERT_IS_TEXT (info->get_item (7), " after\n"); | |
2190 } | |
2191 } | |
2192 | |
2193 /* Tree, via dump_generic_expr. */ | |
2194 { | |
2195 temp_dump_context tmp (with_optinfo, true, | |
2196 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2197 dump_printf_loc (MSG_NOTE, loc, "test of tree: "); | |
2198 dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node); | |
2199 | |
2200 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0"); | |
2201 if (with_optinfo) | |
2202 { | |
2203 optinfo *info = tmp.get_pending_optinfo (); | |
2204 ASSERT_TRUE (info != NULL); | |
2205 ASSERT_EQ (info->get_location_t (), where); | |
2206 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2207 ASSERT_EQ (info->num_items (), 2); | |
2208 ASSERT_IS_TEXT (info->get_item (0), "test of tree: "); | |
2209 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0"); | |
2210 } | |
2211 } | |
2212 | |
2213 /* Tree, via dump_generic_expr_loc. */ | |
2214 { | |
2215 temp_dump_context tmp (with_optinfo, true, | |
2216 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2217 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node); | |
2218 | |
2219 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1"); | |
2220 if (with_optinfo) | |
2221 { | |
2222 optinfo *info = tmp.get_pending_optinfo (); | |
2223 ASSERT_TRUE (info != NULL); | |
2224 ASSERT_EQ (info->get_location_t (), where); | |
2225 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE); | |
2226 ASSERT_EQ (info->num_items (), 1); | |
2227 ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1"); | |
2228 } | |
2229 } | |
2230 | |
2231 /* Gimple. */ | |
2232 { | |
2233 /* dump_gimple_stmt_loc. */ | |
2234 { | |
2235 temp_dump_context tmp (with_optinfo, true, | |
2236 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2237 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2); | |
2238 | |
2239 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n"); | |
2240 if (with_optinfo) | |
2241 { | |
2242 optinfo *info = tmp.get_pending_optinfo (); | |
2243 ASSERT_TRUE (info != NULL); | |
2244 ASSERT_EQ (info->num_items (), 1); | |
2245 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n"); | |
2246 } | |
2247 } | |
2248 | |
2249 /* dump_gimple_stmt. */ | |
2250 { | |
2251 temp_dump_context tmp (with_optinfo, true, | |
2252 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2253 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2); | |
2254 | |
2255 ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n"); | |
2256 if (with_optinfo) | |
2257 { | |
2258 optinfo *info = tmp.get_pending_optinfo (); | |
2259 ASSERT_TRUE (info != NULL); | |
2260 ASSERT_EQ (info->num_items (), 1); | |
2261 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n"); | |
2262 } | |
2263 } | |
2264 | |
2265 /* dump_gimple_expr_loc. */ | |
2266 { | |
2267 temp_dump_context tmp (with_optinfo, true, | |
2268 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2269 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2); | |
2270 | |
2271 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;"); | |
2272 if (with_optinfo) | |
2273 { | |
2274 optinfo *info = tmp.get_pending_optinfo (); | |
2275 ASSERT_TRUE (info != NULL); | |
2276 ASSERT_EQ (info->num_items (), 1); | |
2277 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;"); | |
2278 } | |
2279 } | |
2280 | |
2281 /* dump_gimple_expr. */ | |
2282 { | |
2283 temp_dump_context tmp (with_optinfo, true, | |
2284 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2285 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2); | |
2286 | |
2287 ASSERT_DUMPED_TEXT_EQ (tmp, "return;"); | |
2288 if (with_optinfo) | |
2289 { | |
2290 optinfo *info = tmp.get_pending_optinfo (); | |
2291 ASSERT_TRUE (info != NULL); | |
2292 ASSERT_EQ (info->num_items (), 1); | |
2293 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;"); | |
2294 } | |
2295 } | |
2296 } | |
2297 | |
2298 /* poly_int. */ | |
2299 { | |
2300 temp_dump_context tmp (with_optinfo, true, | |
2301 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING); | |
2302 dump_dec (MSG_NOTE, poly_int64 (42)); | |
2303 | |
2304 ASSERT_DUMPED_TEXT_EQ (tmp, "42"); | |
2305 if (with_optinfo) | |
2306 { | |
2307 optinfo *info = tmp.get_pending_optinfo (); | |
2308 ASSERT_TRUE (info != NULL); | |
2309 ASSERT_EQ (info->num_items (), 1); | |
2310 ASSERT_IS_TEXT (info->get_item (0), "42"); | |
2311 } | |
2312 } | |
2313 | |
2314 /* Scopes. Test with all 4 combinations of | |
2315 filtering by MSG_PRIORITY_USER_FACING | |
2316 and/or filtering by MSG_PRIORITY_INTERNALS. */ | |
2317 for (int j = 0; j < 3; j++) | |
2318 { | |
2319 dump_flags_t dump_filter = MSG_ALL_KINDS; | |
2320 if (j % 2) | |
2321 dump_filter |= MSG_PRIORITY_USER_FACING; | |
2322 if (j / 2) | |
2323 dump_filter |= MSG_PRIORITY_INTERNALS; | |
2324 | |
2325 temp_dump_context tmp (with_optinfo, true, dump_filter); | |
2326 /* Emit various messages, mostly with implicit priority. */ | |
2327 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n"); | |
2328 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt, | |
2329 "explicitly internal msg\n"); | |
2330 { | |
2331 AUTO_DUMP_SCOPE ("outer scope", stmt); | |
2332 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n"); | |
2333 { | |
2334 AUTO_DUMP_SCOPE ("middle scope", stmt); | |
2335 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n"); | |
2336 { | |
2337 AUTO_DUMP_SCOPE ("inner scope", stmt); | |
2338 dump_printf_loc (MSG_NOTE, stmt, "msg 4\n"); | |
2339 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt, | |
2340 "explicitly user-facing msg\n"); | |
2341 } | |
2342 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n"); | |
2343 } | |
2344 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n"); | |
2345 } | |
2346 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n"); | |
2347 | |
2348 switch (dump_filter & MSG_ALL_PRIORITIES) | |
2349 { | |
2350 default: | |
2351 gcc_unreachable (); | |
2352 case 0: | |
2353 ASSERT_DUMPED_TEXT_EQ (tmp, ""); | |
2354 break; | |
2355 case MSG_PRIORITY_USER_FACING: | |
2356 ASSERT_DUMPED_TEXT_EQ | |
2357 (tmp, | |
2358 "test.txt:5:10: note: msg 1\n" | |
2359 "test.txt:5:10: note: explicitly user-facing msg\n" | |
2360 "test.txt:5:10: note: msg 7\n"); | |
2361 break; | |
2362 case MSG_PRIORITY_INTERNALS: | |
2363 ASSERT_DUMPED_TEXT_EQ | |
2364 (tmp, | |
2365 "test.txt:5:10: note: explicitly internal msg\n" | |
2366 "test.txt:5:10: note: === outer scope ===\n" | |
2367 "test.txt:5:10: note: msg 2\n" | |
2368 "test.txt:5:10: note: === middle scope ===\n" | |
2369 "test.txt:5:10: note: msg 3\n" | |
2370 "test.txt:5:10: note: === inner scope ===\n" | |
2371 "test.txt:5:10: note: msg 4\n" | |
2372 "test.txt:5:10: note: msg 5\n" | |
2373 "test.txt:5:10: note: msg 6\n"); | |
2374 break; | |
2375 case MSG_ALL_PRIORITIES: | |
2376 ASSERT_DUMPED_TEXT_EQ | |
2377 (tmp, | |
2378 "test.txt:5:10: note: msg 1\n" | |
2379 "test.txt:5:10: note: explicitly internal msg\n" | |
2380 "test.txt:5:10: note: === outer scope ===\n" | |
2381 "test.txt:5:10: note: msg 2\n" | |
2382 "test.txt:5:10: note: === middle scope ===\n" | |
2383 "test.txt:5:10: note: msg 3\n" | |
2384 "test.txt:5:10: note: === inner scope ===\n" | |
2385 "test.txt:5:10: note: msg 4\n" | |
2386 "test.txt:5:10: note: explicitly user-facing msg\n" | |
2387 "test.txt:5:10: note: msg 5\n" | |
2388 "test.txt:5:10: note: msg 6\n" | |
2389 "test.txt:5:10: note: msg 7\n"); | |
2390 break; | |
2391 } | |
2392 if (with_optinfo) | |
2393 { | |
2394 optinfo *info = tmp.get_pending_optinfo (); | |
2395 ASSERT_TRUE (info != NULL); | |
2396 ASSERT_EQ (info->num_items (), 1); | |
2397 ASSERT_IS_TEXT (info->get_item (0), "msg 7\n"); | |
2398 } | |
2399 } | |
2400 } | |
2401 | |
2402 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE | |
2403 above. */ | |
2404 { | |
2405 /* MSG_OPTIMIZED_LOCATIONS. */ | |
2406 { | |
2407 temp_dump_context tmp (true, true, MSG_ALL_KINDS); | |
2408 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test"); | |
2409 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (), | |
2410 OPTINFO_KIND_SUCCESS); | |
2411 } | |
2412 | |
2413 /* MSG_MISSED_OPTIMIZATION. */ | |
2414 { | |
2415 temp_dump_context tmp (true, true, MSG_ALL_KINDS); | |
2416 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test"); | |
2417 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (), | |
2418 OPTINFO_KIND_FAILURE); | |
2419 } | |
2420 } | |
2421 | |
2422 /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */ | |
2423 { | |
2424 temp_dump_context tmp (false, true, | |
2425 MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES); | |
2426 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n"); | |
2427 { | |
2428 AUTO_DUMP_SCOPE ("outer scope", stmt); | |
2429 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n"); | |
2430 { | |
2431 AUTO_DUMP_SCOPE ("middle scope", stmt); | |
2432 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n"); | |
2433 { | |
2434 AUTO_DUMP_SCOPE ("inner scope", stmt); | |
2435 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n"); | |
2436 } | |
2437 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n"); | |
2438 } | |
2439 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n"); | |
2440 } | |
2441 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n"); | |
2442 | |
2443 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized: msg 4\n"); | |
2444 } | |
2445 } | |
2446 | |
2447 /* Run all of the selftests within this file. */ | |
2448 | |
2449 void | |
2450 dumpfile_c_tests () | |
2451 { | |
2452 test_impl_location (); | |
2453 for_each_line_table_case (test_capture_of_dump_calls); | |
2454 } | |
2455 | |
2456 } // namespace selftest | |
2457 | |
2458 #endif /* CHECKING_P */ |