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