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