rs6000: Fix gcc.target/powerpc testsuite target requirements.
[official-gcc.git] / gcc / dumpfile.c
blob5d61946fc49a902cde3aff9ad035f99849ed96c7
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "options.h"
24 #include "tree.h"
25 #include "gimple-pretty-print.h"
26 #include "diagnostic-core.h"
27 #include "dumpfile.h"
28 #include "context.h"
29 #include "profile-count.h"
30 #include "tree-cfg.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. */
42 #include "spellcheck.h"
44 /* If non-NULL, return one past-the-end of the matching SUBPART of
45 the WHOLE string. */
46 #define skip_leading_substring(whole, part) \
47 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
49 static dump_flags_t pflags; /* current dump_flags */
51 static void dump_loc (dump_flags_t, FILE *, location_t);
53 /* Current -fopt-info output stream, if any, and flags. */
54 static FILE *alt_dump_file = NULL;
55 static dump_flags_t alt_flags;
57 static FILE *dump_open_alternate_stream (struct dump_file_info *);
59 /* These are currently used for communicating between passes.
60 However, instead of accessing them directly, the passes can use
61 dump_printf () for dumps. */
62 FILE *dump_file = NULL;
63 const char *dump_file_name;
64 dump_flags_t dump_flags;
65 bool dumps_are_enabled = false;
68 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
69 global. */
71 void
72 set_dump_file (FILE *new_dump_file)
74 dumpfile_ensure_any_optinfo_are_flushed ();
75 dump_file = new_dump_file;
76 dump_context::get ().refresh_dumps_are_enabled ();
79 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
80 global. */
82 static void
83 set_alt_dump_file (FILE *new_alt_dump_file)
85 dumpfile_ensure_any_optinfo_are_flushed ();
86 alt_dump_file = new_alt_dump_file;
87 dump_context::get ().refresh_dumps_are_enabled ();
90 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
91 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
92 OPTGROUP_NONE, 0, 0, num, false, false}
94 /* Table of tree dump switches. This must be consistent with the
95 TREE_DUMP_INDEX enumeration in dumpfile.h. */
96 static struct dump_file_info dump_files[TDI_end] =
98 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
99 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
100 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
101 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
102 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
103 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
104 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
105 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
106 #define FIRST_AUTO_NUMBERED_DUMP 1
107 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
109 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
110 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
111 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
112 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
115 /* Table of dump options. This must be consistent with the TDF_* flags
116 in dumpfile.h and opt_info_options below. */
117 static const kv_pair<dump_flags_t> dump_options[] =
119 {"none", TDF_NONE},
120 {"address", TDF_ADDRESS},
121 {"asmname", TDF_ASMNAME},
122 {"slim", TDF_SLIM},
123 {"raw", TDF_RAW},
124 {"graph", TDF_GRAPH},
125 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
126 | MSG_MISSED_OPTIMIZATION
127 | MSG_NOTE)},
128 {"cselib", TDF_CSELIB},
129 {"stats", TDF_STATS},
130 {"blocks", TDF_BLOCKS},
131 {"vops", TDF_VOPS},
132 {"lineno", TDF_LINENO},
133 {"uid", TDF_UID},
134 {"stmtaddr", TDF_STMTADDR},
135 {"memsyms", TDF_MEMSYMS},
136 {"eh", TDF_EH},
137 {"alias", TDF_ALIAS},
138 {"nouid", TDF_NOUID},
139 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
140 {"scev", TDF_SCEV},
141 {"gimple", TDF_GIMPLE},
142 {"folding", TDF_FOLDING},
143 {"optimized", MSG_OPTIMIZED_LOCATIONS},
144 {"missed", MSG_MISSED_OPTIMIZATION},
145 {"note", MSG_NOTE},
146 {"optall", MSG_ALL_KINDS},
147 {"all", dump_flags_t (TDF_ALL_VALUES
148 & ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
149 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
150 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
151 {NULL, TDF_NONE}
154 /* A subset of the dump_options table which is used for -fopt-info
155 types. This must be consistent with the MSG_* flags in dumpfile.h.
157 static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
159 {"optimized", MSG_OPTIMIZED_LOCATIONS},
160 {"missed", MSG_MISSED_OPTIMIZATION},
161 {"note", MSG_NOTE},
162 {"all", MSG_ALL_KINDS},
163 {"internals", MSG_PRIORITY_INTERNALS},
164 {NULL, TDF_NONE}
167 /* Flags used for -fopt-info groups. */
168 const kv_pair<optgroup_flags_t> optgroup_options[] =
170 {"ipa", OPTGROUP_IPA},
171 {"loop", OPTGROUP_LOOP},
172 {"inline", OPTGROUP_INLINE},
173 {"omp", OPTGROUP_OMP},
174 {"vec", OPTGROUP_VEC},
175 {"optall", OPTGROUP_ALL},
176 {NULL, OPTGROUP_NONE}
179 gcc::dump_manager::dump_manager ():
180 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
181 m_extra_dump_files (NULL),
182 m_extra_dump_files_in_use (0),
183 m_extra_dump_files_alloced (0),
184 m_optgroup_flags (OPTGROUP_NONE),
185 m_optinfo_flags (TDF_NONE),
186 m_optinfo_filename (NULL)
190 gcc::dump_manager::~dump_manager ()
192 free (m_optinfo_filename);
193 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
195 dump_file_info *dfi = &m_extra_dump_files[i];
196 /* suffix, swtch, glob are statically allocated for the entries
197 in dump_files, and for statistics, but are dynamically allocated
198 for those for passes. */
199 if (dfi->owns_strings)
201 XDELETEVEC (const_cast <char *> (dfi->suffix));
202 XDELETEVEC (const_cast <char *> (dfi->swtch));
203 XDELETEVEC (const_cast <char *> (dfi->glob));
205 /* These, if non-NULL, are always dynamically allocated. */
206 XDELETEVEC (const_cast <char *> (dfi->pfilename));
207 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
209 XDELETEVEC (m_extra_dump_files);
212 unsigned int
213 gcc::dump_manager::
214 dump_register (const char *suffix, const char *swtch, const char *glob,
215 dump_kind dkind, optgroup_flags_t optgroup_flags,
216 bool take_ownership)
218 int num = m_next_dump++;
220 size_t count = m_extra_dump_files_in_use++;
222 if (count >= m_extra_dump_files_alloced)
224 if (m_extra_dump_files_alloced == 0)
225 m_extra_dump_files_alloced = 512;
226 else
227 m_extra_dump_files_alloced *= 2;
228 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
229 m_extra_dump_files,
230 m_extra_dump_files_alloced);
232 /* Construct a new object in the space allocated above. */
233 new (m_extra_dump_files + count) dump_file_info ();
235 else
237 /* Zero out the already constructed object. */
238 m_extra_dump_files[count] = dump_file_info ();
241 m_extra_dump_files[count].suffix = suffix;
242 m_extra_dump_files[count].swtch = swtch;
243 m_extra_dump_files[count].glob = glob;
244 m_extra_dump_files[count].dkind = dkind;
245 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
246 m_extra_dump_files[count].num = num;
247 m_extra_dump_files[count].owns_strings = take_ownership;
249 return count + TDI_end;
253 /* Allow languages and middle-end to register their dumps before the
254 optimization passes. */
256 void
257 gcc::dump_manager::
258 register_dumps ()
260 lang_hooks.register_dumps (this);
261 /* If this assert fails, some FE registered more than
262 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
263 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
264 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
265 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
266 dump_files[TDI_original].num = m_next_dump++;
267 dump_files[TDI_gimple].num = m_next_dump++;
268 dump_files[TDI_nested].num = m_next_dump++;
272 /* Return the dump_file_info for the given phase. */
274 struct dump_file_info *
275 gcc::dump_manager::
276 get_dump_file_info (int phase) const
278 if (phase < TDI_end)
279 return &dump_files[phase];
280 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
281 return NULL;
282 else
283 return m_extra_dump_files + (phase - TDI_end);
286 /* Locate the dump_file_info with swtch equal to SWTCH,
287 or return NULL if no such dump_file_info exists. */
289 struct dump_file_info *
290 gcc::dump_manager::
291 get_dump_file_info_by_switch (const char *swtch) const
293 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
294 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
295 return &m_extra_dump_files[i];
297 /* Not found. */
298 return NULL;
302 /* Return the name of the dump file for the given phase.
303 The caller is responsible for calling free on the returned
304 buffer.
305 If the dump is not enabled, returns NULL. */
307 char *
308 gcc::dump_manager::
309 get_dump_file_name (int phase, int part) const
311 struct dump_file_info *dfi;
313 if (phase == TDI_none)
314 return NULL;
316 dfi = get_dump_file_info (phase);
318 return get_dump_file_name (dfi, part);
321 /* Return the name of the dump file for the given dump_file_info.
322 The caller is responsible for calling free on the returned
323 buffer.
324 If the dump is not enabled, returns NULL. */
326 char *
327 gcc::dump_manager::
328 get_dump_file_name (struct dump_file_info *dfi, int part) const
330 char dump_id[10];
332 gcc_assert (dfi);
334 if (dfi->pstate == 0)
335 return NULL;
337 /* If available, use the command line dump filename. */
338 if (dfi->pfilename)
339 return xstrdup (dfi->pfilename);
341 if (dfi->num < 0)
342 dump_id[0] = '\0';
343 else
345 /* (null), LANG, TREE, RTL, IPA. */
346 char suffix = " ltri"[dfi->dkind];
348 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
349 dump_id[0] = '\0';
352 if (part != -1)
354 char part_id[8];
355 snprintf (part_id, sizeof (part_id), ".%i", part);
356 return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
358 else
359 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
362 /* Open a dump file called FILENAME. Some filenames are special and
363 refer to the standard streams. TRUNC indicates whether this is the
364 first open (so the file should be truncated, rather than appended).
365 An error message is emitted in the event of failure. */
367 static FILE *
368 dump_open (const char *filename, bool trunc)
370 if (strcmp ("stderr", filename) == 0)
371 return stderr;
373 if (strcmp ("stdout", filename) == 0
374 || strcmp ("-", filename) == 0)
375 return stdout;
377 FILE *stream = fopen (filename, trunc ? "w" : "a");
379 if (!stream)
380 error ("could not open dump file %qs: %m", filename);
381 return stream;
384 /* For a given DFI, open an alternate dump filename (which could also
385 be a standard stream such as stdout/stderr). If the alternate dump
386 file cannot be opened, return NULL. */
388 static FILE *
389 dump_open_alternate_stream (struct dump_file_info *dfi)
391 if (!dfi->alt_filename)
392 return NULL;
394 if (dfi->alt_stream)
395 return dfi->alt_stream;
397 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
399 if (stream)
400 dfi->alt_state = 1;
402 return stream;
405 /* Construct a dump_user_location_t from STMT (using its location and
406 hotness). */
408 dump_user_location_t::dump_user_location_t (const gimple *stmt)
409 : m_count (), m_loc (UNKNOWN_LOCATION)
411 if (stmt)
413 if (stmt->bb)
414 m_count = stmt->bb->count;
415 m_loc = gimple_location (stmt);
419 /* Construct a dump_user_location_t from an RTL instruction (using its
420 location and hotness). */
422 dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
423 : m_count (), m_loc (UNKNOWN_LOCATION)
425 if (insn)
427 basic_block bb = BLOCK_FOR_INSN (insn);
428 if (bb)
429 m_count = bb->count;
430 m_loc = INSN_LOCATION (insn);
434 /* Construct from a function declaration. This one requires spelling out
435 to avoid accidentally constructing from other kinds of tree. */
437 dump_user_location_t
438 dump_user_location_t::from_function_decl (tree fndecl)
440 gcc_assert (fndecl);
442 // FIXME: profile count for function?
443 return dump_user_location_t (profile_count (),
444 DECL_SOURCE_LOCATION (fndecl));
447 /* Extract the MSG_* component from DUMP_KIND and return a string for use
448 as a prefix to dump messages.
449 These match the strings in optinfo_verbosity_options and thus the
450 "OPTIONS" within "-fopt-info-OPTIONS". */
452 static const char *
453 kind_as_string (dump_flags_t dump_kind)
455 switch (dump_kind & MSG_ALL_KINDS)
457 default:
458 gcc_unreachable ();
459 case MSG_OPTIMIZED_LOCATIONS:
460 return "optimized";
461 case MSG_MISSED_OPTIMIZATION:
462 return "missed";
463 case MSG_NOTE:
464 return "note";
468 /* Print source location on DFILE if enabled. */
470 static void
471 dump_loc (dump_flags_t dump_kind, FILE *dfile, location_t loc)
473 if (dump_kind)
475 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
476 fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc),
477 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
478 else if (current_function_decl)
479 fprintf (dfile, "%s:%d:%d: ",
480 DECL_SOURCE_FILE (current_function_decl),
481 DECL_SOURCE_LINE (current_function_decl),
482 DECL_SOURCE_COLUMN (current_function_decl));
483 fprintf (dfile, "%s: ", kind_as_string (dump_kind));
484 /* Indentation based on scope depth. */
485 fprintf (dfile, "%*s", get_dump_scope_depth (), "");
489 /* Print source location to PP if enabled. */
491 static void
492 dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
494 if (dump_kind)
496 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
497 pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc),
498 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
499 else if (current_function_decl)
500 pp_printf (pp, "%s:%d:%d: ",
501 DECL_SOURCE_FILE (current_function_decl),
502 DECL_SOURCE_LINE (current_function_decl),
503 DECL_SOURCE_COLUMN (current_function_decl));
504 pp_printf (pp, "%s: ", kind_as_string (dump_kind));
505 /* Indentation based on scope depth. */
506 for (unsigned i = 0; i < get_dump_scope_depth (); i++)
507 pp_character (pp, ' ');
511 /* Implementation of dump_context member functions. */
513 /* dump_context's dtor. */
515 dump_context::~dump_context ()
517 delete m_pending;
520 void
521 dump_context::set_json_writer (optrecord_json_writer *writer)
523 delete m_json_writer;
524 m_json_writer = writer;
527 /* Perform cleanup activity for -fsave-optimization-record.
528 Currently, the file is written out here in one go, before cleaning
529 up. */
531 void
532 dump_context::finish_any_json_writer ()
534 if (!m_json_writer)
535 return;
537 m_json_writer->write ();
538 delete m_json_writer;
539 m_json_writer = NULL;
542 /* Update the "dumps_are_enabled" global; to be called whenever dump_file
543 or alt_dump_file change, or when changing dump_context in selftests. */
545 void
546 dump_context::refresh_dumps_are_enabled ()
548 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
549 || m_test_pp);
552 /* Determine if a message of kind DUMP_KIND and at the current scope depth
553 should be printed.
555 Only show messages that match FILTER both on their kind *and*
556 their priority. */
558 bool
559 dump_context::apply_dump_filter_p (dump_flags_t dump_kind,
560 dump_flags_t filter) const
562 /* Few messages, if any, have an explicit MSG_PRIORITY.
563 If DUMP_KIND does, we'll use it.
564 Otherwise, generate an implicit priority value for the message based
565 on the current scope depth.
566 Messages at the top-level scope are MSG_PRIORITY_USER_FACING,
567 whereas those in nested scopes are MSG_PRIORITY_INTERNALS. */
568 if (!(dump_kind & MSG_ALL_PRIORITIES))
570 dump_flags_t implicit_priority
571 = (m_scope_depth > 0
572 ? MSG_PRIORITY_INTERNALS
573 : MSG_PRIORITY_USER_FACING);
574 dump_kind |= implicit_priority;
577 return (dump_kind & (filter & MSG_ALL_KINDS)
578 && dump_kind & (filter & MSG_ALL_PRIORITIES));
581 /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
582 If optinfos are enabled, begin a new optinfo. */
584 void
585 dump_context::dump_loc (const dump_metadata_t &metadata,
586 const dump_user_location_t &loc)
588 end_any_optinfo ();
590 dump_loc_immediate (metadata.get_dump_flags (), loc);
592 if (optinfo_enabled_p ())
593 begin_next_optinfo (metadata, loc);
596 /* As dump_loc above, but without starting a new optinfo. */
598 void
599 dump_context::dump_loc_immediate (dump_flags_t dump_kind,
600 const dump_user_location_t &loc)
602 location_t srcloc = loc.get_location_t ();
604 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
605 ::dump_loc (dump_kind, dump_file, srcloc);
607 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
608 ::dump_loc (dump_kind, alt_dump_file, srcloc);
610 /* Support for temp_dump_context in selftests. */
611 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
612 ::dump_loc (dump_kind, m_test_pp, srcloc);
615 /* Make an item for the given dump call, equivalent to print_gimple_stmt. */
617 static optinfo_item *
618 make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
620 pretty_printer pp;
621 pp_needs_newline (&pp) = true;
622 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
623 pp_newline (&pp);
625 optinfo_item *item
626 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
627 xstrdup (pp_formatted_text (&pp)));
628 return item;
631 /* Dump gimple statement GS with SPC indentation spaces and
632 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
634 void
635 dump_context::dump_gimple_stmt (const dump_metadata_t &metadata,
636 dump_flags_t extra_dump_flags,
637 gimple *gs, int spc)
639 optinfo_item *item
640 = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
641 emit_item (item, metadata.get_dump_flags ());
643 if (optinfo_enabled_p ())
645 optinfo &info = ensure_pending_optinfo (metadata);
646 info.add_item (item);
648 else
649 delete item;
652 /* Similar to dump_gimple_stmt, except additionally print source location. */
654 void
655 dump_context::dump_gimple_stmt_loc (const dump_metadata_t &metadata,
656 const dump_user_location_t &loc,
657 dump_flags_t extra_dump_flags,
658 gimple *gs, int spc)
660 dump_loc (metadata, loc);
661 dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
664 /* Make an item for the given dump call, equivalent to print_gimple_expr. */
666 static optinfo_item *
667 make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
669 dump_flags |= TDF_RHS_ONLY;
670 pretty_printer pp;
671 pp_needs_newline (&pp) = true;
672 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
674 optinfo_item *item
675 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
676 xstrdup (pp_formatted_text (&pp)));
677 return item;
680 /* Dump gimple statement GS with SPC indentation spaces and
681 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
682 Do not terminate with a newline or semicolon. */
684 void
685 dump_context::dump_gimple_expr (const dump_metadata_t &metadata,
686 dump_flags_t extra_dump_flags,
687 gimple *gs, int spc)
689 optinfo_item *item
690 = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
691 emit_item (item, metadata.get_dump_flags ());
693 if (optinfo_enabled_p ())
695 optinfo &info = ensure_pending_optinfo (metadata);
696 info.add_item (item);
698 else
699 delete item;
702 /* Similar to dump_gimple_expr, except additionally print source location. */
704 void
705 dump_context::dump_gimple_expr_loc (const dump_metadata_t &metadata,
706 const dump_user_location_t &loc,
707 dump_flags_t extra_dump_flags,
708 gimple *gs,
709 int spc)
711 dump_loc (metadata, loc);
712 dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
715 /* Make an item for the given dump call, equivalent to print_generic_expr. */
717 static optinfo_item *
718 make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
720 pretty_printer pp;
721 pp_needs_newline (&pp) = true;
722 pp_translate_identifiers (&pp) = false;
723 dump_generic_node (&pp, node, 0, dump_flags, false);
725 location_t loc = UNKNOWN_LOCATION;
726 if (EXPR_HAS_LOCATION (node))
727 loc = EXPR_LOCATION (node);
729 optinfo_item *item
730 = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
731 xstrdup (pp_formatted_text (&pp)));
732 return item;
735 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
736 DUMP_KIND is enabled. */
738 void
739 dump_context::dump_generic_expr (const dump_metadata_t &metadata,
740 dump_flags_t extra_dump_flags,
741 tree t)
743 optinfo_item *item
744 = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
745 emit_item (item, metadata.get_dump_flags ());
747 if (optinfo_enabled_p ())
749 optinfo &info = ensure_pending_optinfo (metadata);
750 info.add_item (item);
752 else
753 delete item;
757 /* Similar to dump_generic_expr, except additionally print the source
758 location. */
760 void
761 dump_context::dump_generic_expr_loc (const dump_metadata_t &metadata,
762 const dump_user_location_t &loc,
763 dump_flags_t extra_dump_flags,
764 tree t)
766 dump_loc (metadata, loc);
767 dump_generic_expr (metadata, extra_dump_flags, t);
770 /* Make an item for the given dump call. */
772 static optinfo_item *
773 make_item_for_dump_symtab_node (symtab_node *node)
775 location_t loc = DECL_SOURCE_LOCATION (node->decl);
776 optinfo_item *item
777 = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
778 xstrdup (node->dump_name ()));
779 return item;
782 /* dump_pretty_printer's ctor. */
784 dump_pretty_printer::dump_pretty_printer (dump_context *context,
785 dump_flags_t dump_kind)
786 : pretty_printer (), m_context (context), m_dump_kind (dump_kind),
787 m_stashed_items ()
789 pp_format_decoder (this) = format_decoder_cb;
792 /* Phase 3 of formatting; compare with pp_output_formatted_text.
794 Emit optinfo_item instances for the various formatted chunks from phases
795 1 and 2 (i.e. pp_format).
797 Some chunks may already have had their items built (during decode_format).
798 These chunks have been stashed into m_stashed_items; we emit them here.
800 For all other purely textual chunks, they are printed into
801 buffer->formatted_obstack, and then emitted as a textual optinfo_item.
802 This consolidates multiple adjacent text chunks into a single text
803 optinfo_item. */
805 void
806 dump_pretty_printer::emit_items (optinfo *dest)
808 output_buffer *buffer = pp_buffer (this);
809 struct chunk_info *chunk_array = buffer->cur_chunk_array;
810 const char **args = chunk_array->args;
812 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
813 gcc_assert (buffer->line_length == 0);
815 unsigned stashed_item_idx = 0;
816 for (unsigned chunk = 0; args[chunk]; chunk++)
818 if (stashed_item_idx < m_stashed_items.length ()
819 && args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr)
821 emit_any_pending_textual_chunks (dest);
822 /* This chunk has a stashed item: use it. */
823 emit_item (m_stashed_items[stashed_item_idx++].item, dest);
825 else
826 /* This chunk is purely textual. Print it (to
827 buffer->formatted_obstack), so that we can consolidate adjacent
828 chunks into one textual optinfo_item. */
829 pp_string (this, args[chunk]);
832 emit_any_pending_textual_chunks (dest);
834 /* Ensure that we consumed all of stashed_items. */
835 gcc_assert (stashed_item_idx == m_stashed_items.length ());
837 /* Deallocate the chunk structure and everything after it (i.e. the
838 associated series of formatted strings). */
839 buffer->cur_chunk_array = chunk_array->prev;
840 obstack_free (&buffer->chunk_obstack, chunk_array);
843 /* Subroutine of dump_pretty_printer::emit_items
844 for consolidating multiple adjacent pure-text chunks into single
845 optinfo_items (in phase 3). */
847 void
848 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest)
850 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
852 /* Don't emit an item if the pending text is empty. */
853 if (output_buffer_last_position_in_text (buffer) == NULL)
854 return;
856 char *formatted_text = xstrdup (pp_formatted_text (this));
857 optinfo_item *item
858 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
859 formatted_text);
860 emit_item (item, dest);
862 /* Clear the pending text by unwinding formatted_text back to the start
863 of the buffer (without deallocating). */
864 obstack_free (&buffer->formatted_obstack,
865 buffer->formatted_obstack.object_base);
868 /* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
869 to DEST; otherwise delete ITEM. */
871 void
872 dump_pretty_printer::emit_item (optinfo_item *item, optinfo *dest)
874 m_context->emit_item (item, m_dump_kind);
875 if (dest)
876 dest->add_item (item);
877 else
878 delete item;
881 /* Record that ITEM (generated in phase 2 of formatting) is to be used for
882 the chunk at BUFFER_PTR in phase 3 (by emit_items). */
884 void
885 dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item)
887 gcc_assert (buffer_ptr);
888 gcc_assert (item);
890 m_stashed_items.safe_push (stashed_item (buffer_ptr, item));
893 /* pp_format_decoder callback for dump_pretty_printer, and thus for
894 dump_printf and dump_printf_loc.
896 A wrapper around decode_format, for type-safety. */
898 bool
899 dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
900 const char *spec, int /*precision*/,
901 bool /*wide*/, bool /*set_locus*/,
902 bool /*verbose*/, bool */*quoted*/,
903 const char **buffer_ptr)
905 dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
906 return opp->decode_format (text, spec, buffer_ptr);
909 /* Format decoder for dump_pretty_printer, and thus for dump_printf and
910 dump_printf_loc.
912 Supported format codes (in addition to the standard pretty_printer ones)
913 are:
915 %C: cgraph_node *:
916 Equivalent to: dump_symtab_node (MSG_*, node)
917 %E: gimple *:
918 Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
919 %G: gimple *:
920 Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
921 %T: tree:
922 Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
924 TODO: add a format code that can handle (symtab_node*) *and* both
925 subclasses (presumably means teaching -Wformat about non-virtual
926 subclasses).
928 These format codes build optinfo_item instances, thus capturing metadata
929 about the arguments being dumped, as well as the textual output. */
931 bool
932 dump_pretty_printer::decode_format (text_info *text, const char *spec,
933 const char **buffer_ptr)
935 /* Various format codes that imply making an optinfo_item and stashed it
936 for later use (to capture metadata, rather than plain text). */
937 switch (*spec)
939 case 'C':
941 cgraph_node *node = va_arg (*text->args_ptr, cgraph_node *);
943 /* Make an item for the node, and stash it. */
944 optinfo_item *item = make_item_for_dump_symtab_node (node);
945 stash_item (buffer_ptr, item);
946 return true;
949 case 'E':
951 gimple *stmt = va_arg (*text->args_ptr, gimple *);
953 /* Make an item for the stmt, and stash it. */
954 optinfo_item *item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
955 stash_item (buffer_ptr, item);
956 return true;
959 case 'G':
961 gimple *stmt = va_arg (*text->args_ptr, gimple *);
963 /* Make an item for the stmt, and stash it. */
964 optinfo_item *item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
965 stash_item (buffer_ptr, item);
966 return true;
969 case 'T':
971 tree t = va_arg (*text->args_ptr, tree);
973 /* Make an item for the tree, and stash it. */
974 optinfo_item *item = make_item_for_dump_generic_expr (t, TDF_SLIM);
975 stash_item (buffer_ptr, item);
976 return true;
979 default:
980 return false;
984 /* Output a formatted message using FORMAT on appropriate dump streams. */
986 void
987 dump_context::dump_printf_va (const dump_metadata_t &metadata, const char *format,
988 va_list *ap)
990 dump_pretty_printer pp (this, metadata.get_dump_flags ());
992 text_info text;
993 text.err_no = errno;
994 text.args_ptr = ap;
995 text.format_spec = format;
997 /* Phases 1 and 2, using pp_format. */
998 pp_format (&pp, &text);
1000 /* Phase 3. */
1001 if (optinfo_enabled_p ())
1003 optinfo &info = ensure_pending_optinfo (metadata);
1004 pp.emit_items (&info);
1006 else
1007 pp.emit_items (NULL);
1010 /* Similar to dump_printf, except source location is also printed, and
1011 dump location captured. */
1013 void
1014 dump_context::dump_printf_loc_va (const dump_metadata_t &metadata,
1015 const dump_user_location_t &loc,
1016 const char *format, va_list *ap)
1018 dump_loc (metadata, loc);
1019 dump_printf_va (metadata, format, ap);
1022 /* Make an item for the given dump call, equivalent to print_dec. */
1024 template<unsigned int N, typename C>
1025 static optinfo_item *
1026 make_item_for_dump_dec (const poly_int<N, C> &value)
1028 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
1029 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
1031 pretty_printer pp;
1033 if (value.is_constant ())
1034 pp_wide_int (&pp, value.coeffs[0], sgn);
1035 else
1037 pp_character (&pp, '[');
1038 for (unsigned int i = 0; i < N; ++i)
1040 pp_wide_int (&pp, value.coeffs[i], sgn);
1041 pp_character (&pp, i == N - 1 ? ']' : ',');
1045 optinfo_item *item
1046 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
1047 xstrdup (pp_formatted_text (&pp)));
1048 return item;
1051 /* Output VALUE in decimal to appropriate dump streams. */
1053 template<unsigned int N, typename C>
1054 void
1055 dump_context::dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
1057 optinfo_item *item = make_item_for_dump_dec (value);
1058 emit_item (item, metadata.get_dump_flags ());
1060 if (optinfo_enabled_p ())
1062 optinfo &info = ensure_pending_optinfo (metadata);
1063 info.add_item (item);
1065 else
1066 delete item;
1069 /* Output the name of NODE on appropriate dump streams. */
1071 void
1072 dump_context::dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
1074 optinfo_item *item = make_item_for_dump_symtab_node (node);
1075 emit_item (item, metadata.get_dump_flags ());
1077 if (optinfo_enabled_p ())
1079 optinfo &info = ensure_pending_optinfo (metadata);
1080 info.add_item (item);
1082 else
1083 delete item;
1086 /* Get the current dump scope-nesting depth.
1087 For use by -fopt-info (for showing nesting via indentation). */
1089 unsigned int
1090 dump_context::get_scope_depth () const
1092 return m_scope_depth;
1095 /* Push a nested dump scope.
1096 Increment the scope depth.
1097 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1098 destination, if any.
1099 Emit a "scope" optinfo if optinfos are enabled. */
1101 void
1102 dump_context::begin_scope (const char *name,
1103 const dump_user_location_t &user_location,
1104 const dump_impl_location_t &impl_location)
1106 m_scope_depth++;
1108 location_t src_loc = user_location.get_location_t ();
1110 if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags))
1111 ::dump_loc (MSG_NOTE, dump_file, src_loc);
1113 if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags))
1114 ::dump_loc (MSG_NOTE, alt_dump_file, src_loc);
1116 /* Support for temp_dump_context in selftests. */
1117 if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
1118 ::dump_loc (MSG_NOTE, m_test_pp, src_loc);
1120 pretty_printer pp;
1121 pp_printf (&pp, "=== %s ===\n", name);
1122 optinfo_item *item
1123 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
1124 xstrdup (pp_formatted_text (&pp)));
1125 emit_item (item, MSG_NOTE);
1127 if (optinfo_enabled_p ())
1129 optinfo &info
1130 = begin_next_optinfo (dump_metadata_t (MSG_NOTE, impl_location),
1131 user_location);
1132 info.m_kind = OPTINFO_KIND_SCOPE;
1133 info.add_item (item);
1134 end_any_optinfo ();
1136 else
1137 delete item;
1140 /* Pop a nested dump scope. */
1142 void
1143 dump_context::end_scope ()
1145 end_any_optinfo ();
1146 m_scope_depth--;
1148 if (m_json_writer)
1149 m_json_writer->pop_scope ();
1152 /* Should optinfo instances be created?
1153 All creation of optinfos should be guarded by this predicate.
1154 Return true if any optinfo destinations are active. */
1156 bool
1157 dump_context::optinfo_enabled_p () const
1159 return (optimization_records_enabled_p ());
1162 /* Return the optinfo currently being accumulated, creating one if
1163 necessary. */
1165 optinfo &
1166 dump_context::ensure_pending_optinfo (const dump_metadata_t &metadata)
1168 if (!m_pending)
1169 return begin_next_optinfo (metadata, dump_user_location_t ());
1170 return *m_pending;
1173 /* Start a new optinfo and return it, ending any optinfo that was already
1174 accumulated. */
1176 optinfo &
1177 dump_context::begin_next_optinfo (const dump_metadata_t &metadata,
1178 const dump_user_location_t &user_loc)
1180 end_any_optinfo ();
1181 gcc_assert (m_pending == NULL);
1182 dump_location_t loc (user_loc, metadata.get_impl_location ());
1183 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
1184 m_pending->handle_dump_file_kind (metadata.get_dump_flags ());
1185 return *m_pending;
1188 /* End any optinfo that has been accumulated within this context; emitting
1189 it to any destinations as appropriate, such as optimization records. */
1191 void
1192 dump_context::end_any_optinfo ()
1194 if (m_pending)
1195 emit_optinfo (m_pending);
1196 delete m_pending;
1197 m_pending = NULL;
1200 /* Emit the optinfo to all of the "non-immediate" destinations
1201 (emission to "immediate" destinations is done by
1202 dump_context::emit_item). */
1204 void
1205 dump_context::emit_optinfo (const optinfo *info)
1207 /* -fsave-optimization-record. */
1208 if (m_json_writer)
1209 m_json_writer->add_record (info);
1212 /* Emit ITEM to all item destinations (those that don't require
1213 consolidation into optinfo instances). */
1215 void
1216 dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind)
1218 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
1219 fprintf (dump_file, "%s", item->get_text ());
1221 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
1222 fprintf (alt_dump_file, "%s", item->get_text ());
1224 /* Support for temp_dump_context in selftests. */
1225 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
1226 pp_string (m_test_pp, item->get_text ());
1229 /* The current singleton dump_context, and its default. */
1231 dump_context *dump_context::s_current = &dump_context::s_default;
1232 dump_context dump_context::s_default;
1234 /* Implementation of dump_* API calls, calling into dump_context
1235 member functions. */
1237 /* Calls to the dump_* functions do non-trivial work, so they ought
1238 to be guarded by:
1239 if (dump_enabled_p ())
1240 Assert that they are guarded, and, if assertions are disabled,
1241 bail out if the calls weren't properly guarded. */
1243 #define VERIFY_DUMP_ENABLED_P \
1244 do { \
1245 gcc_assert (dump_enabled_p ()); \
1246 if (!dump_enabled_p ()) \
1247 return; \
1248 } while (0)
1250 /* Dump gimple statement GS with SPC indentation spaces and
1251 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
1253 void
1254 dump_gimple_stmt (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
1255 gimple *gs, int spc)
1257 VERIFY_DUMP_ENABLED_P;
1258 dump_context::get ().dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
1261 /* Similar to dump_gimple_stmt, except additionally print source location. */
1263 void
1264 dump_gimple_stmt_loc (const dump_metadata_t &metadata,
1265 const dump_user_location_t &loc,
1266 dump_flags_t extra_dump_flags, gimple *gs, int spc)
1268 VERIFY_DUMP_ENABLED_P;
1269 dump_context::get ().dump_gimple_stmt_loc (metadata, loc, extra_dump_flags,
1270 gs, spc);
1273 /* Dump gimple statement GS with SPC indentation spaces and
1274 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
1275 Do not terminate with a newline or semicolon. */
1277 void
1278 dump_gimple_expr (const dump_metadata_t &metadata,
1279 dump_flags_t extra_dump_flags,
1280 gimple *gs, int spc)
1282 VERIFY_DUMP_ENABLED_P;
1283 dump_context::get ().dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
1286 /* Similar to dump_gimple_expr, except additionally print source location. */
1288 void
1289 dump_gimple_expr_loc (const dump_metadata_t &metadata,
1290 const dump_user_location_t &loc,
1291 dump_flags_t extra_dump_flags, gimple *gs, int spc)
1293 VERIFY_DUMP_ENABLED_P;
1294 dump_context::get ().dump_gimple_expr_loc (metadata, loc, extra_dump_flags,
1295 gs, spc);
1298 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
1299 DUMP_KIND is enabled. */
1301 void
1302 dump_generic_expr (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
1303 tree t)
1305 VERIFY_DUMP_ENABLED_P;
1306 dump_context::get ().dump_generic_expr (metadata, extra_dump_flags, t);
1309 /* Similar to dump_generic_expr, except additionally print the source
1310 location. */
1312 void
1313 dump_generic_expr_loc (const dump_metadata_t &metadata,
1314 const dump_user_location_t &loc,
1315 dump_flags_t extra_dump_flags, tree t)
1317 VERIFY_DUMP_ENABLED_P;
1318 dump_context::get ().dump_generic_expr_loc (metadata, loc, extra_dump_flags,
1322 /* Output a formatted message using FORMAT on appropriate dump streams. */
1324 void
1325 dump_printf (const dump_metadata_t &metadata, const char *format, ...)
1327 VERIFY_DUMP_ENABLED_P;
1328 va_list ap;
1329 va_start (ap, format);
1330 dump_context::get ().dump_printf_va (metadata, format, &ap);
1331 va_end (ap);
1334 /* Similar to dump_printf, except source location is also printed, and
1335 dump location captured. */
1337 void
1338 dump_printf_loc (const dump_metadata_t &metadata,
1339 const dump_user_location_t &loc,
1340 const char *format, ...)
1342 VERIFY_DUMP_ENABLED_P;
1343 va_list ap;
1344 va_start (ap, format);
1345 dump_context::get ().dump_printf_loc_va (metadata, loc, format, &ap);
1346 va_end (ap);
1349 /* Output VALUE in decimal to appropriate dump streams. */
1351 template<unsigned int N, typename C>
1352 void
1353 dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
1355 VERIFY_DUMP_ENABLED_P;
1356 dump_context::get ().dump_dec (metadata, value);
1359 template void dump_dec (const dump_metadata_t &metadata, const poly_uint16 &);
1360 template void dump_dec (const dump_metadata_t &metadata, const poly_int64 &);
1361 template void dump_dec (const dump_metadata_t &metadata, const poly_uint64 &);
1362 template void dump_dec (const dump_metadata_t &metadata, const poly_offset_int &);
1363 template void dump_dec (const dump_metadata_t &metadata, const poly_widest_int &);
1365 void
1366 dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
1368 VERIFY_DUMP_ENABLED_P;
1369 if (dump_file
1370 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
1371 print_dec (value, dump_file, sgn);
1373 if (alt_dump_file
1374 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
1375 print_dec (value, alt_dump_file, sgn);
1378 /* Output VALUE in hexadecimal to appropriate dump streams. */
1380 void
1381 dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
1383 VERIFY_DUMP_ENABLED_P;
1384 if (dump_file
1385 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
1386 print_hex (value, dump_file);
1388 if (alt_dump_file
1389 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
1390 print_hex (value, alt_dump_file);
1393 /* Emit and delete the currently pending optinfo, if there is one,
1394 without the caller needing to know about class dump_context. */
1396 void
1397 dumpfile_ensure_any_optinfo_are_flushed ()
1399 dump_context::get().end_any_optinfo ();
1402 /* Output the name of NODE on appropriate dump streams. */
1404 void
1405 dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
1407 VERIFY_DUMP_ENABLED_P;
1408 dump_context::get ().dump_symtab_node (metadata, node);
1411 /* Get the current dump scope-nesting depth.
1412 For use by -fopt-info (for showing nesting via indentation). */
1414 unsigned int
1415 get_dump_scope_depth ()
1417 return dump_context::get ().get_scope_depth ();
1420 /* Push a nested dump scope.
1421 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1422 destination, if any.
1423 Emit a "scope" opinfo if optinfos are enabled.
1424 Increment the scope depth. */
1426 void
1427 dump_begin_scope (const char *name,
1428 const dump_user_location_t &user_location,
1429 const dump_impl_location_t &impl_location)
1431 dump_context::get ().begin_scope (name, user_location, impl_location);
1434 /* Pop a nested dump scope. */
1436 void
1437 dump_end_scope ()
1439 dump_context::get ().end_scope ();
1442 /* Start a dump for PHASE. Store user-supplied dump flags in
1443 *FLAG_PTR. Return the number of streams opened. Set globals
1444 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
1445 set dump_flags appropriately for both pass dump stream and
1446 -fopt-info stream. */
1449 gcc::dump_manager::
1450 dump_start (int phase, dump_flags_t *flag_ptr)
1452 int count = 0;
1453 char *name;
1454 struct dump_file_info *dfi;
1455 FILE *stream;
1456 if (phase == TDI_none || !dump_phase_enabled_p (phase))
1457 return 0;
1459 dfi = get_dump_file_info (phase);
1460 name = get_dump_file_name (phase);
1461 if (name)
1463 stream = dump_open (name, dfi->pstate < 0);
1464 if (stream)
1466 dfi->pstate = 1;
1467 count++;
1469 free (name);
1470 dfi->pstream = stream;
1471 set_dump_file (dfi->pstream);
1472 /* Initialize current dump flags. */
1473 pflags = dfi->pflags;
1476 stream = dump_open_alternate_stream (dfi);
1477 if (stream)
1479 dfi->alt_stream = stream;
1480 count++;
1481 set_alt_dump_file (dfi->alt_stream);
1482 /* Initialize current -fopt-info flags. */
1483 alt_flags = dfi->alt_flags;
1486 if (flag_ptr)
1487 *flag_ptr = dfi->pflags;
1489 return count;
1492 /* Finish a tree dump for PHASE and close associated dump streams. Also
1493 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
1495 void
1496 gcc::dump_manager::
1497 dump_finish (int phase)
1499 struct dump_file_info *dfi;
1501 if (phase < 0)
1502 return;
1503 dfi = get_dump_file_info (phase);
1504 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
1505 fclose (dfi->pstream);
1507 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
1508 fclose (dfi->alt_stream);
1510 dfi->alt_stream = NULL;
1511 dfi->pstream = NULL;
1512 set_dump_file (NULL);
1513 set_alt_dump_file (NULL);
1514 dump_flags = TDF_NONE;
1515 alt_flags = TDF_NONE;
1516 pflags = TDF_NONE;
1519 /* Begin a tree dump for PHASE. Stores any user supplied flag in
1520 *FLAG_PTR and returns a stream to write to. If the dump is not
1521 enabled, returns NULL.
1522 PART can be used for dump files which should be split to multiple
1523 parts. PART == -1 indicates dump file with no parts.
1524 If PART is -1, multiple calls will reopen and append to the dump file. */
1526 FILE *
1527 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
1529 return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
1532 FILE *
1533 gcc::dump_manager::
1534 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
1536 if (phase == TDI_none || !dump_phase_enabled_p (phase))
1537 return NULL;
1539 char *name = get_dump_file_name (phase, part);
1540 if (!name)
1541 return NULL;
1542 struct dump_file_info *dfi = get_dump_file_info (phase);
1544 /* We do not support re-opening of dump files with parts. This would require
1545 tracking pstate per part of the dump file. */
1546 FILE *stream = dump_open (name, part != -1 || dfi->pstate < 0);
1547 if (stream)
1548 dfi->pstate = 1;
1549 free (name);
1551 if (flag_ptr)
1552 *flag_ptr = dfi->pflags;
1554 /* Initialize current flags */
1555 pflags = dfi->pflags;
1556 return stream;
1559 /* Returns nonzero if dump PHASE is enabled for at least one stream.
1560 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1561 any phase. */
1564 gcc::dump_manager::
1565 dump_phase_enabled_p (int phase) const
1567 if (phase == TDI_tree_all)
1569 size_t i;
1570 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1571 if (dump_files[i].pstate || dump_files[i].alt_state)
1572 return 1;
1573 for (i = 0; i < m_extra_dump_files_in_use; i++)
1574 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
1575 return 1;
1576 return 0;
1578 else
1580 struct dump_file_info *dfi = get_dump_file_info (phase);
1581 return dfi->pstate || dfi->alt_state;
1585 /* Returns nonzero if tree dump PHASE has been initialized. */
1588 gcc::dump_manager::
1589 dump_initialized_p (int phase) const
1591 struct dump_file_info *dfi = get_dump_file_info (phase);
1592 return dfi->pstate > 0 || dfi->alt_state > 0;
1595 /* Returns the switch name of PHASE. */
1597 const char *
1598 dump_flag_name (int phase)
1600 return g->get_dumps ()->dump_flag_name (phase);
1603 const char *
1604 gcc::dump_manager::
1605 dump_flag_name (int phase) const
1607 struct dump_file_info *dfi = get_dump_file_info (phase);
1608 return dfi->swtch;
1611 /* Handle -fdump-* and -fopt-info for a pass added after
1612 command-line options are parsed (those from plugins and
1613 those from backends).
1615 Because the registration of plugin/backend passes happens after the
1616 command-line options are parsed, the options that specify single
1617 pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
1618 passes. Therefore we currently can only enable dumping of
1619 new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
1620 are specified. This is done here.
1622 Similarly, the saved -fopt-info options are wired up to the new pass. */
1624 void
1625 gcc::dump_manager::register_pass (opt_pass *pass)
1627 gcc_assert (pass);
1629 register_one_dump_file (pass);
1631 dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number);
1632 gcc_assert (pass_dfi);
1634 enum tree_dump_index tdi;
1635 if (pass->type == SIMPLE_IPA_PASS
1636 || pass->type == IPA_PASS)
1637 tdi = TDI_ipa_all;
1638 else if (pass->type == GIMPLE_PASS)
1639 tdi = TDI_tree_all;
1640 else
1641 tdi = TDI_rtl_all;
1642 const dump_file_info *tdi_dfi = get_dump_file_info (tdi);
1643 gcc_assert (tdi_dfi);
1645 /* Check if dump-all flag is specified. */
1646 if (tdi_dfi->pstate)
1648 pass_dfi->pstate = tdi_dfi->pstate;
1649 pass_dfi->pflags = tdi_dfi->pflags;
1652 update_dfi_for_opt_info (pass_dfi);
1655 /* Finish a tree dump for PHASE. STREAM is the stream created by
1656 dump_begin. */
1658 void
1659 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
1661 if (stream != stderr && stream != stdout)
1662 fclose (stream);
1665 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
1666 enabled tree dumps. */
1669 gcc::dump_manager::
1670 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
1672 int n = 0;
1673 size_t i;
1675 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1677 if (dump_files[i].dkind == dkind)
1679 const char *old_filename = dump_files[i].pfilename;
1680 dump_files[i].pstate = -1;
1681 dump_files[i].pflags |= flags;
1682 n++;
1683 /* Override the existing filename. */
1684 if (filename)
1686 dump_files[i].pfilename = xstrdup (filename);
1687 /* Since it is a command-line provided file, which is
1688 common to all the phases, use it in append mode. */
1689 dump_files[i].pstate = 1;
1691 if (old_filename && filename != old_filename)
1692 free (CONST_CAST (char *, old_filename));
1696 for (i = 0; i < m_extra_dump_files_in_use; i++)
1698 if (m_extra_dump_files[i].dkind == dkind)
1700 const char *old_filename = m_extra_dump_files[i].pfilename;
1701 m_extra_dump_files[i].pstate = -1;
1702 m_extra_dump_files[i].pflags |= flags;
1703 n++;
1704 /* Override the existing filename. */
1705 if (filename)
1707 m_extra_dump_files[i].pfilename = xstrdup (filename);
1708 /* Since it is a command-line provided file, which is
1709 common to all the phases, use it in append mode. */
1710 m_extra_dump_files[i].pstate = 1;
1712 if (old_filename && filename != old_filename)
1713 free (CONST_CAST (char *, old_filename));
1717 return n;
1720 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1721 Enable dumps with FLAGS on FILENAME. Return the number of enabled
1722 dumps. */
1725 gcc::dump_manager::
1726 opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1727 const char *filename)
1729 int n = 0;
1731 m_optgroup_flags = optgroup_flags;
1732 m_optinfo_flags = flags;
1733 m_optinfo_filename = xstrdup (filename);
1735 for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++)
1736 if (update_dfi_for_opt_info (&dump_files[i]))
1737 n++;
1739 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
1740 if (update_dfi_for_opt_info (&m_extra_dump_files[i]))
1741 n++;
1743 return n;
1746 /* Use the saved -fopt-info options to update DFI.
1747 Return true if the dump is enabled. */
1749 bool
1750 gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const
1752 gcc_assert (dfi);
1754 if (!(dfi->optgroup_flags & m_optgroup_flags))
1755 return false;
1757 const char *old_filename = dfi->alt_filename;
1758 /* Since this file is shared among different passes, it
1759 should be opened in append mode. */
1760 dfi->alt_state = 1;
1761 dfi->alt_flags |= m_optinfo_flags;
1762 /* Override the existing filename. */
1763 if (m_optinfo_filename)
1764 dfi->alt_filename = xstrdup (m_optinfo_filename);
1765 if (old_filename && m_optinfo_filename != old_filename)
1766 free (CONST_CAST (char *, old_filename));
1768 return true;
1771 /* Helper routine to parse -<dump format>[=filename]
1772 and return the corresponding dump flag. If POS_P is non-NULL,
1773 assign start of filename into *POS_P. */
1775 dump_flags_t
1776 parse_dump_option (const char *option_value, const char **pos_p)
1778 const char *ptr;
1779 dump_flags_t flags;
1781 ptr = option_value;
1782 if (pos_p)
1783 *pos_p = NULL;
1785 /* Retain "user-facing" and "internals" messages, but filter out
1786 those from an opt_problem being re-emitted at the top level
1787 (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages
1788 messing up scan-tree-dump-times" in DejaGnu tests. */
1789 flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_INTERNALS;
1791 while (*ptr)
1793 const struct kv_pair<dump_flags_t> *option_ptr;
1794 const char *end_ptr;
1795 const char *eq_ptr;
1796 unsigned length;
1797 while (*ptr == '-')
1798 ptr++;
1799 end_ptr = strchr (ptr, '-');
1800 eq_ptr = strchr (ptr, '=');
1802 if (eq_ptr && !end_ptr)
1803 end_ptr = eq_ptr;
1805 if (!end_ptr)
1806 end_ptr = ptr + strlen (ptr);
1807 length = end_ptr - ptr;
1809 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1810 if (strlen (option_ptr->name) == length
1811 && !memcmp (option_ptr->name, ptr, length))
1813 flags |= option_ptr->value;
1814 goto found;
1817 if (*ptr == '=')
1819 /* Interpret rest of the argument as a dump filename. This
1820 filename overrides other command line filenames. */
1821 if (pos_p)
1822 *pos_p = ptr + 1;
1823 break;
1825 else
1827 warning (0, "ignoring unknown option %q.*s",
1828 length, ptr);
1829 flags = TDF_ERROR;
1831 found:
1832 ptr = end_ptr;
1835 return flags;
1838 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1839 relevant details in the dump_files array. */
1842 gcc::dump_manager::
1843 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1845 const char *option_value;
1846 dump_flags_t flags = TDF_NONE;
1848 if (doglob && !dfi->glob)
1849 return 0;
1851 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1852 if (!option_value)
1853 return 0;
1855 if (*option_value && *option_value != '-' && *option_value != '=')
1856 return 0;
1858 const char *filename;
1859 flags = parse_dump_option (option_value, &filename);
1860 if (filename)
1862 if (dfi->pfilename)
1863 free (CONST_CAST (char *, dfi->pfilename));
1864 dfi->pfilename = xstrdup (filename);
1867 dfi->pstate = -1;
1868 dfi->pflags |= flags;
1870 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1871 known dumps. */
1872 if (dfi->suffix == NULL)
1873 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
1875 return 1;
1878 void
1879 gcc::dump_manager::
1880 dump_switch_p (const char *arg)
1882 size_t i;
1883 int any = 0;
1885 for (i = TDI_none + 1; i != TDI_end; i++)
1886 any |= dump_switch_p_1 (arg, &dump_files[i], false);
1888 /* Don't glob if we got a hit already */
1889 if (!any)
1890 for (i = TDI_none + 1; i != TDI_end; i++)
1891 any |= dump_switch_p_1 (arg, &dump_files[i], true);
1893 for (i = 0; i < m_extra_dump_files_in_use; i++)
1894 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
1896 if (!any)
1897 for (i = 0; i < m_extra_dump_files_in_use; i++)
1898 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
1900 if (!any)
1902 auto_vec<const char *> candidates;
1903 for (size_t i = TDI_none + 1; i != TDI_end; i++)
1904 candidates.safe_push (dump_files[i].swtch);
1905 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
1906 candidates.safe_push (m_extra_dump_files[i].swtch);
1907 const char *hint = find_closest_string (arg, &candidates);
1908 if (hint)
1909 error ("unrecognized command-line option %<-fdump-%s%>; "
1910 "did you mean %<-fdump-%s%>?", arg, hint);
1911 else
1912 error ("unrecognized command-line option %<-fdump-%s%>", arg);
1916 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1917 and filename. Return non-zero if it is a recognized switch. */
1919 static int
1920 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
1921 optgroup_flags_t *optgroup_flags, char **filename)
1923 const char *option_value;
1924 const char *ptr;
1926 option_value = arg;
1927 ptr = option_value;
1929 *filename = NULL;
1931 /* Default to filtering out "internals" messages, and retaining
1932 "user-facing" messages, and those from an opt_problem being
1933 re-emitted at the top level. */
1934 *flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_REEMITTED;
1936 *optgroup_flags = OPTGROUP_NONE;
1938 if (!ptr)
1939 return 1; /* Handle '-fopt-info' without any additional options. */
1941 while (*ptr)
1943 const char *end_ptr;
1944 const char *eq_ptr;
1945 unsigned length;
1947 while (*ptr == '-')
1948 ptr++;
1949 end_ptr = strchr (ptr, '-');
1950 eq_ptr = strchr (ptr, '=');
1952 if (eq_ptr && (!end_ptr || eq_ptr < end_ptr))
1953 end_ptr = eq_ptr;
1954 else if (!end_ptr)
1955 end_ptr = ptr + strlen (ptr);
1956 length = end_ptr - ptr;
1958 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
1959 option_ptr->name; option_ptr++)
1960 if (strlen (option_ptr->name) == length
1961 && !memcmp (option_ptr->name, ptr, length))
1963 *flags |= option_ptr->value;
1964 goto found;
1967 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
1968 option_ptr->name; option_ptr++)
1969 if (strlen (option_ptr->name) == length
1970 && !memcmp (option_ptr->name, ptr, length))
1972 *optgroup_flags |= option_ptr->value;
1973 goto found;
1976 if (*ptr == '=')
1978 /* Interpret rest of the argument as a dump filename. This
1979 filename overrides other command line filenames. */
1980 *filename = xstrdup (ptr + 1);
1981 break;
1983 else
1985 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1986 length, ptr, arg);
1987 return 0;
1989 found:;
1990 ptr = end_ptr;
1993 return 1;
1996 /* Return non-zero if ARG is a recognized switch for
1997 -fopt-info. Return zero otherwise. */
2000 opt_info_switch_p (const char *arg)
2002 dump_flags_t flags;
2003 optgroup_flags_t optgroup_flags;
2004 char *filename;
2005 static char *file_seen = NULL;
2006 gcc::dump_manager *dumps = g->get_dumps ();
2008 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
2009 return 0;
2011 if (!filename)
2012 filename = xstrdup ("stderr");
2014 /* Bail out if a different filename has been specified. */
2015 if (file_seen && strcmp (file_seen, filename))
2017 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
2018 arg);
2019 return 1;
2022 file_seen = xstrdup (filename);
2023 if (!(flags & MSG_ALL_KINDS))
2024 flags |= MSG_OPTIMIZED_LOCATIONS;
2025 if (!optgroup_flags)
2026 optgroup_flags = OPTGROUP_ALL;
2028 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
2031 /* Print basic block on the dump streams. */
2033 void
2034 dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
2036 if (dump_file
2037 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
2038 dump_bb (dump_file, bb, indent, TDF_DETAILS);
2039 if (alt_dump_file
2040 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
2041 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
2044 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
2046 void
2047 dump_function (int phase, tree fn)
2049 FILE *stream;
2050 dump_flags_t flags;
2052 stream = dump_begin (phase, &flags);
2053 if (stream)
2055 dump_function_to_file (fn, stream, flags);
2056 dump_end (phase, stream);
2060 /* Print information from the combine pass on dump_file. */
2062 void
2063 print_combine_total_stats (void)
2065 if (dump_file)
2066 dump_combine_total_stats (dump_file);
2069 /* Enable RTL dump for all the RTL passes. */
2071 bool
2072 enable_rtl_dump_file (void)
2074 gcc::dump_manager *dumps = g->get_dumps ();
2075 int num_enabled =
2076 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
2077 NULL);
2078 return num_enabled > 0;
2081 /* debug_dump_context's ctor. Temporarily override the dump_context
2082 (to forcibly enable output to stderr). */
2084 debug_dump_context::debug_dump_context ()
2085 : m_context (),
2086 m_saved (&dump_context::get ()),
2087 m_saved_flags (dump_flags),
2088 m_saved_pflags (pflags),
2089 m_saved_file (dump_file)
2091 set_dump_file (stderr);
2092 dump_context::s_current = &m_context;
2093 pflags = dump_flags = MSG_ALL_KINDS | MSG_ALL_PRIORITIES;
2094 dump_context::get ().refresh_dumps_are_enabled ();
2097 /* debug_dump_context's dtor. Restore the saved dump_context. */
2099 debug_dump_context::~debug_dump_context ()
2101 set_dump_file (m_saved_file);
2102 dump_context::s_current = m_saved;
2103 dump_flags = m_saved_flags;
2104 pflags = m_saved_pflags;
2105 dump_context::get ().refresh_dumps_are_enabled ();
2109 #if CHECKING_P
2111 namespace selftest {
2113 /* temp_dump_context's ctor. Temporarily override the dump_context
2114 (to forcibly enable optinfo-generation). */
2116 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
2117 bool forcibly_enable_dumping,
2118 dump_flags_t test_pp_flags)
2119 : m_context (),
2120 m_saved (&dump_context::get ())
2122 dump_context::s_current = &m_context;
2123 if (forcibly_enable_optinfo)
2124 m_context.set_json_writer (new optrecord_json_writer ());
2125 /* Conditionally enable the test dump, so that we can verify both the
2126 dump_enabled_p and the !dump_enabled_p cases in selftests. */
2127 if (forcibly_enable_dumping)
2129 m_context.m_test_pp = &m_pp;
2130 m_context.m_test_pp_flags = test_pp_flags;
2133 dump_context::get ().refresh_dumps_are_enabled ();
2136 /* temp_dump_context's dtor. Restore the saved dump_context. */
2138 temp_dump_context::~temp_dump_context ()
2140 m_context.set_json_writer (NULL);
2142 dump_context::s_current = m_saved;
2144 dump_context::get ().refresh_dumps_are_enabled ();
2147 /* 0-terminate the text dumped so far, and return it. */
2149 const char *
2150 temp_dump_context::get_dumped_text ()
2152 return pp_formatted_text (&m_pp);
2155 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2156 from EXPECTED_FUNCTION, using LOC for the location of any failure,
2157 provided that the build compiler is sufficiently recent. */
2159 static void
2160 assert_impl_location_eq (const location &loc ATTRIBUTE_UNUSED,
2161 const dump_impl_location_t &impl_loc ATTRIBUTE_UNUSED,
2162 const char *expected_file ATTRIBUTE_UNUSED,
2163 int expected_line ATTRIBUTE_UNUSED,
2164 const char *expected_function ATTRIBUTE_UNUSED)
2166 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
2167 ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_file, expected_file);
2168 ASSERT_EQ_AT (loc, impl_loc.m_line, expected_line);
2169 ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_function, expected_function);
2170 #endif
2173 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2174 from EXPECTED_FUNCTION, provided that the build compiler is
2175 sufficiently recent. */
2177 #define ASSERT_IMPL_LOCATION_EQ(IMPL_LOC, EXPECTED_FILE, EXPECTED_LINE, \
2178 EXPECTED_FUNCTION) \
2179 SELFTEST_BEGIN_STMT \
2180 assert_impl_location_eq (SELFTEST_LOCATION, IMPL_LOC, \
2181 EXPECTED_FILE, EXPECTED_LINE, \
2182 EXPECTED_FUNCTION); \
2183 SELFTEST_END_STMT
2185 /* Verify that the dump_location_t constructors capture the source location
2186 at which they were called (provided that the build compiler is sufficiently
2187 recent). */
2189 static void
2190 test_impl_location ()
2192 /* Default ctor. */
2194 dump_location_t loc;
2195 const int expected_line = __LINE__ - 1;
2196 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2197 "dumpfile.c", expected_line, "test_impl_location");
2200 /* Constructing from a gimple. */
2202 dump_location_t loc ((gimple *)NULL);
2203 const int expected_line = __LINE__ - 1;
2204 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2205 "dumpfile.c", expected_line, "test_impl_location");
2208 /* Constructing from an rtx_insn. */
2210 dump_location_t loc ((rtx_insn *)NULL);
2211 const int expected_line = __LINE__ - 1;
2212 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2213 "dumpfile.c", expected_line, "test_impl_location");
2217 /* Verify that the text dumped so far in CONTEXT equals
2218 EXPECTED_TEXT, using LOC for the location of any failure.
2219 As a side-effect, the internal buffer is 0-terminated. */
2221 void
2222 verify_dumped_text (const location &loc,
2223 temp_dump_context *context,
2224 const char *expected_text)
2226 gcc_assert (context);
2227 ASSERT_STREQ_AT (loc, context->get_dumped_text (),
2228 expected_text);
2231 /* Verify that ITEM has the expected values. */
2233 void
2234 verify_item (const location &loc,
2235 const optinfo_item *item,
2236 enum optinfo_item_kind expected_kind,
2237 location_t expected_location,
2238 const char *expected_text)
2240 ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
2241 ASSERT_EQ_AT (loc, item->get_location (), expected_location);
2242 ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
2245 /* Verify that calls to the dump_* API are captured and consolidated into
2246 optimization records. */
2248 static void
2249 test_capture_of_dump_calls (const line_table_case &case_)
2251 /* Generate a location_t for testing. */
2252 line_table_test ltt (case_);
2253 linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
2254 linemap_line_start (line_table, 5, 100);
2255 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2256 location_t decl_loc = linemap_position_for_column (line_table, 8);
2257 location_t stmt_loc = linemap_position_for_column (line_table, 10);
2258 if (stmt_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
2259 return;
2261 dump_user_location_t loc = dump_user_location_t::from_location_t (stmt_loc);
2263 gimple *stmt = gimple_build_return (NULL);
2264 gimple_set_location (stmt, stmt_loc);
2266 tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
2267 get_identifier ("test_decl"),
2268 build_function_type_list (void_type_node,
2269 NULL_TREE));
2271 symbol_table_test tmp_symtab;
2273 cgraph_node *node = cgraph_node::get_create (test_decl);
2274 gcc_assert (node);
2276 /* Run all tests twice, with and then without optinfo enabled, to ensure
2277 that immediate destinations vs optinfo-based destinations both
2278 work, independently of each other, with no leaks. */
2279 for (int i = 0 ; i < 2; i++)
2281 bool with_optinfo = (i == 0);
2283 /* Test of dump_printf. */
2285 temp_dump_context tmp (with_optinfo, true,
2286 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2287 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
2288 const int expected_impl_line = __LINE__ - 1;
2290 ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
2291 if (with_optinfo)
2293 optinfo *info = tmp.get_pending_optinfo ();
2294 ASSERT_TRUE (info != NULL);
2295 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2296 ASSERT_EQ (info->num_items (), 1);
2297 ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
2298 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2299 "dumpfile.c", expected_impl_line,
2300 "test_capture_of_dump_calls");
2304 /* Test of dump_printf with %T. */
2306 temp_dump_context tmp (with_optinfo, true,
2307 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2308 dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
2309 const int expected_impl_line = __LINE__ - 1;
2311 ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
2312 if (with_optinfo)
2314 optinfo *info = tmp.get_pending_optinfo ();
2315 ASSERT_TRUE (info != NULL);
2316 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2317 ASSERT_EQ (info->num_items (), 2);
2318 ASSERT_IS_TEXT (info->get_item (0), "tree: ");
2319 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2320 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2321 "dumpfile.c", expected_impl_line,
2322 "test_capture_of_dump_calls");
2326 /* Test of dump_printf with %E. */
2328 temp_dump_context tmp (with_optinfo, true,
2329 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2330 dump_printf (MSG_NOTE, "gimple: %E", stmt);
2331 const int expected_impl_line = __LINE__ - 1;
2333 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
2334 if (with_optinfo)
2336 optinfo *info = tmp.get_pending_optinfo ();
2337 ASSERT_TRUE (info != NULL);
2338 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2339 ASSERT_EQ (info->num_items (), 2);
2340 ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
2341 ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
2342 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2343 "dumpfile.c", expected_impl_line,
2344 "test_capture_of_dump_calls");
2348 /* Test of dump_printf with %G. */
2350 temp_dump_context tmp (with_optinfo, true,
2351 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2352 dump_printf (MSG_NOTE, "gimple: %G", stmt);
2353 const int expected_impl_line = __LINE__ - 1;
2355 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
2356 if (with_optinfo)
2358 optinfo *info = tmp.get_pending_optinfo ();
2359 ASSERT_TRUE (info != NULL);
2360 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2361 ASSERT_EQ (info->num_items (), 2);
2362 ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
2363 ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
2364 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2365 "dumpfile.c", expected_impl_line,
2366 "test_capture_of_dump_calls");
2370 /* Test of dump_printf with %C. */
2372 temp_dump_context tmp (with_optinfo, true,
2373 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2374 dump_printf (MSG_NOTE, "node: %C", node);
2375 const int expected_impl_line = __LINE__ - 1;
2377 ASSERT_DUMPED_TEXT_EQ (tmp, "node: test_decl/0");
2378 if (with_optinfo)
2380 optinfo *info = tmp.get_pending_optinfo ();
2381 ASSERT_TRUE (info != NULL);
2382 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2383 ASSERT_EQ (info->num_items (), 2);
2384 ASSERT_IS_TEXT (info->get_item (0), "node: ");
2385 ASSERT_IS_SYMTAB_NODE (info->get_item (1), decl_loc, "test_decl/0");
2386 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2387 "dumpfile.c", expected_impl_line,
2388 "test_capture_of_dump_calls");
2392 /* dump_print_loc with multiple format codes. This tests various
2393 things:
2394 - intermingling of text, format codes handled by the base
2395 pretty_printer, and dump-specific format codes
2396 - multiple dump-specific format codes: some consecutive, others
2397 separated by text, trailing text after the final one. */
2399 temp_dump_context tmp (with_optinfo, true,
2400 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2401 dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
2402 " %i consecutive %E%E after\n",
2403 integer_zero_node, test_decl, 42, stmt, stmt);
2405 ASSERT_DUMPED_TEXT_EQ (tmp,
2406 "test.txt:5:10: note: before 0 and test_decl"
2407 " 42 consecutive return;return; after\n");
2408 if (with_optinfo)
2410 optinfo *info = tmp.get_pending_optinfo ();
2411 ASSERT_TRUE (info != NULL);
2412 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2413 ASSERT_EQ (info->num_items (), 8);
2414 ASSERT_IS_TEXT (info->get_item (0), "before ");
2415 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2416 ASSERT_IS_TEXT (info->get_item (2), " and ");
2417 ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
2418 ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
2419 ASSERT_IS_GIMPLE (info->get_item (5), stmt_loc, "return;");
2420 ASSERT_IS_GIMPLE (info->get_item (6), stmt_loc, "return;");
2421 ASSERT_IS_TEXT (info->get_item (7), " after\n");
2422 /* We don't ASSERT_IMPL_LOCATION_EQ here, to avoid having to
2423 enforce at which exact line the multiline dump_printf_loc
2424 occurred. */
2428 /* Tree, via dump_generic_expr. */
2430 temp_dump_context tmp (with_optinfo, true,
2431 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2432 dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
2433 const int expected_impl_line = __LINE__ - 1;
2434 dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
2436 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
2437 if (with_optinfo)
2439 optinfo *info = tmp.get_pending_optinfo ();
2440 ASSERT_TRUE (info != NULL);
2441 ASSERT_EQ (info->get_location_t (), stmt_loc);
2442 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2443 ASSERT_EQ (info->num_items (), 2);
2444 ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
2445 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2446 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2447 "dumpfile.c", expected_impl_line,
2448 "test_capture_of_dump_calls");
2452 /* Tree, via dump_generic_expr_loc. */
2454 temp_dump_context tmp (with_optinfo, true,
2455 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2456 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
2457 const int expected_impl_line = __LINE__ - 1;
2459 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
2460 if (with_optinfo)
2462 optinfo *info = tmp.get_pending_optinfo ();
2463 ASSERT_TRUE (info != NULL);
2464 ASSERT_EQ (info->get_location_t (), stmt_loc);
2465 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2466 ASSERT_EQ (info->num_items (), 1);
2467 ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
2468 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2469 "dumpfile.c", expected_impl_line,
2470 "test_capture_of_dump_calls");
2474 /* Gimple. */
2476 /* dump_gimple_stmt_loc. */
2478 temp_dump_context tmp (with_optinfo, true,
2479 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2480 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
2481 const int expected_impl_line = __LINE__ - 1;
2483 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
2484 if (with_optinfo)
2486 optinfo *info = tmp.get_pending_optinfo ();
2487 ASSERT_TRUE (info != NULL);
2488 ASSERT_EQ (info->num_items (), 1);
2489 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
2490 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2491 "dumpfile.c", expected_impl_line,
2492 "test_capture_of_dump_calls");
2496 /* dump_gimple_stmt. */
2498 temp_dump_context tmp (with_optinfo, true,
2499 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2500 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
2501 const int expected_impl_line = __LINE__ - 1;
2503 ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
2504 if (with_optinfo)
2506 optinfo *info = tmp.get_pending_optinfo ();
2507 ASSERT_TRUE (info != NULL);
2508 ASSERT_EQ (info->num_items (), 1);
2509 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
2510 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2511 "dumpfile.c", expected_impl_line,
2512 "test_capture_of_dump_calls");
2516 /* dump_gimple_expr_loc. */
2518 temp_dump_context tmp (with_optinfo, true,
2519 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2520 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
2521 const int expected_impl_line = __LINE__ - 1;
2523 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
2524 if (with_optinfo)
2526 optinfo *info = tmp.get_pending_optinfo ();
2527 ASSERT_TRUE (info != NULL);
2528 ASSERT_EQ (info->num_items (), 1);
2529 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
2530 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2531 "dumpfile.c", expected_impl_line,
2532 "test_capture_of_dump_calls");
2536 /* dump_gimple_expr. */
2538 temp_dump_context tmp (with_optinfo, true,
2539 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2540 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
2541 const int expected_impl_line = __LINE__ - 1;
2543 ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
2544 if (with_optinfo)
2546 optinfo *info = tmp.get_pending_optinfo ();
2547 ASSERT_TRUE (info != NULL);
2548 ASSERT_EQ (info->num_items (), 1);
2549 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
2550 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2551 "dumpfile.c", expected_impl_line,
2552 "test_capture_of_dump_calls");
2557 /* symtab_node. */
2559 temp_dump_context tmp (with_optinfo, true,
2560 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2561 dump_symtab_node (MSG_NOTE, node);
2562 const int expected_impl_line = __LINE__ - 1;
2564 ASSERT_DUMPED_TEXT_EQ (tmp, "test_decl/0");
2565 if (with_optinfo)
2567 optinfo *info = tmp.get_pending_optinfo ();
2568 ASSERT_TRUE (info != NULL);
2569 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2570 ASSERT_EQ (info->num_items (), 1);
2571 ASSERT_IS_SYMTAB_NODE (info->get_item (0), decl_loc, "test_decl/0");
2572 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2573 "dumpfile.c", expected_impl_line,
2574 "test_capture_of_dump_calls");
2578 /* poly_int. */
2580 temp_dump_context tmp (with_optinfo, true,
2581 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2582 dump_dec (MSG_NOTE, poly_int64 (42));
2583 const int expected_impl_line = __LINE__ - 1;
2585 ASSERT_DUMPED_TEXT_EQ (tmp, "42");
2586 if (with_optinfo)
2588 optinfo *info = tmp.get_pending_optinfo ();
2589 ASSERT_TRUE (info != NULL);
2590 ASSERT_EQ (info->num_items (), 1);
2591 ASSERT_IS_TEXT (info->get_item (0), "42");
2592 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2593 "dumpfile.c", expected_impl_line,
2594 "test_capture_of_dump_calls");
2598 /* Scopes. Test with all 4 combinations of
2599 filtering by MSG_PRIORITY_USER_FACING
2600 and/or filtering by MSG_PRIORITY_INTERNALS. */
2601 for (int j = 0; j < 3; j++)
2603 dump_flags_t dump_filter = MSG_ALL_KINDS;
2604 if (j % 2)
2605 dump_filter |= MSG_PRIORITY_USER_FACING;
2606 if (j / 2)
2607 dump_filter |= MSG_PRIORITY_INTERNALS;
2609 temp_dump_context tmp (with_optinfo, true, dump_filter);
2610 /* Emit various messages, mostly with implicit priority. */
2611 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
2612 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt,
2613 "explicitly internal msg\n");
2615 AUTO_DUMP_SCOPE ("outer scope", stmt);
2616 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
2618 AUTO_DUMP_SCOPE ("middle scope", stmt);
2619 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
2621 AUTO_DUMP_SCOPE ("inner scope", stmt);
2622 dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
2623 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt,
2624 "explicitly user-facing msg\n");
2626 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
2628 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
2630 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
2631 const int expected_impl_line = __LINE__ - 1;
2633 switch (dump_filter & MSG_ALL_PRIORITIES)
2635 default:
2636 gcc_unreachable ();
2637 case 0:
2638 ASSERT_DUMPED_TEXT_EQ (tmp, "");
2639 break;
2640 case MSG_PRIORITY_USER_FACING:
2641 ASSERT_DUMPED_TEXT_EQ
2642 (tmp,
2643 "test.txt:5:10: note: msg 1\n"
2644 "test.txt:5:10: note: explicitly user-facing msg\n"
2645 "test.txt:5:10: note: msg 7\n");
2646 break;
2647 case MSG_PRIORITY_INTERNALS:
2648 ASSERT_DUMPED_TEXT_EQ
2649 (tmp,
2650 "test.txt:5:10: note: explicitly internal msg\n"
2651 "test.txt:5:10: note: === outer scope ===\n"
2652 "test.txt:5:10: note: msg 2\n"
2653 "test.txt:5:10: note: === middle scope ===\n"
2654 "test.txt:5:10: note: msg 3\n"
2655 "test.txt:5:10: note: === inner scope ===\n"
2656 "test.txt:5:10: note: msg 4\n"
2657 "test.txt:5:10: note: msg 5\n"
2658 "test.txt:5:10: note: msg 6\n");
2659 break;
2660 case MSG_ALL_PRIORITIES:
2661 ASSERT_DUMPED_TEXT_EQ
2662 (tmp,
2663 "test.txt:5:10: note: msg 1\n"
2664 "test.txt:5:10: note: explicitly internal msg\n"
2665 "test.txt:5:10: note: === outer scope ===\n"
2666 "test.txt:5:10: note: msg 2\n"
2667 "test.txt:5:10: note: === middle scope ===\n"
2668 "test.txt:5:10: note: msg 3\n"
2669 "test.txt:5:10: note: === inner scope ===\n"
2670 "test.txt:5:10: note: msg 4\n"
2671 "test.txt:5:10: note: explicitly user-facing msg\n"
2672 "test.txt:5:10: note: msg 5\n"
2673 "test.txt:5:10: note: msg 6\n"
2674 "test.txt:5:10: note: msg 7\n");
2675 break;
2677 if (with_optinfo)
2679 optinfo *info = tmp.get_pending_optinfo ();
2680 ASSERT_TRUE (info != NULL);
2681 ASSERT_EQ (info->num_items (), 1);
2682 ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
2683 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2684 "dumpfile.c", expected_impl_line,
2685 "test_capture_of_dump_calls");
2690 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
2691 above. */
2693 /* MSG_OPTIMIZED_LOCATIONS. */
2695 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
2696 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
2697 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
2698 OPTINFO_KIND_SUCCESS);
2701 /* MSG_MISSED_OPTIMIZATION. */
2703 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
2704 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
2705 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
2706 OPTINFO_KIND_FAILURE);
2710 /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
2712 temp_dump_context tmp (false, true,
2713 MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
2714 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
2716 AUTO_DUMP_SCOPE ("outer scope", stmt);
2717 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
2719 AUTO_DUMP_SCOPE ("middle scope", stmt);
2720 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
2722 AUTO_DUMP_SCOPE ("inner scope", stmt);
2723 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
2725 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
2727 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
2729 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
2731 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized: msg 4\n");
2735 static void
2736 test_pr87025 ()
2738 dump_user_location_t loc
2739 = dump_user_location_t::from_location_t (UNKNOWN_LOCATION);
2741 temp_dump_context tmp (true, true,
2742 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2744 AUTO_DUMP_SCOPE ("outer scope", loc);
2745 dump_printf (MSG_NOTE, "msg1\n");
2749 /* Run all of the selftests within this file. */
2751 void
2752 dumpfile_c_tests ()
2754 test_impl_location ();
2755 for_each_line_table_case (test_capture_of_dump_calls);
2756 test_pr87025 ();
2759 } // namespace selftest
2761 #endif /* CHECKING_P */