1 /* Dump infrastructure for optimizations and intermediate representation.
2    Copyright (C) 2012-2021 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "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"
43 
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))
48 
49 static dump_flags_t pflags;		      /* current dump_flags */
50 
51 static void dump_loc (dump_flags_t, FILE *, location_t);
52 
53 /* Current -fopt-info output stream, if any, and flags.  */
54 static FILE *alt_dump_file = NULL;
55 static dump_flags_t alt_flags;
56 
57 static FILE *dump_open_alternate_stream (struct dump_file_info *);
58 
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;
66 
67 
68 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
69    global.  */
70 
71 void
set_dump_file(FILE * new_dump_file)72 set_dump_file (FILE *new_dump_file)
73 {
74   dumpfile_ensure_any_optinfo_are_flushed ();
75   dump_file = new_dump_file;
76   dump_context::get ().refresh_dumps_are_enabled ();
77 }
78 
79 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
80    global.  */
81 
82 static void
set_alt_dump_file(FILE * new_alt_dump_file)83 set_alt_dump_file (FILE *new_alt_dump_file)
84 {
85   dumpfile_ensure_any_optinfo_are_flushed ();
86   alt_dump_file = new_alt_dump_file;
87   dump_context::get ().refresh_dumps_are_enabled ();
88 }
89 
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}
93 
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] =
97 {
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   DUMP_FILE_INFO (".profile-report", "profile-report", DK_ipa, 0),
107 #define FIRST_AUTO_NUMBERED_DUMP 1
108 #define FIRST_ME_AUTO_NUMBERED_DUMP 5
109 
110   DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
111   DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
112   DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
113   DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
114 };
115 
116 /* Table of dump options. This must be consistent with the TDF_* flags
117    in dumpfile.h and opt_info_options below. */
118 static const kv_pair<dump_flags_t> dump_options[] =
119 {
120   {"none", TDF_NONE},
121   {"address", TDF_ADDRESS},
122   {"asmname", TDF_ASMNAME},
123   {"slim", TDF_SLIM},
124   {"raw", TDF_RAW},
125   {"graph", TDF_GRAPH},
126   {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
127                | MSG_MISSED_OPTIMIZATION
128                | MSG_NOTE)},
129   {"cselib", TDF_CSELIB},
130   {"stats", TDF_STATS},
131   {"blocks", TDF_BLOCKS},
132   {"vops", TDF_VOPS},
133   {"lineno", TDF_LINENO},
134   {"uid", TDF_UID},
135   {"stmtaddr", TDF_STMTADDR},
136   {"memsyms", TDF_MEMSYMS},
137   {"eh", TDF_EH},
138   {"alias", TDF_ALIAS},
139   {"nouid", TDF_NOUID},
140   {"enumerate_locals", TDF_ENUMERATE_LOCALS},
141   {"scev", TDF_SCEV},
142   {"gimple", TDF_GIMPLE},
143   {"folding", TDF_FOLDING},
144   {"optimized", MSG_OPTIMIZED_LOCATIONS},
145   {"missed", MSG_MISSED_OPTIMIZATION},
146   {"note", MSG_NOTE},
147   {"optall", MSG_ALL_KINDS},
148   {"all", dump_flags_t (TDF_ALL_VALUES
149 			& ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
150 			    | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
151 			    | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
152   {NULL, TDF_NONE}
153 };
154 
155 /* A subset of the dump_options table which is used for -fopt-info
156    types. This must be consistent with the MSG_* flags in dumpfile.h.
157  */
158 static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
159 {
160   {"optimized", MSG_OPTIMIZED_LOCATIONS},
161   {"missed", MSG_MISSED_OPTIMIZATION},
162   {"note", MSG_NOTE},
163   {"all", MSG_ALL_KINDS},
164   {"internals", MSG_PRIORITY_INTERNALS},
165   {NULL, TDF_NONE}
166 };
167 
168 /* Flags used for -fopt-info groups.  */
169 const kv_pair<optgroup_flags_t> optgroup_options[] =
170 {
171   {"ipa", OPTGROUP_IPA},
172   {"loop", OPTGROUP_LOOP},
173   {"inline", OPTGROUP_INLINE},
174   {"omp", OPTGROUP_OMP},
175   {"vec", OPTGROUP_VEC},
176   {"optall", OPTGROUP_ALL},
177   {NULL, OPTGROUP_NONE}
178 };
179 
dump_manager()180 gcc::dump_manager::dump_manager ():
181   m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
182   m_extra_dump_files (NULL),
183   m_extra_dump_files_in_use (0),
184   m_extra_dump_files_alloced (0),
185   m_optgroup_flags (OPTGROUP_NONE),
186   m_optinfo_flags (TDF_NONE),
187   m_optinfo_filename (NULL)
188 {
189 }
190 
~dump_manager()191 gcc::dump_manager::~dump_manager ()
192 {
193   free (m_optinfo_filename);
194   for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
195     {
196       dump_file_info *dfi = &m_extra_dump_files[i];
197       /* suffix, swtch, glob are statically allocated for the entries
198 	 in dump_files, and for statistics, but are dynamically allocated
199 	 for those for passes.  */
200       if (dfi->owns_strings)
201 	{
202 	  XDELETEVEC (const_cast <char *> (dfi->suffix));
203 	  XDELETEVEC (const_cast <char *> (dfi->swtch));
204 	  XDELETEVEC (const_cast <char *> (dfi->glob));
205 	}
206       /* These, if non-NULL, are always dynamically allocated.  */
207       XDELETEVEC (const_cast <char *> (dfi->pfilename));
208       XDELETEVEC (const_cast <char *> (dfi->alt_filename));
209     }
210   XDELETEVEC (m_extra_dump_files);
211 }
212 
213 unsigned int
214 gcc::dump_manager::
dump_register(const char * suffix,const char * swtch,const char * glob,dump_kind dkind,optgroup_flags_t optgroup_flags,bool take_ownership)215 dump_register (const char *suffix, const char *swtch, const char *glob,
216 	       dump_kind dkind, optgroup_flags_t optgroup_flags,
217 	       bool take_ownership)
218 {
219   int num = m_next_dump++;
220 
221   size_t count = m_extra_dump_files_in_use++;
222 
223   if (count >= m_extra_dump_files_alloced)
224     {
225       if (m_extra_dump_files_alloced == 0)
226 	m_extra_dump_files_alloced = 512;
227       else
228 	m_extra_dump_files_alloced *= 2;
229       m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
230 				       m_extra_dump_files,
231 				       m_extra_dump_files_alloced);
232 
233       /* Construct a new object in the space allocated above.  */
234       new (m_extra_dump_files + count) dump_file_info ();
235     }
236   else
237     {
238       /* Zero out the already constructed object.  */
239       m_extra_dump_files[count] = dump_file_info ();
240     }
241 
242   m_extra_dump_files[count].suffix = suffix;
243   m_extra_dump_files[count].swtch = swtch;
244   m_extra_dump_files[count].glob = glob;
245   m_extra_dump_files[count].dkind = dkind;
246   m_extra_dump_files[count].optgroup_flags = optgroup_flags;
247   m_extra_dump_files[count].num = num;
248   m_extra_dump_files[count].owns_strings = take_ownership;
249 
250   return count + TDI_end;
251 }
252 
253 
254 /* Allow languages and middle-end to register their dumps before the
255    optimization passes.  */
256 
257 void
258 gcc::dump_manager::
register_dumps()259 register_dumps ()
260 {
261   lang_hooks.register_dumps (this);
262   /* If this assert fails, some FE registered more than
263      FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
264      dump files.  Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly.  */
265   gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
266   m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
267   dump_files[TDI_original].num = m_next_dump++;
268   dump_files[TDI_gimple].num = m_next_dump++;
269   dump_files[TDI_nested].num = m_next_dump++;
270 }
271 
272 
273 /* Return the dump_file_info for the given phase.  */
274 
275 struct dump_file_info *
276 gcc::dump_manager::
get_dump_file_info(int phase)277 get_dump_file_info (int phase) const
278 {
279   if (phase < TDI_end)
280     return &dump_files[phase];
281   else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
282     return NULL;
283   else
284     return m_extra_dump_files + (phase - TDI_end);
285 }
286 
287 /* Locate the dump_file_info with swtch equal to SWTCH,
288    or return NULL if no such dump_file_info exists.  */
289 
290 struct dump_file_info *
291 gcc::dump_manager::
get_dump_file_info_by_switch(const char * swtch)292 get_dump_file_info_by_switch (const char *swtch) const
293 {
294   for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
295     if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
296       return &m_extra_dump_files[i];
297 
298   /* Not found.  */
299   return NULL;
300 }
301 
302 
303 /* Return the name of the dump file for the given phase.
304    The caller is responsible for calling free on the returned
305    buffer.
306    If the dump is not enabled, returns NULL.  */
307 
308 char *
309 gcc::dump_manager::
get_dump_file_name(int phase,int part)310 get_dump_file_name (int phase, int part) const
311 {
312   struct dump_file_info *dfi;
313 
314   if (phase == TDI_none)
315     return NULL;
316 
317   dfi = get_dump_file_info (phase);
318 
319   return get_dump_file_name (dfi, part);
320 }
321 
322 /* Return the name of the dump file for the given dump_file_info.
323    The caller is responsible for calling free on the returned
324    buffer.
325    If the dump is not enabled, returns NULL.  */
326 
327 char *
328 gcc::dump_manager::
get_dump_file_name(struct dump_file_info * dfi,int part)329 get_dump_file_name (struct dump_file_info *dfi, int part) const
330 {
331   char dump_id[10];
332 
333   gcc_assert (dfi);
334 
335   if (dfi->pstate == 0)
336     return NULL;
337 
338   /* If available, use the command line dump filename. */
339   if (dfi->pfilename)
340     return xstrdup (dfi->pfilename);
341 
342   if (dfi->num < 0)
343     dump_id[0] = '\0';
344   else
345     {
346       /* (null), LANG, TREE, RTL, IPA.  */
347       char suffix = " ltri"[dfi->dkind];
348 
349       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
350 	dump_id[0] = '\0';
351     }
352 
353   if (part != -1)
354     {
355        char part_id[8];
356        snprintf (part_id, sizeof (part_id), ".%i", part);
357        return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
358     }
359   else
360     return concat (dump_base_name, dump_id, dfi->suffix, NULL);
361 }
362 
363 /* Open a dump file called FILENAME.  Some filenames are special and
364    refer to the standard streams.  TRUNC indicates whether this is the
365    first open (so the file should be truncated, rather than appended).
366    An error message is emitted in the event of failure.  */
367 
368 static FILE *
dump_open(const char * filename,bool trunc)369 dump_open (const char *filename, bool trunc)
370 {
371   if (strcmp ("stderr", filename) == 0)
372     return stderr;
373 
374   if (strcmp ("stdout", filename) == 0
375       || strcmp ("-", filename) == 0)
376     return stdout;
377 
378   FILE *stream = fopen (filename, trunc ? "w" : "a");
379 
380   if (!stream)
381     error ("could not open dump file %qs: %m", filename);
382   return stream;
383 }
384 
385 /* For a given DFI, open an alternate dump filename (which could also
386    be a standard stream such as stdout/stderr). If the alternate dump
387    file cannot be opened, return NULL.  */
388 
389 static FILE *
dump_open_alternate_stream(struct dump_file_info * dfi)390 dump_open_alternate_stream (struct dump_file_info *dfi)
391 {
392   if (!dfi->alt_filename)
393     return NULL;
394 
395   if (dfi->alt_stream)
396     return dfi->alt_stream;
397 
398   FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
399 
400   if (stream)
401     dfi->alt_state = 1;
402 
403   return stream;
404 }
405 
406 /* Construct a dump_user_location_t from STMT (using its location and
407    hotness).  */
408 
dump_user_location_t(const gimple * stmt)409 dump_user_location_t::dump_user_location_t (const gimple *stmt)
410 : m_count (), m_loc (UNKNOWN_LOCATION)
411 {
412   if (stmt)
413     {
414       if (stmt->bb)
415 	m_count = stmt->bb->count;
416       m_loc = gimple_location (stmt);
417     }
418 }
419 
420 /* Construct a dump_user_location_t from an RTL instruction (using its
421    location and hotness).  */
422 
dump_user_location_t(const rtx_insn * insn)423 dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
424 : m_count (), m_loc (UNKNOWN_LOCATION)
425 {
426   if (insn)
427     {
428       basic_block bb = BLOCK_FOR_INSN (insn);
429       if (bb)
430 	m_count = bb->count;
431       m_loc = INSN_LOCATION (insn);
432     }
433 }
434 
435 /* Construct from a function declaration.  This one requires spelling out
436    to avoid accidentally constructing from other kinds of tree.  */
437 
438 dump_user_location_t
from_function_decl(tree fndecl)439 dump_user_location_t::from_function_decl (tree fndecl)
440 {
441   gcc_assert (fndecl);
442 
443   // FIXME: profile count for function?
444   return dump_user_location_t (profile_count (),
445 			       DECL_SOURCE_LOCATION (fndecl));
446 }
447 
448 /* Extract the MSG_* component from DUMP_KIND and return a string for use
449    as a prefix to dump messages.
450    These match the strings in optinfo_verbosity_options and thus the
451    "OPTIONS" within "-fopt-info-OPTIONS".  */
452 
453 static const char *
kind_as_string(dump_flags_t dump_kind)454 kind_as_string (dump_flags_t dump_kind)
455 {
456   switch (dump_kind & MSG_ALL_KINDS)
457     {
458     default:
459       gcc_unreachable ();
460     case MSG_OPTIMIZED_LOCATIONS:
461       return "optimized";
462     case MSG_MISSED_OPTIMIZATION:
463       return "missed";
464     case MSG_NOTE:
465       return "note";
466     }
467 }
468 
469 /* Print source location on DFILE if enabled.  */
470 
471 static void
dump_loc(dump_flags_t dump_kind,FILE * dfile,location_t loc)472 dump_loc (dump_flags_t dump_kind, FILE *dfile, location_t loc)
473 {
474   if (dump_kind)
475     {
476       if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
477         fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc),
478                  LOCATION_LINE (loc), LOCATION_COLUMN (loc));
479       else if (current_function_decl)
480         fprintf (dfile, "%s:%d:%d: ",
481                  DECL_SOURCE_FILE (current_function_decl),
482                  DECL_SOURCE_LINE (current_function_decl),
483                  DECL_SOURCE_COLUMN (current_function_decl));
484       fprintf (dfile, "%s: ", kind_as_string (dump_kind));
485       /* Indentation based on scope depth.  */
486       fprintf (dfile, "%*s", get_dump_scope_depth (), "");
487     }
488 }
489 
490 /* Print source location to PP if enabled.  */
491 
492 static void
dump_loc(dump_flags_t dump_kind,pretty_printer * pp,location_t loc)493 dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
494 {
495   /* Disable warnings about missing quoting in GCC diagnostics for
496      the pp_printf calls.  Their format strings aren't used to format
497      diagnostics so don't need to follow GCC diagnostic conventions.  */
498 #if __GNUC__ >= 10
499 #  pragma GCC diagnostic push
500 #  pragma GCC diagnostic ignored "-Wformat-diag"
501 #endif
502 
503   if (dump_kind)
504     {
505       if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
506 	pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc),
507 		   LOCATION_LINE (loc), LOCATION_COLUMN (loc));
508       else if (current_function_decl)
509 	pp_printf (pp, "%s:%d:%d: ",
510 		   DECL_SOURCE_FILE (current_function_decl),
511 		   DECL_SOURCE_LINE (current_function_decl),
512 		   DECL_SOURCE_COLUMN (current_function_decl));
513       pp_printf (pp, "%s: ", kind_as_string (dump_kind));
514       /* Indentation based on scope depth.  */
515       for (unsigned i = 0; i < get_dump_scope_depth (); i++)
516 	pp_character (pp, ' ');
517     }
518 
519 #if __GNUC__ >= 10
520 #  pragma GCC diagnostic pop
521 #endif
522 }
523 
524 /* Implementation of dump_context member functions.  */
525 
526 /* dump_context's dtor.  */
527 
~dump_context()528 dump_context::~dump_context ()
529 {
530   delete m_pending;
531 }
532 
533 void
set_json_writer(optrecord_json_writer * writer)534 dump_context::set_json_writer (optrecord_json_writer *writer)
535 {
536   delete m_json_writer;
537   m_json_writer = writer;
538 }
539 
540 /* Perform cleanup activity for -fsave-optimization-record.
541    Currently, the file is written out here in one go, before cleaning
542    up.  */
543 
544 void
finish_any_json_writer()545 dump_context::finish_any_json_writer ()
546 {
547   if (!m_json_writer)
548     return;
549 
550   m_json_writer->write ();
551   delete m_json_writer;
552   m_json_writer = NULL;
553 }
554 
555 /* Update the "dumps_are_enabled" global; to be called whenever dump_file
556    or alt_dump_file change, or when changing dump_context in selftests.  */
557 
558 void
refresh_dumps_are_enabled()559 dump_context::refresh_dumps_are_enabled ()
560 {
561   dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
562 		       || m_test_pp);
563 }
564 
565 /* Determine if a message of kind DUMP_KIND and at the current scope depth
566    should be printed.
567 
568    Only show messages that match FILTER both on their kind *and*
569    their priority.  */
570 
571 bool
apply_dump_filter_p(dump_flags_t dump_kind,dump_flags_t filter)572 dump_context::apply_dump_filter_p (dump_flags_t dump_kind,
573 				   dump_flags_t filter) const
574 {
575   /* Few messages, if any, have an explicit MSG_PRIORITY.
576      If DUMP_KIND does, we'll use it.
577      Otherwise, generate an implicit priority value for the message based
578      on the current scope depth.
579      Messages at the top-level scope are MSG_PRIORITY_USER_FACING,
580      whereas those in nested scopes are MSG_PRIORITY_INTERNALS.  */
581   if (!(dump_kind & MSG_ALL_PRIORITIES))
582     {
583       dump_flags_t implicit_priority
584 	=  (m_scope_depth > 0
585 	    ? MSG_PRIORITY_INTERNALS
586 	    : MSG_PRIORITY_USER_FACING);
587       dump_kind |= implicit_priority;
588     }
589 
590   return (dump_kind & (filter & MSG_ALL_KINDS)
591 	  && dump_kind & (filter & MSG_ALL_PRIORITIES));
592 }
593 
594 /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
595    If optinfos are enabled, begin a new optinfo.  */
596 
597 void
dump_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc)598 dump_context::dump_loc (const dump_metadata_t &metadata,
599 			const dump_user_location_t &loc)
600 {
601   end_any_optinfo ();
602 
603   dump_loc_immediate (metadata.get_dump_flags (), loc);
604 
605   if (optinfo_enabled_p ())
606     begin_next_optinfo (metadata, loc);
607 }
608 
609 /* As dump_loc above, but without starting a new optinfo. */
610 
611 void
dump_loc_immediate(dump_flags_t dump_kind,const dump_user_location_t & loc)612 dump_context::dump_loc_immediate (dump_flags_t dump_kind,
613 				  const dump_user_location_t &loc)
614 {
615   location_t srcloc = loc.get_location_t ();
616 
617   if (dump_file && apply_dump_filter_p (dump_kind, pflags))
618     ::dump_loc (dump_kind, dump_file, srcloc);
619 
620   if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
621     ::dump_loc (dump_kind, alt_dump_file, srcloc);
622 
623   /* Support for temp_dump_context in selftests.  */
624   if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
625     ::dump_loc (dump_kind, m_test_pp, srcloc);
626 }
627 
628 /* Make an item for the given dump call, equivalent to print_gimple_stmt.  */
629 
630 static optinfo_item *
make_item_for_dump_gimple_stmt(gimple * stmt,int spc,dump_flags_t dump_flags)631 make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
632 {
633   pretty_printer pp;
634   pp_needs_newline (&pp) = true;
635   pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
636   pp_newline (&pp);
637 
638   optinfo_item *item
639     = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
640 			xstrdup (pp_formatted_text (&pp)));
641   return item;
642 }
643 
644 /* Dump gimple statement GS with SPC indentation spaces and
645    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
646 
647 void
dump_gimple_stmt(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,gimple * gs,int spc)648 dump_context::dump_gimple_stmt (const dump_metadata_t &metadata,
649 				dump_flags_t extra_dump_flags,
650 				gimple *gs, int spc)
651 {
652   optinfo_item *item
653     = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
654   emit_item (item, metadata.get_dump_flags ());
655 
656   if (optinfo_enabled_p ())
657     {
658       optinfo &info = ensure_pending_optinfo (metadata);
659       info.add_item (item);
660     }
661   else
662     delete item;
663 }
664 
665 /* Similar to dump_gimple_stmt, except additionally print source location.  */
666 
667 void
dump_gimple_stmt_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,gimple * gs,int spc)668 dump_context::dump_gimple_stmt_loc (const dump_metadata_t &metadata,
669 				    const dump_user_location_t &loc,
670 				    dump_flags_t extra_dump_flags,
671 				    gimple *gs, int spc)
672 {
673   dump_loc (metadata, loc);
674   dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
675 }
676 
677 /* Make an item for the given dump call, equivalent to print_gimple_expr.  */
678 
679 static optinfo_item *
make_item_for_dump_gimple_expr(gimple * stmt,int spc,dump_flags_t dump_flags)680 make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
681 {
682   dump_flags |= TDF_RHS_ONLY;
683   pretty_printer pp;
684   pp_needs_newline (&pp) = true;
685   pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
686 
687   optinfo_item *item
688     = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
689 			xstrdup (pp_formatted_text (&pp)));
690   return item;
691 }
692 
693 /* Dump gimple statement GS with SPC indentation spaces and
694    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
695    Do not terminate with a newline or semicolon.  */
696 
697 void
dump_gimple_expr(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,gimple * gs,int spc)698 dump_context::dump_gimple_expr (const dump_metadata_t &metadata,
699 				dump_flags_t extra_dump_flags,
700 				gimple *gs, int spc)
701 {
702   optinfo_item *item
703     = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
704   emit_item (item, metadata.get_dump_flags ());
705 
706   if (optinfo_enabled_p ())
707     {
708       optinfo &info = ensure_pending_optinfo (metadata);
709       info.add_item (item);
710     }
711   else
712     delete item;
713 }
714 
715 /* Similar to dump_gimple_expr, except additionally print source location.  */
716 
717 void
dump_gimple_expr_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,gimple * gs,int spc)718 dump_context::dump_gimple_expr_loc (const dump_metadata_t &metadata,
719 				    const dump_user_location_t &loc,
720 				    dump_flags_t extra_dump_flags,
721 				    gimple *gs,
722 				    int spc)
723 {
724   dump_loc (metadata, loc);
725   dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
726 }
727 
728 /* Make an item for the given dump call, equivalent to print_generic_expr.  */
729 
730 static optinfo_item *
make_item_for_dump_generic_expr(tree node,dump_flags_t dump_flags)731 make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
732 {
733   pretty_printer pp;
734   pp_needs_newline (&pp) = true;
735   pp_translate_identifiers (&pp) = false;
736   dump_generic_node (&pp, node, 0, dump_flags, false);
737 
738   location_t loc = UNKNOWN_LOCATION;
739   if (EXPR_HAS_LOCATION (node))
740     loc = EXPR_LOCATION (node);
741 
742   optinfo_item *item
743     = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
744 			xstrdup (pp_formatted_text (&pp)));
745   return item;
746 }
747 
748 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
749    DUMP_KIND is enabled.  */
750 
751 void
dump_generic_expr(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,tree t)752 dump_context::dump_generic_expr (const dump_metadata_t &metadata,
753 				 dump_flags_t extra_dump_flags,
754 				 tree t)
755 {
756   optinfo_item *item
757     = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
758   emit_item (item, metadata.get_dump_flags ());
759 
760   if (optinfo_enabled_p ())
761     {
762       optinfo &info = ensure_pending_optinfo (metadata);
763       info.add_item (item);
764     }
765   else
766     delete item;
767 }
768 
769 
770 /* Similar to dump_generic_expr, except additionally print the source
771    location.  */
772 
773 void
dump_generic_expr_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,tree t)774 dump_context::dump_generic_expr_loc (const dump_metadata_t &metadata,
775 				     const dump_user_location_t &loc,
776 				     dump_flags_t extra_dump_flags,
777 				     tree t)
778 {
779   dump_loc (metadata, loc);
780   dump_generic_expr (metadata, extra_dump_flags, t);
781 }
782 
783 /* Make an item for the given dump call.  */
784 
785 static optinfo_item *
make_item_for_dump_symtab_node(symtab_node * node)786 make_item_for_dump_symtab_node (symtab_node *node)
787 {
788   location_t loc = DECL_SOURCE_LOCATION (node->decl);
789   optinfo_item *item
790     = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
791 			xstrdup (node->dump_name ()));
792   return item;
793 }
794 
795 /* dump_pretty_printer's ctor.  */
796 
dump_pretty_printer(dump_context * context,dump_flags_t dump_kind)797 dump_pretty_printer::dump_pretty_printer (dump_context *context,
798 					  dump_flags_t dump_kind)
799 : pretty_printer (), m_context (context), m_dump_kind (dump_kind),
800   m_stashed_items ()
801 {
802   pp_format_decoder (this) = format_decoder_cb;
803 }
804 
805 /* Phase 3 of formatting; compare with pp_output_formatted_text.
806 
807    Emit optinfo_item instances for the various formatted chunks from phases
808    1 and 2 (i.e. pp_format).
809 
810    Some chunks may already have had their items built (during decode_format).
811    These chunks have been stashed into m_stashed_items; we emit them here.
812 
813    For all other purely textual chunks, they are printed into
814    buffer->formatted_obstack, and then emitted as a textual optinfo_item.
815    This consolidates multiple adjacent text chunks into a single text
816    optinfo_item.  */
817 
818 void
emit_items(optinfo * dest)819 dump_pretty_printer::emit_items (optinfo *dest)
820 {
821   output_buffer *buffer = pp_buffer (this);
822   struct chunk_info *chunk_array = buffer->cur_chunk_array;
823   const char **args = chunk_array->args;
824 
825   gcc_assert (buffer->obstack == &buffer->formatted_obstack);
826   gcc_assert (buffer->line_length == 0);
827 
828   unsigned stashed_item_idx = 0;
829   for (unsigned chunk = 0; args[chunk]; chunk++)
830     {
831       if (stashed_item_idx < m_stashed_items.length ()
832 	  && args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr)
833 	{
834 	  emit_any_pending_textual_chunks (dest);
835 	  /* This chunk has a stashed item: use it.  */
836 	  emit_item (m_stashed_items[stashed_item_idx++].item, dest);
837 	}
838       else
839 	/* This chunk is purely textual.  Print it (to
840 	   buffer->formatted_obstack), so that we can consolidate adjacent
841 	   chunks into one textual optinfo_item.  */
842 	pp_string (this, args[chunk]);
843     }
844 
845   emit_any_pending_textual_chunks (dest);
846 
847   /* Ensure that we consumed all of stashed_items.  */
848   gcc_assert (stashed_item_idx == m_stashed_items.length ());
849 
850   /* Deallocate the chunk structure and everything after it (i.e. the
851      associated series of formatted strings).  */
852   buffer->cur_chunk_array = chunk_array->prev;
853   obstack_free (&buffer->chunk_obstack, chunk_array);
854 }
855 
856 /* Subroutine of dump_pretty_printer::emit_items
857    for consolidating multiple adjacent pure-text chunks into single
858    optinfo_items (in phase 3).  */
859 
860 void
emit_any_pending_textual_chunks(optinfo * dest)861 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest)
862 {
863   gcc_assert (buffer->obstack == &buffer->formatted_obstack);
864 
865   /* Don't emit an item if the pending text is empty.  */
866   if (output_buffer_last_position_in_text (buffer) == NULL)
867     return;
868 
869   char *formatted_text = xstrdup (pp_formatted_text (this));
870   optinfo_item *item
871     = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
872 			formatted_text);
873   emit_item (item, dest);
874 
875   /* Clear the pending text by unwinding formatted_text back to the start
876      of the buffer (without deallocating).  */
877   obstack_free (&buffer->formatted_obstack,
878 		buffer->formatted_obstack.object_base);
879 }
880 
881 /* Emit ITEM and take ownership of it.  If DEST is non-NULL, add ITEM
882    to DEST; otherwise delete ITEM.  */
883 
884 void
emit_item(optinfo_item * item,optinfo * dest)885 dump_pretty_printer::emit_item (optinfo_item *item, optinfo *dest)
886 {
887   m_context->emit_item (item, m_dump_kind);
888   if (dest)
889     dest->add_item (item);
890   else
891     delete item;
892 }
893 
894 /* Record that ITEM (generated in phase 2 of formatting) is to be used for
895    the chunk at BUFFER_PTR in phase 3 (by emit_items).  */
896 
897 void
stash_item(const char ** buffer_ptr,optinfo_item * item)898 dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item)
899 {
900   gcc_assert (buffer_ptr);
901   gcc_assert (item);
902 
903   m_stashed_items.safe_push (stashed_item (buffer_ptr, item));
904 }
905 
906 /* pp_format_decoder callback for dump_pretty_printer, and thus for
907    dump_printf and dump_printf_loc.
908 
909    A wrapper around decode_format, for type-safety.  */
910 
911 bool
format_decoder_cb(pretty_printer * pp,text_info * text,const char * spec,int,bool,bool,bool,bool *,const char ** buffer_ptr)912 dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
913 					const char *spec, int /*precision*/,
914 					bool /*wide*/, bool /*set_locus*/,
915 					bool /*verbose*/, bool */*quoted*/,
916 					const char **buffer_ptr)
917 {
918   dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
919   return opp->decode_format (text, spec, buffer_ptr);
920 }
921 
922 /* Format decoder for dump_pretty_printer, and thus for dump_printf and
923    dump_printf_loc.
924 
925    Supported format codes (in addition to the standard pretty_printer ones)
926    are:
927 
928    %C: cgraph_node *:
929        Equivalent to: dump_symtab_node (MSG_*, node)
930    %E: gimple *:
931        Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
932    %G: gimple *:
933        Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
934    %T: tree:
935        Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
936 
937    TODO: add a format code that can handle (symtab_node*) *and* both
938    subclasses (presumably means teaching -Wformat about non-virtual
939    subclasses).
940 
941    These format codes build optinfo_item instances, thus capturing metadata
942    about the arguments being dumped, as well as the textual output.  */
943 
944 bool
decode_format(text_info * text,const char * spec,const char ** buffer_ptr)945 dump_pretty_printer::decode_format (text_info *text, const char *spec,
946 				       const char **buffer_ptr)
947 {
948   /* Various format codes that imply making an optinfo_item and stashed it
949      for later use (to capture metadata, rather than plain text).  */
950   switch (*spec)
951     {
952     case 'C':
953       {
954 	cgraph_node *node = va_arg (*text->args_ptr, cgraph_node *);
955 
956 	/* Make an item for the node, and stash it.  */
957 	optinfo_item *item = make_item_for_dump_symtab_node (node);
958 	stash_item (buffer_ptr, item);
959 	return true;
960       }
961 
962     case 'E':
963       {
964 	gimple *stmt = va_arg (*text->args_ptr, gimple *);
965 
966 	/* Make an item for the stmt, and stash it.  */
967 	optinfo_item *item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
968 	stash_item (buffer_ptr, item);
969 	return true;
970       }
971 
972     case 'G':
973       {
974 	gimple *stmt = va_arg (*text->args_ptr, gimple *);
975 
976 	/* Make an item for the stmt, and stash it.  */
977 	optinfo_item *item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
978 	stash_item (buffer_ptr, item);
979 	return true;
980       }
981 
982     case 'T':
983       {
984 	tree t = va_arg (*text->args_ptr, tree);
985 
986 	/* Make an item for the tree, and stash it.  */
987 	optinfo_item *item = make_item_for_dump_generic_expr (t, TDF_SLIM);
988 	stash_item (buffer_ptr, item);
989 	return true;
990       }
991 
992     default:
993       return false;
994     }
995 }
996 
997 /* Output a formatted message using FORMAT on appropriate dump streams.  */
998 
999 void
dump_printf_va(const dump_metadata_t & metadata,const char * format,va_list * ap)1000 dump_context::dump_printf_va (const dump_metadata_t &metadata, const char *format,
1001 			      va_list *ap)
1002 {
1003   dump_pretty_printer pp (this, metadata.get_dump_flags ());
1004 
1005   text_info text;
1006   text.err_no = errno;
1007   text.args_ptr = ap;
1008   text.format_spec = format;
1009 
1010   /* Phases 1 and 2, using pp_format.  */
1011   pp_format (&pp, &text);
1012 
1013   /* Phase 3.  */
1014   if (optinfo_enabled_p ())
1015     {
1016       optinfo &info = ensure_pending_optinfo (metadata);
1017       pp.emit_items (&info);
1018     }
1019   else
1020     pp.emit_items (NULL);
1021 }
1022 
1023 /* Similar to dump_printf, except source location is also printed, and
1024    dump location captured.  */
1025 
1026 void
dump_printf_loc_va(const dump_metadata_t & metadata,const dump_user_location_t & loc,const char * format,va_list * ap)1027 dump_context::dump_printf_loc_va (const dump_metadata_t &metadata,
1028 				  const dump_user_location_t &loc,
1029 				  const char *format, va_list *ap)
1030 {
1031   dump_loc (metadata, loc);
1032   dump_printf_va (metadata, format, ap);
1033 }
1034 
1035 /* Make an item for the given dump call, equivalent to print_dec.  */
1036 
1037 template<unsigned int N, typename C>
1038 static optinfo_item *
make_item_for_dump_dec(const poly_int<N,C> & value)1039 make_item_for_dump_dec (const poly_int<N, C> &value)
1040 {
1041   STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
1042   signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
1043 
1044   pretty_printer pp;
1045 
1046   if (value.is_constant ())
1047     pp_wide_int (&pp, value.coeffs[0], sgn);
1048   else
1049     {
1050       pp_character (&pp, '[');
1051       for (unsigned int i = 0; i < N; ++i)
1052 	{
1053 	  pp_wide_int (&pp, value.coeffs[i], sgn);
1054 	  pp_character (&pp, i == N - 1 ? ']' : ',');
1055 	}
1056     }
1057 
1058   optinfo_item *item
1059     = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
1060 			xstrdup (pp_formatted_text (&pp)));
1061   return item;
1062 }
1063 
1064 /* Output VALUE in decimal to appropriate dump streams.  */
1065 
1066 template<unsigned int N, typename C>
1067 void
dump_dec(const dump_metadata_t & metadata,const poly_int<N,C> & value)1068 dump_context::dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
1069 {
1070   optinfo_item *item = make_item_for_dump_dec (value);
1071   emit_item (item, metadata.get_dump_flags ());
1072 
1073   if (optinfo_enabled_p ())
1074     {
1075       optinfo &info = ensure_pending_optinfo (metadata);
1076       info.add_item (item);
1077     }
1078   else
1079     delete item;
1080 }
1081 
1082 /* Output the name of NODE on appropriate dump streams.  */
1083 
1084 void
dump_symtab_node(const dump_metadata_t & metadata,symtab_node * node)1085 dump_context::dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
1086 {
1087   optinfo_item *item = make_item_for_dump_symtab_node (node);
1088   emit_item (item, metadata.get_dump_flags ());
1089 
1090   if (optinfo_enabled_p ())
1091     {
1092       optinfo &info = ensure_pending_optinfo (metadata);
1093       info.add_item (item);
1094     }
1095   else
1096     delete item;
1097 }
1098 
1099 /* Get the current dump scope-nesting depth.
1100    For use by -fopt-info (for showing nesting via indentation).  */
1101 
1102 unsigned int
get_scope_depth()1103 dump_context::get_scope_depth () const
1104 {
1105   return m_scope_depth;
1106 }
1107 
1108 /* Push a nested dump scope.
1109    Increment the scope depth.
1110    Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1111    destination, if any.
1112    Emit a "scope" optinfo if optinfos are enabled.  */
1113 
1114 void
begin_scope(const char * name,const dump_user_location_t & user_location,const dump_impl_location_t & impl_location)1115 dump_context::begin_scope (const char *name,
1116 			   const dump_user_location_t &user_location,
1117 			   const dump_impl_location_t &impl_location)
1118 {
1119   m_scope_depth++;
1120 
1121   location_t src_loc = user_location.get_location_t ();
1122 
1123   if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags))
1124     ::dump_loc (MSG_NOTE, dump_file, src_loc);
1125 
1126   if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags))
1127     ::dump_loc (MSG_NOTE, alt_dump_file, src_loc);
1128 
1129   /* Support for temp_dump_context in selftests.  */
1130   if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
1131     ::dump_loc (MSG_NOTE, m_test_pp, src_loc);
1132 
1133   /* Format multiple consecutive punctuation characters via %s to
1134      avoid -Wformat-diag in the pp_printf call below whose output
1135      isn't used for diagnostic output.  */
1136   pretty_printer pp;
1137   pp_printf (&pp, "%s %s %s", "===", name, "===");
1138   pp_newline (&pp);
1139   optinfo_item *item
1140     = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
1141 			xstrdup (pp_formatted_text (&pp)));
1142   emit_item (item, MSG_NOTE);
1143 
1144   if (optinfo_enabled_p ())
1145     {
1146       optinfo &info
1147 	= begin_next_optinfo (dump_metadata_t (MSG_NOTE, impl_location),
1148 			      user_location);
1149       info.m_kind = OPTINFO_KIND_SCOPE;
1150       info.add_item (item);
1151       end_any_optinfo ();
1152     }
1153   else
1154     delete item;
1155 }
1156 
1157 /* Pop a nested dump scope.  */
1158 
1159 void
end_scope()1160 dump_context::end_scope ()
1161 {
1162   end_any_optinfo ();
1163   m_scope_depth--;
1164 
1165   if (m_json_writer)
1166     m_json_writer->pop_scope ();
1167 }
1168 
1169 /* Should optinfo instances be created?
1170    All creation of optinfos should be guarded by this predicate.
1171    Return true if any optinfo destinations are active.  */
1172 
1173 bool
optinfo_enabled_p()1174 dump_context::optinfo_enabled_p () const
1175 {
1176   return (optimization_records_enabled_p ());
1177 }
1178 
1179 /* Return the optinfo currently being accumulated, creating one if
1180    necessary.  */
1181 
1182 optinfo &
ensure_pending_optinfo(const dump_metadata_t & metadata)1183 dump_context::ensure_pending_optinfo (const dump_metadata_t &metadata)
1184 {
1185   if (!m_pending)
1186     return begin_next_optinfo (metadata, dump_user_location_t ());
1187   return *m_pending;
1188 }
1189 
1190 /* Start a new optinfo and return it, ending any optinfo that was already
1191    accumulated.  */
1192 
1193 optinfo &
begin_next_optinfo(const dump_metadata_t & metadata,const dump_user_location_t & user_loc)1194 dump_context::begin_next_optinfo (const dump_metadata_t &metadata,
1195 				  const dump_user_location_t &user_loc)
1196 {
1197   end_any_optinfo ();
1198   gcc_assert (m_pending == NULL);
1199   dump_location_t loc (user_loc, metadata.get_impl_location ());
1200   m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
1201   m_pending->handle_dump_file_kind (metadata.get_dump_flags ());
1202   return *m_pending;
1203 }
1204 
1205 /* End any optinfo that has been accumulated within this context; emitting
1206    it to any destinations as appropriate, such as optimization records.  */
1207 
1208 void
end_any_optinfo()1209 dump_context::end_any_optinfo ()
1210 {
1211   if (m_pending)
1212     emit_optinfo (m_pending);
1213   delete m_pending;
1214   m_pending = NULL;
1215 }
1216 
1217 /* Emit the optinfo to all of the "non-immediate" destinations
1218    (emission to "immediate" destinations is done by
1219    dump_context::emit_item).  */
1220 
1221 void
emit_optinfo(const optinfo * info)1222 dump_context::emit_optinfo (const optinfo *info)
1223 {
1224   /* -fsave-optimization-record.  */
1225   if (m_json_writer)
1226     m_json_writer->add_record (info);
1227 }
1228 
1229 /* Emit ITEM to all item destinations (those that don't require
1230    consolidation into optinfo instances).  */
1231 
1232 void
emit_item(optinfo_item * item,dump_flags_t dump_kind)1233 dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind)
1234 {
1235   if (dump_file && apply_dump_filter_p (dump_kind, pflags))
1236     fprintf (dump_file, "%s", item->get_text ());
1237 
1238   if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
1239     fprintf (alt_dump_file, "%s", item->get_text ());
1240 
1241   /* Support for temp_dump_context in selftests.  */
1242   if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
1243     pp_string (m_test_pp, item->get_text ());
1244 }
1245 
1246 /* The current singleton dump_context, and its default.  */
1247 
1248 dump_context *dump_context::s_current = &dump_context::s_default;
1249 dump_context dump_context::s_default;
1250 
1251 /* Implementation of dump_* API calls, calling into dump_context
1252    member functions.  */
1253 
1254 /* Calls to the dump_* functions do non-trivial work, so they ought
1255    to be guarded by:
1256      if (dump_enabled_p ())
1257    Assert that they are guarded, and, if assertions are disabled,
1258    bail out if the calls weren't properly guarded.  */
1259 
1260 #define VERIFY_DUMP_ENABLED_P \
1261   do {					\
1262     gcc_assert (dump_enabled_p ());	\
1263     if (!dump_enabled_p ())		\
1264       return;				\
1265   } while (0)
1266 
1267 /* Dump gimple statement GS with SPC indentation spaces and
1268    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
1269 
1270 void
dump_gimple_stmt(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,gimple * gs,int spc)1271 dump_gimple_stmt (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
1272 		  gimple *gs, int spc)
1273 {
1274   VERIFY_DUMP_ENABLED_P;
1275   dump_context::get ().dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
1276 }
1277 
1278 /* Similar to dump_gimple_stmt, except additionally print source location.  */
1279 
1280 void
dump_gimple_stmt_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,gimple * gs,int spc)1281 dump_gimple_stmt_loc (const dump_metadata_t &metadata,
1282 		      const dump_user_location_t &loc,
1283 		      dump_flags_t extra_dump_flags, gimple *gs, int spc)
1284 {
1285   VERIFY_DUMP_ENABLED_P;
1286   dump_context::get ().dump_gimple_stmt_loc (metadata, loc, extra_dump_flags,
1287 					     gs, spc);
1288 }
1289 
1290 /* Dump gimple statement GS with SPC indentation spaces and
1291    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
1292    Do not terminate with a newline or semicolon.  */
1293 
1294 void
dump_gimple_expr(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,gimple * gs,int spc)1295 dump_gimple_expr (const dump_metadata_t &metadata,
1296 		  dump_flags_t extra_dump_flags,
1297 		  gimple *gs, int spc)
1298 {
1299   VERIFY_DUMP_ENABLED_P;
1300   dump_context::get ().dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
1301 }
1302 
1303 /* Similar to dump_gimple_expr, except additionally print source location.  */
1304 
1305 void
dump_gimple_expr_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,gimple * gs,int spc)1306 dump_gimple_expr_loc (const dump_metadata_t &metadata,
1307 		      const dump_user_location_t &loc,
1308 		      dump_flags_t extra_dump_flags, gimple *gs, int spc)
1309 {
1310   VERIFY_DUMP_ENABLED_P;
1311   dump_context::get ().dump_gimple_expr_loc (metadata, loc, extra_dump_flags,
1312 					     gs, spc);
1313 }
1314 
1315 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
1316    DUMP_KIND is enabled.  */
1317 
1318 void
dump_generic_expr(const dump_metadata_t & metadata,dump_flags_t extra_dump_flags,tree t)1319 dump_generic_expr (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
1320 		   tree t)
1321 {
1322   VERIFY_DUMP_ENABLED_P;
1323   dump_context::get ().dump_generic_expr (metadata, extra_dump_flags, t);
1324 }
1325 
1326 /* Similar to dump_generic_expr, except additionally print the source
1327    location.  */
1328 
1329 void
dump_generic_expr_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,dump_flags_t extra_dump_flags,tree t)1330 dump_generic_expr_loc (const dump_metadata_t &metadata,
1331 		       const dump_user_location_t &loc,
1332 		       dump_flags_t extra_dump_flags, tree t)
1333 {
1334   VERIFY_DUMP_ENABLED_P;
1335   dump_context::get ().dump_generic_expr_loc (metadata, loc, extra_dump_flags,
1336 					      t);
1337 }
1338 
1339 /* Output a formatted message using FORMAT on appropriate dump streams.  */
1340 
1341 void
dump_printf(const dump_metadata_t & metadata,const char * format,...)1342 dump_printf (const dump_metadata_t &metadata, const char *format, ...)
1343 {
1344   VERIFY_DUMP_ENABLED_P;
1345   va_list ap;
1346   va_start (ap, format);
1347   dump_context::get ().dump_printf_va (metadata, format, &ap);
1348   va_end (ap);
1349 }
1350 
1351 /* Similar to dump_printf, except source location is also printed, and
1352    dump location captured.  */
1353 
1354 void
dump_printf_loc(const dump_metadata_t & metadata,const dump_user_location_t & loc,const char * format,...)1355 dump_printf_loc (const dump_metadata_t &metadata,
1356 		 const dump_user_location_t &loc,
1357 		 const char *format, ...)
1358 {
1359   VERIFY_DUMP_ENABLED_P;
1360   va_list ap;
1361   va_start (ap, format);
1362   dump_context::get ().dump_printf_loc_va (metadata, loc, format, &ap);
1363   va_end (ap);
1364 }
1365 
1366 /* Output VALUE in decimal to appropriate dump streams.  */
1367 
1368 template<unsigned int N, typename C>
1369 void
dump_dec(const dump_metadata_t & metadata,const poly_int<N,C> & value)1370 dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
1371 {
1372   VERIFY_DUMP_ENABLED_P;
1373   dump_context::get ().dump_dec (metadata, value);
1374 }
1375 
1376 template void dump_dec (const dump_metadata_t &metadata, const poly_uint16 &);
1377 template void dump_dec (const dump_metadata_t &metadata, const poly_int64 &);
1378 template void dump_dec (const dump_metadata_t &metadata, const poly_uint64 &);
1379 template void dump_dec (const dump_metadata_t &metadata, const poly_offset_int &);
1380 template void dump_dec (const dump_metadata_t &metadata, const poly_widest_int &);
1381 
1382 void
dump_dec(dump_flags_t dump_kind,const poly_wide_int & value,signop sgn)1383 dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
1384 {
1385   VERIFY_DUMP_ENABLED_P;
1386   if (dump_file
1387       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
1388     print_dec (value, dump_file, sgn);
1389 
1390   if (alt_dump_file
1391       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
1392     print_dec (value, alt_dump_file, sgn);
1393 }
1394 
1395 /* Output VALUE in hexadecimal to appropriate dump streams.  */
1396 
1397 void
dump_hex(dump_flags_t dump_kind,const poly_wide_int & value)1398 dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
1399 {
1400   VERIFY_DUMP_ENABLED_P;
1401   if (dump_file
1402       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
1403     print_hex (value, dump_file);
1404 
1405   if (alt_dump_file
1406       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
1407     print_hex (value, alt_dump_file);
1408 }
1409 
1410 /* Emit and delete the currently pending optinfo, if there is one,
1411    without the caller needing to know about class dump_context.  */
1412 
1413 void
dumpfile_ensure_any_optinfo_are_flushed()1414 dumpfile_ensure_any_optinfo_are_flushed ()
1415 {
1416   dump_context::get().end_any_optinfo ();
1417 }
1418 
1419 /* Output the name of NODE on appropriate dump streams.  */
1420 
1421 void
dump_symtab_node(const dump_metadata_t & metadata,symtab_node * node)1422 dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
1423 {
1424   VERIFY_DUMP_ENABLED_P;
1425   dump_context::get ().dump_symtab_node (metadata, node);
1426 }
1427 
1428 /* Get the current dump scope-nesting depth.
1429    For use by -fopt-info (for showing nesting via indentation).  */
1430 
1431 unsigned int
get_dump_scope_depth()1432 get_dump_scope_depth ()
1433 {
1434   return dump_context::get ().get_scope_depth ();
1435 }
1436 
1437 /* Push a nested dump scope.
1438    Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1439    destination, if any.
1440    Emit a "scope" opinfo if optinfos are enabled.
1441    Increment the scope depth.  */
1442 
1443 void
dump_begin_scope(const char * name,const dump_user_location_t & user_location,const dump_impl_location_t & impl_location)1444 dump_begin_scope (const char *name,
1445 		  const dump_user_location_t &user_location,
1446 		  const dump_impl_location_t &impl_location)
1447 {
1448   dump_context::get ().begin_scope (name, user_location, impl_location);
1449 }
1450 
1451 /* Pop a nested dump scope.  */
1452 
1453 void
dump_end_scope()1454 dump_end_scope ()
1455 {
1456   dump_context::get ().end_scope ();
1457 }
1458 
1459 /* Start a dump for PHASE. Store user-supplied dump flags in
1460    *FLAG_PTR.  Return the number of streams opened.  Set globals
1461    DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
1462    set dump_flags appropriately for both pass dump stream and
1463    -fopt-info stream. */
1464 
1465 int
1466 gcc::dump_manager::
dump_start(int phase,dump_flags_t * flag_ptr)1467 dump_start (int phase, dump_flags_t *flag_ptr)
1468 {
1469   int count = 0;
1470   char *name;
1471   struct dump_file_info *dfi;
1472   FILE *stream;
1473   if (phase == TDI_none || !dump_phase_enabled_p (phase))
1474     return 0;
1475 
1476   dfi = get_dump_file_info (phase);
1477   name = get_dump_file_name (phase);
1478   if (name)
1479     {
1480       stream = dump_open (name, dfi->pstate < 0);
1481       if (stream)
1482         {
1483           dfi->pstate = 1;
1484           count++;
1485         }
1486       free (name);
1487       dfi->pstream = stream;
1488       set_dump_file (dfi->pstream);
1489       /* Initialize current dump flags. */
1490       pflags = dfi->pflags;
1491     }
1492 
1493   stream = dump_open_alternate_stream (dfi);
1494   if (stream)
1495     {
1496       dfi->alt_stream = stream;
1497       count++;
1498       set_alt_dump_file (dfi->alt_stream);
1499       /* Initialize current -fopt-info flags. */
1500       alt_flags = dfi->alt_flags;
1501     }
1502 
1503   if (flag_ptr)
1504     *flag_ptr = dfi->pflags;
1505 
1506   return count;
1507 }
1508 
1509 /* Finish a tree dump for PHASE and close associated dump streams.  Also
1510    reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS.  */
1511 
1512 void
1513 gcc::dump_manager::
dump_finish(int phase)1514 dump_finish (int phase)
1515 {
1516   struct dump_file_info *dfi;
1517 
1518   if (phase < 0)
1519     return;
1520   dfi = get_dump_file_info (phase);
1521   if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
1522     fclose (dfi->pstream);
1523 
1524   if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
1525     fclose (dfi->alt_stream);
1526 
1527   dfi->alt_stream = NULL;
1528   dfi->pstream = NULL;
1529   set_dump_file (NULL);
1530   set_alt_dump_file (NULL);
1531   dump_flags = TDF_NONE;
1532   alt_flags = TDF_NONE;
1533   pflags = TDF_NONE;
1534 }
1535 
1536 /* Begin a tree dump for PHASE. Stores any user supplied flag in
1537    *FLAG_PTR and returns a stream to write to. If the dump is not
1538    enabled, returns NULL.
1539    PART can be used for dump files which should be split to multiple
1540    parts. PART == -1 indicates dump file with no parts.
1541    If PART is -1, multiple calls will reopen and append to the dump file.  */
1542 
1543 FILE *
dump_begin(int phase,dump_flags_t * flag_ptr,int part)1544 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
1545 {
1546   return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
1547 }
1548 
1549 FILE *
1550 gcc::dump_manager::
dump_begin(int phase,dump_flags_t * flag_ptr,int part)1551 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
1552 {
1553   if (phase == TDI_none || !dump_phase_enabled_p (phase))
1554     return NULL;
1555 
1556   char *name = get_dump_file_name (phase, part);
1557   if (!name)
1558     return NULL;
1559   struct dump_file_info *dfi = get_dump_file_info (phase);
1560 
1561   /* We do not support re-opening of dump files with parts.  This would require
1562      tracking pstate per part of the dump file.  */
1563   FILE *stream = dump_open (name, part != -1 || dfi->pstate < 0);
1564   if (stream)
1565     dfi->pstate = 1;
1566   free (name);
1567 
1568   if (flag_ptr)
1569     *flag_ptr = dfi->pflags;
1570 
1571   /* Initialize current flags */
1572   pflags = dfi->pflags;
1573   return stream;
1574 }
1575 
1576 /* Returns nonzero if dump PHASE is enabled for at least one stream.
1577    If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1578    any phase.  */
1579 
1580 int
1581 gcc::dump_manager::
dump_phase_enabled_p(int phase)1582 dump_phase_enabled_p (int phase) const
1583 {
1584   if (phase == TDI_tree_all)
1585     {
1586       size_t i;
1587       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1588 	if (dump_files[i].pstate || dump_files[i].alt_state)
1589 	  return 1;
1590       for (i = 0; i < m_extra_dump_files_in_use; i++)
1591 	if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
1592 	  return 1;
1593       return 0;
1594     }
1595   else
1596     {
1597       struct dump_file_info *dfi = get_dump_file_info (phase);
1598       return dfi->pstate || dfi->alt_state;
1599     }
1600 }
1601 
1602 /* Returns nonzero if tree dump PHASE has been initialized.  */
1603 
1604 int
1605 gcc::dump_manager::
dump_initialized_p(int phase)1606 dump_initialized_p (int phase) const
1607 {
1608   struct dump_file_info *dfi = get_dump_file_info (phase);
1609   return dfi->pstate > 0 || dfi->alt_state > 0;
1610 }
1611 
1612 /* Returns the switch name of PHASE.  */
1613 
1614 const char *
dump_flag_name(int phase)1615 dump_flag_name (int phase)
1616 {
1617   return g->get_dumps ()->dump_flag_name (phase);
1618 }
1619 
1620 const char *
1621 gcc::dump_manager::
dump_flag_name(int phase)1622 dump_flag_name (int phase) const
1623 {
1624   struct dump_file_info *dfi = get_dump_file_info (phase);
1625   return dfi->swtch;
1626 }
1627 
1628 /* Handle -fdump-* and -fopt-info for a pass added after
1629    command-line options are parsed (those from plugins and
1630    those from backends).
1631 
1632    Because the registration of plugin/backend passes happens after the
1633    command-line options are parsed, the options that specify single
1634    pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
1635    passes. Therefore we currently can only enable dumping of
1636    new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
1637    are specified.  This is done here.
1638 
1639    Similarly, the saved -fopt-info options are wired up to the new pass.  */
1640 
1641 void
register_pass(opt_pass * pass)1642 gcc::dump_manager::register_pass (opt_pass *pass)
1643 {
1644   gcc_assert (pass);
1645 
1646   register_one_dump_file (pass);
1647 
1648   dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number);
1649   gcc_assert (pass_dfi);
1650 
1651   enum tree_dump_index tdi;
1652   if (pass->type == SIMPLE_IPA_PASS
1653       || pass->type == IPA_PASS)
1654     tdi = TDI_ipa_all;
1655   else if (pass->type == GIMPLE_PASS)
1656     tdi = TDI_tree_all;
1657   else
1658     tdi = TDI_rtl_all;
1659   const dump_file_info *tdi_dfi = get_dump_file_info (tdi);
1660   gcc_assert (tdi_dfi);
1661 
1662   /* Check if dump-all flag is specified.  */
1663   if (tdi_dfi->pstate)
1664     {
1665       pass_dfi->pstate = tdi_dfi->pstate;
1666       pass_dfi->pflags = tdi_dfi->pflags;
1667     }
1668 
1669   update_dfi_for_opt_info (pass_dfi);
1670 }
1671 
1672 /* Finish a tree dump for PHASE. STREAM is the stream created by
1673    dump_begin.  */
1674 
1675 void
dump_end(int phase ATTRIBUTE_UNUSED,FILE * stream)1676 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
1677 {
1678   if (stream != stderr && stream != stdout)
1679     fclose (stream);
1680 }
1681 
1682 /* Enable all tree dumps with FLAGS on FILENAME.  Return number of
1683    enabled tree dumps.  */
1684 
1685 int
1686 gcc::dump_manager::
dump_enable_all(dump_kind dkind,dump_flags_t flags,const char * filename)1687 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
1688 {
1689   int n = 0;
1690   size_t i;
1691 
1692   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1693     {
1694       if (dump_files[i].dkind == dkind)
1695         {
1696           const char *old_filename = dump_files[i].pfilename;
1697           dump_files[i].pstate = -1;
1698           dump_files[i].pflags |= flags;
1699           n++;
1700           /* Override the existing filename.  */
1701           if (filename)
1702             {
1703               dump_files[i].pfilename = xstrdup (filename);
1704               /* Since it is a command-line provided file, which is
1705                  common to all the phases, use it in append mode.  */
1706               dump_files[i].pstate = 1;
1707             }
1708           if (old_filename && filename != old_filename)
1709             free (CONST_CAST (char *, old_filename));
1710         }
1711     }
1712 
1713   for (i = 0; i < m_extra_dump_files_in_use; i++)
1714     {
1715       if (m_extra_dump_files[i].dkind == dkind)
1716         {
1717           const char *old_filename = m_extra_dump_files[i].pfilename;
1718           m_extra_dump_files[i].pstate = -1;
1719           m_extra_dump_files[i].pflags |= flags;
1720           n++;
1721           /* Override the existing filename.  */
1722           if (filename)
1723             {
1724               m_extra_dump_files[i].pfilename = xstrdup (filename);
1725               /* Since it is a command-line provided file, which is
1726                  common to all the phases, use it in append mode.  */
1727               m_extra_dump_files[i].pstate = 1;
1728             }
1729           if (old_filename && filename != old_filename)
1730             free (CONST_CAST (char *, old_filename));
1731         }
1732     }
1733 
1734   return n;
1735 }
1736 
1737 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1738    Enable dumps with FLAGS on FILENAME.  Return the number of enabled
1739    dumps.  */
1740 
1741 int
1742 gcc::dump_manager::
opt_info_enable_passes(optgroup_flags_t optgroup_flags,dump_flags_t flags,const char * filename)1743 opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1744 			const char *filename)
1745 {
1746   int n = 0;
1747 
1748   m_optgroup_flags = optgroup_flags;
1749   m_optinfo_flags = flags;
1750   m_optinfo_filename = xstrdup (filename);
1751 
1752   for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++)
1753     if (update_dfi_for_opt_info (&dump_files[i]))
1754       n++;
1755 
1756   for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
1757     if (update_dfi_for_opt_info (&m_extra_dump_files[i]))
1758       n++;
1759 
1760   return n;
1761 }
1762 
1763 /* Use the saved -fopt-info options to update DFI.
1764    Return true if the dump is enabled.  */
1765 
1766 bool
update_dfi_for_opt_info(dump_file_info * dfi)1767 gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const
1768 {
1769   gcc_assert (dfi);
1770 
1771   if (!(dfi->optgroup_flags & m_optgroup_flags))
1772     return false;
1773 
1774   const char *old_filename = dfi->alt_filename;
1775   /* Since this file is shared among different passes, it
1776      should be opened in append mode.  */
1777   dfi->alt_state = 1;
1778   dfi->alt_flags |= m_optinfo_flags;
1779   /* Override the existing filename.  */
1780   if (m_optinfo_filename)
1781     dfi->alt_filename = xstrdup (m_optinfo_filename);
1782   if (old_filename && m_optinfo_filename != old_filename)
1783     free (CONST_CAST (char *, old_filename));
1784 
1785   return true;
1786 }
1787 
1788 /* Helper routine to parse -<dump format>[=filename]
1789    and return the corresponding dump flag.  If POS_P is non-NULL,
1790    assign start of filename into *POS_P.  */
1791 
1792 dump_flags_t
parse_dump_option(const char * option_value,const char ** pos_p)1793 parse_dump_option (const char *option_value, const char **pos_p)
1794 {
1795   const char *ptr;
1796   dump_flags_t flags;
1797 
1798   ptr = option_value;
1799   if (pos_p)
1800     *pos_p = NULL;
1801 
1802   /* Retain "user-facing" and "internals" messages, but filter out
1803      those from an opt_problem being re-emitted at the top level
1804      (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages
1805      messing up scan-tree-dump-times" in DejaGnu tests.  */
1806   flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_INTERNALS;
1807 
1808   while (*ptr)
1809     {
1810       const struct kv_pair<dump_flags_t> *option_ptr;
1811       const char *end_ptr;
1812       const char *eq_ptr;
1813       unsigned length;
1814       while (*ptr == '-')
1815 	ptr++;
1816       end_ptr = strchr (ptr, '-');
1817       eq_ptr = strchr (ptr, '=');
1818 
1819       if (eq_ptr && (!end_ptr || end_ptr > eq_ptr))
1820 	end_ptr = eq_ptr;
1821 
1822       if (!end_ptr)
1823 	end_ptr = ptr + strlen (ptr);
1824       length = end_ptr - ptr;
1825 
1826       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1827 	if (strlen (option_ptr->name) == length
1828 	    && !memcmp (option_ptr->name, ptr, length))
1829 	  {
1830 	    flags |= option_ptr->value;
1831 	    goto found;
1832 	  }
1833 
1834       if (*ptr == '=')
1835 	{
1836           /* Interpret rest of the argument as a dump filename.  This
1837              filename overrides other command line filenames.  */
1838 	  if (pos_p)
1839 	    *pos_p = ptr + 1;
1840 	  break;
1841 	}
1842       else
1843       {
1844 	warning (0, "ignoring unknown option %q.*s",
1845 		 length, ptr);
1846 	flags = TDF_ERROR;
1847       }
1848     found:
1849       ptr = end_ptr;
1850   }
1851 
1852   return flags;
1853 }
1854 
1855 /* Parse ARG as a dump switch.  Return nonzero if it is, and store the
1856    relevant details in the dump_files array.  */
1857 
1858 int
1859 gcc::dump_manager::
1860 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1861 {
1862   const char *option_value;
1863   dump_flags_t flags = TDF_NONE;
1864 
1865   if (doglob && !dfi->glob)
1866     return 0;
1867 
1868   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1869   if (!option_value)
1870     return 0;
1871 
1872   if (*option_value && *option_value != '-' && *option_value != '=')
1873     return 0;
1874 
1875   const char *filename;
1876   flags = parse_dump_option (option_value, &filename);
1877   if (filename)
1878     {
1879       if (dfi->pfilename)
1880   free (CONST_CAST (char *, dfi->pfilename));
1881       dfi->pfilename = xstrdup (filename);
1882     }
1883 
1884   dfi->pstate = -1;
1885   dfi->pflags |= flags;
1886 
1887   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1888      known dumps.  */
1889   if (dfi->suffix == NULL)
1890     dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
1891 
1892   return 1;
1893 }
1894 
1895 void
1896 gcc::dump_manager::
1897 dump_switch_p (const char *arg)
1898 {
1899   size_t i;
1900   int any = 0;
1901 
1902   for (i = TDI_none + 1; i != TDI_end; i++)
1903     any |= dump_switch_p_1 (arg, &dump_files[i], false);
1904 
1905   /* Don't glob if we got a hit already */
1906   if (!any)
1907     for (i = TDI_none + 1; i != TDI_end; i++)
1908       any |= dump_switch_p_1 (arg, &dump_files[i], true);
1909 
1910   for (i = 0; i < m_extra_dump_files_in_use; i++)
1911     any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
1912 
1913   if (!any)
1914     for (i = 0; i < m_extra_dump_files_in_use; i++)
1915       any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
1916 
1917   if (!any)
1918     {
1919       auto_vec<const char *> candidates;
1920       for (size_t i = TDI_none + 1; i != TDI_end; i++)
1921 	candidates.safe_push (dump_files[i].swtch);
1922       for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
1923 	candidates.safe_push (m_extra_dump_files[i].swtch);
1924       const char *hint = find_closest_string (arg, &candidates);
1925       if (hint)
1926 	error ("unrecognized command-line option %<-fdump-%s%>; "
1927 	       "did you mean %<-fdump-%s%>?", arg, hint);
1928       else
1929 	error ("unrecognized command-line option %<-fdump-%s%>", arg);
1930     }
1931 }
1932 
1933 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1934    and filename.  Return non-zero if it is a recognized switch.  */
1935 
1936 static int
1937 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
1938 		     optgroup_flags_t *optgroup_flags, char **filename)
1939 {
1940   const char *option_value;
1941   const char *ptr;
1942 
1943   option_value = arg;
1944   ptr = option_value;
1945 
1946   *filename = NULL;
1947 
1948   /* Default to filtering out "internals" messages, and retaining
1949      "user-facing" messages, and those from an opt_problem being
1950      re-emitted at the top level.  */
1951   *flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_REEMITTED;
1952 
1953   *optgroup_flags = OPTGROUP_NONE;
1954 
1955   if (!ptr)
1956     return 1;       /* Handle '-fopt-info' without any additional options.  */
1957 
1958   while (*ptr)
1959     {
1960       const char *end_ptr;
1961       const char *eq_ptr;
1962       unsigned length;
1963 
1964       while (*ptr == '-')
1965 	ptr++;
1966       end_ptr = strchr (ptr, '-');
1967       eq_ptr = strchr (ptr, '=');
1968 
1969       if (eq_ptr && (!end_ptr || eq_ptr < end_ptr))
1970         end_ptr = eq_ptr;
1971       else if (!end_ptr)
1972 	end_ptr = ptr + strlen (ptr);
1973       length = end_ptr - ptr;
1974 
1975       for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
1976 	   option_ptr->name; option_ptr++)
1977 	if (strlen (option_ptr->name) == length
1978 	    && !memcmp (option_ptr->name, ptr, length))
1979           {
1980             *flags |= option_ptr->value;
1981 	    goto found;
1982           }
1983 
1984       for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
1985 	   option_ptr->name; option_ptr++)
1986 	if (strlen (option_ptr->name) == length
1987 	    && !memcmp (option_ptr->name, ptr, length))
1988           {
1989             *optgroup_flags |= option_ptr->value;
1990 	    goto found;
1991           }
1992 
1993       if (*ptr == '=')
1994         {
1995           /* Interpret rest of the argument as a dump filename.  This
1996              filename overrides other command line filenames.  */
1997           *filename = xstrdup (ptr + 1);
1998           break;
1999         }
2000       else
2001         {
2002           warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
2003                    length, ptr, arg);
2004           return 0;
2005         }
2006     found:;
2007       ptr = end_ptr;
2008     }
2009 
2010   return 1;
2011 }
2012 
2013 /* Return non-zero if ARG is a recognized switch for
2014    -fopt-info. Return zero otherwise.  */
2015 
2016 int
2017 opt_info_switch_p (const char *arg)
2018 {
2019   dump_flags_t flags;
2020   optgroup_flags_t optgroup_flags;
2021   char *filename;
2022   static char *file_seen = NULL;
2023   gcc::dump_manager *dumps = g->get_dumps ();
2024 
2025   if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
2026     return 0;
2027 
2028   if (!filename)
2029     filename = xstrdup ("stderr");
2030 
2031   /* Bail out if a different filename has been specified.  */
2032   if (file_seen && strcmp (file_seen, filename))
2033     {
2034       warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
2035                arg);
2036       return 1;
2037     }
2038 
2039   file_seen = xstrdup (filename);
2040   if (!(flags & MSG_ALL_KINDS))
2041     flags |= MSG_OPTIMIZED_LOCATIONS;
2042   if (!optgroup_flags)
2043     optgroup_flags = OPTGROUP_ALL;
2044 
2045   return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
2046 }
2047 
2048 /* Print basic block on the dump streams.  */
2049 
2050 void
2051 dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
2052 {
2053   if (dump_file
2054       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
2055     dump_bb (dump_file, bb, indent, TDF_DETAILS);
2056   if (alt_dump_file
2057       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
2058     dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
2059 }
2060 
2061 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
2062 
2063 void
2064 dump_function (int phase, tree fn)
2065 {
2066   FILE *stream;
2067   dump_flags_t flags;
2068 
2069   stream = dump_begin (phase, &flags);
2070   if (stream)
2071     {
2072       dump_function_to_file (fn, stream, flags);
2073       dump_end (phase, stream);
2074     }
2075 }
2076 
2077 /* Print information from the combine pass on dump_file.  */
2078 
2079 void
2080 print_combine_total_stats (void)
2081 {
2082   if (dump_file)
2083     dump_combine_total_stats (dump_file);
2084 }
2085 
2086 /* Enable RTL dump for all the RTL passes.  */
2087 
2088 bool
2089 enable_rtl_dump_file (void)
2090 {
2091   gcc::dump_manager *dumps = g->get_dumps ();
2092   int num_enabled =
2093     dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
2094 			    NULL);
2095   return num_enabled > 0;
2096 }
2097 
2098 /* debug_dump_context's ctor.  Temporarily override the dump_context
2099    (to forcibly enable output to stderr).  */
2100 
2101 debug_dump_context::debug_dump_context ()
2102 : m_context (),
2103   m_saved (&dump_context::get ()),
2104   m_saved_flags (dump_flags),
2105   m_saved_pflags (pflags),
2106   m_saved_file (dump_file)
2107 {
2108   set_dump_file (stderr);
2109   dump_context::s_current = &m_context;
2110   pflags = dump_flags = MSG_ALL_KINDS | MSG_ALL_PRIORITIES;
2111   dump_context::get ().refresh_dumps_are_enabled ();
2112 }
2113 
2114 /* debug_dump_context's dtor.  Restore the saved dump_context.  */
2115 
2116 debug_dump_context::~debug_dump_context ()
2117 {
2118   set_dump_file (m_saved_file);
2119   dump_context::s_current = m_saved;
2120   dump_flags = m_saved_flags;
2121   pflags = m_saved_pflags;
2122   dump_context::get ().refresh_dumps_are_enabled ();
2123 }
2124 
2125 
2126 #if CHECKING_P
2127 
2128 namespace selftest {
2129 
2130 /* temp_dump_context's ctor.  Temporarily override the dump_context
2131    (to forcibly enable optinfo-generation).  */
2132 
2133 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
2134 				      bool forcibly_enable_dumping,
2135 				      dump_flags_t test_pp_flags)
2136 : m_context (),
2137   m_saved (&dump_context::get ())
2138 {
2139   dump_context::s_current = &m_context;
2140   if (forcibly_enable_optinfo)
2141     m_context.set_json_writer (new optrecord_json_writer ());
2142   /* Conditionally enable the test dump, so that we can verify both the
2143      dump_enabled_p and the !dump_enabled_p cases in selftests.  */
2144   if (forcibly_enable_dumping)
2145     {
2146       m_context.m_test_pp = &m_pp;
2147       m_context.m_test_pp_flags = test_pp_flags;
2148     }
2149 
2150   dump_context::get ().refresh_dumps_are_enabled ();
2151 }
2152 
2153 /* temp_dump_context's dtor.  Restore the saved dump_context.  */
2154 
2155 temp_dump_context::~temp_dump_context ()
2156 {
2157   m_context.set_json_writer (NULL);
2158 
2159   dump_context::s_current = m_saved;
2160 
2161   dump_context::get ().refresh_dumps_are_enabled ();
2162 }
2163 
2164 /* 0-terminate the text dumped so far, and return it.  */
2165 
2166 const char *
2167 temp_dump_context::get_dumped_text ()
2168 {
2169   return pp_formatted_text (&m_pp);
2170 }
2171 
2172 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2173    from EXPECTED_FUNCTION, using LOC for the location of any failure,
2174    provided that the build compiler is sufficiently recent.  */
2175 
2176 static void
2177 assert_impl_location_eq (const location &loc ATTRIBUTE_UNUSED,
2178 			 const dump_impl_location_t &impl_loc ATTRIBUTE_UNUSED,
2179 			 const char *expected_file ATTRIBUTE_UNUSED,
2180 			 int expected_line ATTRIBUTE_UNUSED,
2181 			 const char *expected_function ATTRIBUTE_UNUSED)
2182 {
2183 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
2184   ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_file, expected_file);
2185   ASSERT_EQ_AT (loc, impl_loc.m_line, expected_line);
2186   ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_function, expected_function);
2187 #endif
2188 }
2189 
2190 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2191    from EXPECTED_FUNCTION, provided that the build compiler is
2192    sufficiently recent.  */
2193 
2194 #define ASSERT_IMPL_LOCATION_EQ(IMPL_LOC, EXPECTED_FILE, EXPECTED_LINE, \
2195 				EXPECTED_FUNCTION)			\
2196   SELFTEST_BEGIN_STMT							\
2197     assert_impl_location_eq (SELFTEST_LOCATION, IMPL_LOC,		\
2198 			     EXPECTED_FILE, EXPECTED_LINE,		\
2199 			     EXPECTED_FUNCTION);			\
2200   SELFTEST_END_STMT
2201 
2202 /* Verify that the dump_location_t constructors capture the source location
2203    at which they were called (provided that the build compiler is sufficiently
2204    recent).  */
2205 
2206 static void
2207 test_impl_location ()
2208 {
2209   /* Default ctor.  */
2210   {
2211     dump_location_t loc;
2212     const int expected_line = __LINE__ - 1;
2213     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2214 			     "dumpfile.c", expected_line, "test_impl_location");
2215   }
2216 
2217   /* Constructing from a gimple.  */
2218   {
2219     dump_location_t loc ((gimple *)NULL);
2220     const int expected_line = __LINE__ - 1;
2221     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2222 			     "dumpfile.c", expected_line, "test_impl_location");
2223   }
2224 
2225   /* Constructing from an rtx_insn.  */
2226   {
2227     dump_location_t loc ((rtx_insn *)NULL);
2228     const int expected_line = __LINE__ - 1;
2229     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2230 			     "dumpfile.c", expected_line, "test_impl_location");
2231   }
2232 }
2233 
2234 /* Verify that the text dumped so far in CONTEXT equals
2235    EXPECTED_TEXT, using LOC for the location of any failure.
2236    As a side-effect, the internal buffer is 0-terminated.  */
2237 
2238 void
2239 verify_dumped_text (const location &loc,
2240 		    temp_dump_context *context,
2241 		    const char *expected_text)
2242 {
2243   gcc_assert (context);
2244   ASSERT_STREQ_AT (loc, context->get_dumped_text (),
2245 		   expected_text);
2246 }
2247 
2248 /* Verify that ITEM has the expected values.  */
2249 
2250 void
2251 verify_item (const location &loc,
2252 	     const optinfo_item *item,
2253 	     enum optinfo_item_kind expected_kind,
2254 	     location_t expected_location,
2255 	     const char *expected_text)
2256 {
2257   ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
2258   ASSERT_EQ_AT (loc, item->get_location (), expected_location);
2259   ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
2260 }
2261 
2262 /* Verify that calls to the dump_* API are captured and consolidated into
2263    optimization records. */
2264 
2265 static void
2266 test_capture_of_dump_calls (const line_table_case &case_)
2267 {
2268   /* Generate a location_t for testing.  */
2269   line_table_test ltt (case_);
2270   linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
2271   linemap_line_start (line_table, 5, 100);
2272   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2273   location_t decl_loc = linemap_position_for_column (line_table, 8);
2274   location_t stmt_loc = linemap_position_for_column (line_table, 10);
2275   if (stmt_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
2276     return;
2277 
2278   dump_user_location_t loc = dump_user_location_t::from_location_t (stmt_loc);
2279 
2280   gimple *stmt = gimple_build_return (NULL);
2281   gimple_set_location (stmt, stmt_loc);
2282 
2283   tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
2284 			       get_identifier ("test_decl"),
2285 			       build_function_type_list (void_type_node,
2286 							 NULL_TREE));
2287 
2288   symbol_table_test tmp_symtab;
2289 
2290   cgraph_node *node = cgraph_node::get_create (test_decl);
2291   gcc_assert (node);
2292 
2293   /* Run all tests twice, with and then without optinfo enabled, to ensure
2294      that immediate destinations vs optinfo-based destinations both
2295      work, independently of each other, with no leaks.  */
2296   for (int i = 0 ; i < 2; i++)
2297     {
2298       bool with_optinfo = (i == 0);
2299 
2300       /* Test of dump_printf.  */
2301       {
2302 	temp_dump_context tmp (with_optinfo, true,
2303 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2304 	dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
2305 	const int expected_impl_line = __LINE__ - 1;
2306 
2307 	ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
2308 	if (with_optinfo)
2309 	  {
2310 	    optinfo *info = tmp.get_pending_optinfo ();
2311 	    ASSERT_TRUE (info != NULL);
2312 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2313 	    ASSERT_EQ (info->num_items (), 1);
2314 	    ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
2315 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2316 				     "dumpfile.c", expected_impl_line,
2317 				     "test_capture_of_dump_calls");
2318 	  }
2319       }
2320 
2321       /* Test of dump_printf with %T.  */
2322       {
2323 	temp_dump_context tmp (with_optinfo, true,
2324 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2325 	dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
2326 	const int expected_impl_line = __LINE__ - 1;
2327 
2328 	ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
2329 	if (with_optinfo)
2330 	  {
2331 	    optinfo *info = tmp.get_pending_optinfo ();
2332 	    ASSERT_TRUE (info != NULL);
2333 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2334 	    ASSERT_EQ (info->num_items (), 2);
2335 	    ASSERT_IS_TEXT (info->get_item (0), "tree: ");
2336 	    ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2337 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2338 				     "dumpfile.c", expected_impl_line,
2339 				     "test_capture_of_dump_calls");
2340 	  }
2341       }
2342 
2343       /* Test of dump_printf with %E.  */
2344       {
2345 	temp_dump_context tmp (with_optinfo, true,
2346 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2347 	dump_printf (MSG_NOTE, "gimple: %E", stmt);
2348 	const int expected_impl_line = __LINE__ - 1;
2349 
2350 	ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
2351 	if (with_optinfo)
2352 	  {
2353 	    optinfo *info = tmp.get_pending_optinfo ();
2354 	    ASSERT_TRUE (info != NULL);
2355 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2356 	    ASSERT_EQ (info->num_items (), 2);
2357 	    ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
2358 	    ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
2359 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2360 				     "dumpfile.c", expected_impl_line,
2361 				     "test_capture_of_dump_calls");
2362 	  }
2363       }
2364 
2365       /* Test of dump_printf with %G.  */
2366       {
2367 	temp_dump_context tmp (with_optinfo, true,
2368 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2369 	dump_printf (MSG_NOTE, "gimple: %G", stmt);
2370 	const int expected_impl_line = __LINE__ - 1;
2371 
2372 	ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
2373 	if (with_optinfo)
2374 	  {
2375 	    optinfo *info = tmp.get_pending_optinfo ();
2376 	    ASSERT_TRUE (info != NULL);
2377 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2378 	    ASSERT_EQ (info->num_items (), 2);
2379 	    ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
2380 	    ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
2381 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2382 				     "dumpfile.c", expected_impl_line,
2383 				     "test_capture_of_dump_calls");
2384 	  }
2385       }
2386 
2387       /* Test of dump_printf with %C.  */
2388       {
2389 	temp_dump_context tmp (with_optinfo, true,
2390 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2391 	dump_printf (MSG_NOTE, "node: %C", node);
2392 	const int expected_impl_line = __LINE__ - 1;
2393 
2394 	ASSERT_DUMPED_TEXT_EQ (tmp, "node: test_decl/0");
2395 	if (with_optinfo)
2396 	  {
2397 	    optinfo *info = tmp.get_pending_optinfo ();
2398 	    ASSERT_TRUE (info != NULL);
2399 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2400 	    ASSERT_EQ (info->num_items (), 2);
2401 	    ASSERT_IS_TEXT (info->get_item (0), "node: ");
2402 	    ASSERT_IS_SYMTAB_NODE (info->get_item (1), decl_loc, "test_decl/0");
2403 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2404 				     "dumpfile.c", expected_impl_line,
2405 				     "test_capture_of_dump_calls");
2406 	  }
2407       }
2408 
2409       /* dump_print_loc with multiple format codes.  This tests various
2410 	 things:
2411 	 - intermingling of text, format codes handled by the base
2412 	 pretty_printer, and dump-specific format codes
2413 	 - multiple dump-specific format codes: some consecutive, others
2414 	 separated by text, trailing text after the final one.  */
2415       {
2416 	temp_dump_context tmp (with_optinfo, true,
2417 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2418 	dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
2419 			 " %i consecutive %E%E after\n",
2420 			 integer_zero_node, test_decl, 42, stmt, stmt);
2421 
2422 	ASSERT_DUMPED_TEXT_EQ (tmp,
2423 			       "test.txt:5:10: note: before 0 and test_decl"
2424 			       " 42 consecutive return;return; after\n");
2425 	if (with_optinfo)
2426 	  {
2427 	    optinfo *info = tmp.get_pending_optinfo ();
2428 	    ASSERT_TRUE (info != NULL);
2429 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2430 	    ASSERT_EQ (info->num_items (), 8);
2431 	    ASSERT_IS_TEXT (info->get_item (0), "before ");
2432 	    ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2433 	    ASSERT_IS_TEXT (info->get_item (2), " and ");
2434 	    ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
2435 	    ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
2436 	    ASSERT_IS_GIMPLE (info->get_item (5), stmt_loc, "return;");
2437 	    ASSERT_IS_GIMPLE (info->get_item (6), stmt_loc, "return;");
2438 	    ASSERT_IS_TEXT (info->get_item (7), " after\n");
2439 	    /* We don't ASSERT_IMPL_LOCATION_EQ here, to avoid having to
2440 	       enforce at which exact line the multiline dump_printf_loc
2441 	       occurred.  */
2442 	  }
2443       }
2444 
2445       /* Tree, via dump_generic_expr.  */
2446       {
2447 	temp_dump_context tmp (with_optinfo, true,
2448 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2449 	dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
2450 	const int expected_impl_line = __LINE__ - 1;
2451 	dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
2452 
2453 	ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
2454 	if (with_optinfo)
2455 	  {
2456 	    optinfo *info = tmp.get_pending_optinfo ();
2457 	    ASSERT_TRUE (info != NULL);
2458 	    ASSERT_EQ (info->get_location_t (), stmt_loc);
2459 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2460 	    ASSERT_EQ (info->num_items (), 2);
2461 	    ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
2462 	    ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
2463 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2464 				     "dumpfile.c", expected_impl_line,
2465 				     "test_capture_of_dump_calls");
2466 	  }
2467       }
2468 
2469       /* Tree, via dump_generic_expr_loc.  */
2470       {
2471 	temp_dump_context tmp (with_optinfo, true,
2472 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2473 	dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
2474 	const int expected_impl_line = __LINE__ - 1;
2475 
2476 	ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
2477 	if (with_optinfo)
2478 	  {
2479 	    optinfo *info = tmp.get_pending_optinfo ();
2480 	    ASSERT_TRUE (info != NULL);
2481 	    ASSERT_EQ (info->get_location_t (), stmt_loc);
2482 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2483 	    ASSERT_EQ (info->num_items (), 1);
2484 	    ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
2485 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2486 				     "dumpfile.c", expected_impl_line,
2487 				     "test_capture_of_dump_calls");
2488 	  }
2489       }
2490 
2491       /* Gimple.  */
2492       {
2493 	/* dump_gimple_stmt_loc.  */
2494 	{
2495 	  temp_dump_context tmp (with_optinfo, true,
2496 				 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2497 	  dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
2498 	  const int expected_impl_line = __LINE__ - 1;
2499 
2500 	  ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
2501 	  if (with_optinfo)
2502 	    {
2503 	      optinfo *info = tmp.get_pending_optinfo ();
2504 	      ASSERT_TRUE (info != NULL);
2505 	      ASSERT_EQ (info->num_items (), 1);
2506 	      ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
2507 	      ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2508 				       "dumpfile.c", expected_impl_line,
2509 				       "test_capture_of_dump_calls");
2510 	    }
2511 	}
2512 
2513 	/* dump_gimple_stmt.  */
2514 	{
2515 	  temp_dump_context tmp (with_optinfo, true,
2516 				 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2517 	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
2518 	  const int expected_impl_line = __LINE__ - 1;
2519 
2520 	  ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
2521 	  if (with_optinfo)
2522 	    {
2523 	      optinfo *info = tmp.get_pending_optinfo ();
2524 	      ASSERT_TRUE (info != NULL);
2525 	      ASSERT_EQ (info->num_items (), 1);
2526 	      ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
2527 	      ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2528 				       "dumpfile.c", expected_impl_line,
2529 				       "test_capture_of_dump_calls");
2530 	    }
2531 	}
2532 
2533 	/* dump_gimple_expr_loc.  */
2534 	{
2535 	  temp_dump_context tmp (with_optinfo, true,
2536 				 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2537 	  dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
2538 	  const int expected_impl_line = __LINE__ - 1;
2539 
2540 	  ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
2541 	  if (with_optinfo)
2542 	    {
2543 	      optinfo *info = tmp.get_pending_optinfo ();
2544 	      ASSERT_TRUE (info != NULL);
2545 	      ASSERT_EQ (info->num_items (), 1);
2546 	      ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
2547 	      ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2548 				       "dumpfile.c", expected_impl_line,
2549 				       "test_capture_of_dump_calls");
2550 	    }
2551 	}
2552 
2553 	/* dump_gimple_expr.  */
2554 	{
2555 	  temp_dump_context tmp (with_optinfo, true,
2556 				 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2557 	  dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
2558 	  const int expected_impl_line = __LINE__ - 1;
2559 
2560 	  ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
2561 	  if (with_optinfo)
2562 	    {
2563 	      optinfo *info = tmp.get_pending_optinfo ();
2564 	      ASSERT_TRUE (info != NULL);
2565 	      ASSERT_EQ (info->num_items (), 1);
2566 	      ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
2567 	      ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2568 				       "dumpfile.c", expected_impl_line,
2569 				       "test_capture_of_dump_calls");
2570 	    }
2571 	}
2572       }
2573 
2574       /* symtab_node.  */
2575       {
2576 	temp_dump_context tmp (with_optinfo, true,
2577 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2578 	dump_symtab_node (MSG_NOTE, node);
2579 	const int expected_impl_line = __LINE__ - 1;
2580 
2581 	ASSERT_DUMPED_TEXT_EQ (tmp, "test_decl/0");
2582 	if (with_optinfo)
2583 	  {
2584 	    optinfo *info = tmp.get_pending_optinfo ();
2585 	    ASSERT_TRUE (info != NULL);
2586 	    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
2587 	    ASSERT_EQ (info->num_items (), 1);
2588 	    ASSERT_IS_SYMTAB_NODE (info->get_item (0), decl_loc, "test_decl/0");
2589 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2590 				     "dumpfile.c", expected_impl_line,
2591 				     "test_capture_of_dump_calls");
2592 	  }
2593       }
2594 
2595       /* poly_int.  */
2596       {
2597 	temp_dump_context tmp (with_optinfo, true,
2598 			       MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2599 	dump_dec (MSG_NOTE, poly_int64 (42));
2600 	const int expected_impl_line = __LINE__ - 1;
2601 
2602 	ASSERT_DUMPED_TEXT_EQ (tmp, "42");
2603 	if (with_optinfo)
2604 	  {
2605 	    optinfo *info = tmp.get_pending_optinfo ();
2606 	    ASSERT_TRUE (info != NULL);
2607 	    ASSERT_EQ (info->num_items (), 1);
2608 	    ASSERT_IS_TEXT (info->get_item (0), "42");
2609 	    ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2610 				     "dumpfile.c", expected_impl_line,
2611 				     "test_capture_of_dump_calls");
2612 	  }
2613       }
2614 
2615       /* Scopes.  Test with all 4 combinations of
2616 	 filtering by MSG_PRIORITY_USER_FACING
2617 	 and/or filtering by MSG_PRIORITY_INTERNALS.  */
2618       for (int j = 0; j < 3; j++)
2619 	{
2620 	  dump_flags_t dump_filter = MSG_ALL_KINDS;
2621 	  if (j % 2)
2622 	    dump_filter |= MSG_PRIORITY_USER_FACING;
2623 	  if (j / 2)
2624 	    dump_filter |= MSG_PRIORITY_INTERNALS;
2625 
2626 	  temp_dump_context tmp (with_optinfo, true, dump_filter);
2627 	  /* Emit various messages, mostly with implicit priority.  */
2628 	  dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
2629 	  dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt,
2630 			   "explicitly internal msg\n");
2631 	  {
2632 	    AUTO_DUMP_SCOPE ("outer scope", stmt);
2633 	    dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
2634 	    {
2635 	      AUTO_DUMP_SCOPE ("middle scope", stmt);
2636 	      dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
2637 	      {
2638 		AUTO_DUMP_SCOPE ("inner scope", stmt);
2639 		dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
2640 		dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt,
2641 				 "explicitly user-facing msg\n");
2642 	      }
2643 	      dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
2644 	    }
2645 	    dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
2646 	  }
2647 	  dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
2648 	  const int expected_impl_line = __LINE__ - 1;
2649 
2650 	  switch (dump_filter & MSG_ALL_PRIORITIES)
2651 	    {
2652 	    default:
2653 	      gcc_unreachable ();
2654 	    case 0:
2655 	      ASSERT_DUMPED_TEXT_EQ (tmp, "");
2656 	      break;
2657 	    case MSG_PRIORITY_USER_FACING:
2658 	      ASSERT_DUMPED_TEXT_EQ
2659 		(tmp,
2660 		 "test.txt:5:10: note: msg 1\n"
2661 		 "test.txt:5:10: note:    explicitly user-facing msg\n"
2662 		 "test.txt:5:10: note: msg 7\n");
2663 	      break;
2664 	    case MSG_PRIORITY_INTERNALS:
2665 	      ASSERT_DUMPED_TEXT_EQ
2666 		(tmp,
2667 		 "test.txt:5:10: note: explicitly internal msg\n"
2668 		 "test.txt:5:10: note:  === outer scope ===\n"
2669 		 "test.txt:5:10: note:  msg 2\n"
2670 		 "test.txt:5:10: note:   === middle scope ===\n"
2671 		 "test.txt:5:10: note:   msg 3\n"
2672 		 "test.txt:5:10: note:    === inner scope ===\n"
2673 		 "test.txt:5:10: note:    msg 4\n"
2674 		 "test.txt:5:10: note:   msg 5\n"
2675 		 "test.txt:5:10: note:  msg 6\n");
2676 	      break;
2677 	    case MSG_ALL_PRIORITIES:
2678 	      ASSERT_DUMPED_TEXT_EQ
2679 		(tmp,
2680 		 "test.txt:5:10: note: msg 1\n"
2681 		 "test.txt:5:10: note: explicitly internal msg\n"
2682 		 "test.txt:5:10: note: === outer scope ===\n"
2683 		 "test.txt:5:10: note:  msg 2\n"
2684 		 "test.txt:5:10: note:  === middle scope ===\n"
2685 		 "test.txt:5:10: note:   msg 3\n"
2686 		 "test.txt:5:10: note:   === inner scope ===\n"
2687 		 "test.txt:5:10: note:    msg 4\n"
2688 		 "test.txt:5:10: note:    explicitly user-facing msg\n"
2689 		 "test.txt:5:10: note:   msg 5\n"
2690 		 "test.txt:5:10: note:  msg 6\n"
2691 		 "test.txt:5:10: note: msg 7\n");
2692 	      break;
2693 	    }
2694 	  if (with_optinfo)
2695 	    {
2696 	      optinfo *info = tmp.get_pending_optinfo ();
2697 	      ASSERT_TRUE (info != NULL);
2698 	      ASSERT_EQ (info->num_items (), 1);
2699 	      ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
2700 	      ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2701 				       "dumpfile.c", expected_impl_line,
2702 				       "test_capture_of_dump_calls");
2703 	    }
2704 	}
2705     }
2706 
2707   /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
2708      above.  */
2709   {
2710     /* MSG_OPTIMIZED_LOCATIONS.  */
2711     {
2712       temp_dump_context tmp (true, true, MSG_ALL_KINDS);
2713       dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
2714       ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
2715 		 OPTINFO_KIND_SUCCESS);
2716     }
2717 
2718     /* MSG_MISSED_OPTIMIZATION.  */
2719     {
2720       temp_dump_context tmp (true, true, MSG_ALL_KINDS);
2721       dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
2722       ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
2723 		 OPTINFO_KIND_FAILURE);
2724     }
2725   }
2726 
2727   /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls.  */
2728   {
2729     temp_dump_context tmp (false, true,
2730 			   MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
2731     dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
2732     {
2733       AUTO_DUMP_SCOPE ("outer scope", stmt);
2734       dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
2735       {
2736 	AUTO_DUMP_SCOPE ("middle scope", stmt);
2737 	dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
2738 	{
2739 	  AUTO_DUMP_SCOPE ("inner scope", stmt);
2740 	  dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
2741 	}
2742 	dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
2743       }
2744       dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
2745     }
2746     dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
2747 
2748     ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized:    msg 4\n");
2749   }
2750 }
2751 
2752 static void
2753 test_pr87025 ()
2754 {
2755   dump_user_location_t loc
2756     = dump_user_location_t::from_location_t (UNKNOWN_LOCATION);
2757 
2758   temp_dump_context tmp (true, true,
2759 			 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
2760   {
2761     AUTO_DUMP_SCOPE ("outer scope", loc);
2762     dump_printf (MSG_NOTE, "msg1\n");
2763   }
2764 }
2765 
2766 /* Run all of the selftests within this file.  */
2767 
2768 void
2769 dumpfile_c_tests ()
2770 {
2771   test_impl_location ();
2772   for_each_line_table_case (test_capture_of_dump_calls);
2773   test_pr87025 ();
2774 }
2775 
2776 } // namespace selftest
2777 
2778 #endif /* CHECKING_P */
2779