]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dumpfile.c
[Ada] Remove Determine_License
[thirdparty/gcc.git] / gcc / dumpfile.c
CommitLineData
b5f47924 1/* Dump infrastructure for optimizations and intermediate representation.
8d9254fc 2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
b5f47924
SS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
957060b5
AM
23#include "options.h"
24#include "tree.h"
25#include "gimple-pretty-print.h"
b5f47924
SS
26#include "diagnostic-core.h"
27#include "dumpfile.h"
47e0da37 28#include "context.h"
0de11d4d 29#include "profile-count.h"
c24e924f 30#include "tree-cfg.h"
363dc72c 31#include "langhooks.h"
4f5b9c80
DM
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"
4df3629e
DM
36#include "optinfo.h"
37#include "dump-context.h"
38#include "cgraph.h"
39#include "tree-pass.h" /* for "current_pass". */
4a4412b9 40#include "optinfo-emit-json.h"
6f795a92 41#include "stringpool.h" /* for get_identifier. */
48c04103 42#include "spellcheck.h"
b5f47924
SS
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
1a817418 49static dump_flags_t pflags; /* current dump_flags */
b5f47924 50
620e594b 51static void dump_loc (dump_flags_t, FILE *, location_t);
29b54a9d
DM
52
53/* Current -fopt-info output stream, if any, and flags. */
54static FILE *alt_dump_file = NULL;
55static dump_flags_t alt_flags;
56
b5f47924
SS
57static FILE *dump_open_alternate_stream (struct dump_file_info *);
58
73fbfcad
SS
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. */
62FILE *dump_file = NULL;
73fbfcad 63const char *dump_file_name;
1a817418 64dump_flags_t dump_flags;
29b54a9d
DM
65bool dumps_are_enabled = false;
66
67
29b54a9d
DM
68/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
69 global. */
70
71void
72set_dump_file (FILE *new_dump_file)
73{
4df3629e 74 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d 75 dump_file = new_dump_file;
b84e3bde 76 dump_context::get ().refresh_dumps_are_enabled ();
29b54a9d
DM
77}
78
79/* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
80 global. */
81
82static void
83set_alt_dump_file (FILE *new_alt_dump_file)
84{
4df3629e 85 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d 86 alt_dump_file = new_alt_dump_file;
b84e3bde 87 dump_context::get ().refresh_dumps_are_enabled ();
29b54a9d 88}
73fbfcad 89
63523736 90#define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
4af78ef8
DM
91 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
92 OPTGROUP_NONE, 0, 0, num, false, false}
8264c84d 93
b5f47924
SS
94/* Table of tree dump switches. This must be consistent with the
95 TREE_DUMP_INDEX enumeration in dumpfile.h. */
96static struct dump_file_info dump_files[TDI_end] =
97{
63523736
ML
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),
363dc72c
JJ
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),
b4da704c 105 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
363dc72c 106#define FIRST_AUTO_NUMBERED_DUMP 1
29a50dfb 107#define FIRST_ME_AUTO_NUMBERED_DUMP 4
b5f47924 108
63523736
ML
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),
b5f47924
SS
113};
114
b5f47924
SS
115/* Table of dump options. This must be consistent with the TDF_* flags
116 in dumpfile.h and opt_info_options below. */
4af78ef8 117static const kv_pair<dump_flags_t> dump_options[] =
b5f47924 118{
66d62d9f 119 {"none", TDF_NONE},
b5f47924
SS
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},
b5f47924
SS
136 {"eh", TDF_EH},
137 {"alias", TDF_ALIAS},
138 {"nouid", TDF_NOUID},
139 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
140 {"scev", TDF_SCEV},
1ee62b92 141 {"gimple", TDF_GIMPLE},
56af751e 142 {"folding", TDF_FOLDING},
f14726bd
TJ
143 {"optimized", MSG_OPTIMIZED_LOCATIONS},
144 {"missed", MSG_MISSED_OPTIMIZATION},
145 {"note", MSG_NOTE},
7db960c5 146 {"optall", MSG_ALL_KINDS},
de6c8d7f
ML
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))},
4af78ef8 151 {NULL, TDF_NONE}
b5f47924
SS
152};
153
2b4e6bf1
SS
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.
b5f47924 156 */
4af78ef8 157static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
b5f47924
SS
158{
159 {"optimized", MSG_OPTIMIZED_LOCATIONS},
160 {"missed", MSG_MISSED_OPTIMIZATION},
161 {"note", MSG_NOTE},
7db960c5
DM
162 {"all", MSG_ALL_KINDS},
163 {"internals", MSG_PRIORITY_INTERNALS},
4af78ef8 164 {NULL, TDF_NONE}
2b4e6bf1
SS
165};
166
167/* Flags used for -fopt-info groups. */
4a4412b9 168const kv_pair<optgroup_flags_t> optgroup_options[] =
2b4e6bf1
SS
169{
170 {"ipa", OPTGROUP_IPA},
171 {"loop", OPTGROUP_LOOP},
172 {"inline", OPTGROUP_INLINE},
fd2b8c8b 173 {"omp", OPTGROUP_OMP},
2b4e6bf1
SS
174 {"vec", OPTGROUP_VEC},
175 {"optall", OPTGROUP_ALL},
4af78ef8 176 {NULL, OPTGROUP_NONE}
b5f47924
SS
177};
178
47e0da37
DM
179gcc::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),
5d98e5a6
DM
183 m_extra_dump_files_alloced (0),
184 m_optgroup_flags (OPTGROUP_NONE),
185 m_optinfo_flags (TDF_NONE),
186 m_optinfo_filename (NULL)
47e0da37
DM
187{
188}
189
10fdd6e9
DM
190gcc::dump_manager::~dump_manager ()
191{
5d98e5a6 192 free (m_optinfo_filename);
10fdd6e9
DM
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
b5f47924 212unsigned int
47e0da37 213gcc::dump_manager::
b5f47924 214dump_register (const char *suffix, const char *swtch, const char *glob,
4af78ef8
DM
215 dump_kind dkind, optgroup_flags_t optgroup_flags,
216 bool take_ownership)
b5f47924 217{
47e0da37 218 int num = m_next_dump++;
b5f47924 219
47e0da37 220 size_t count = m_extra_dump_files_in_use++;
b5f47924 221
47e0da37 222 if (count >= m_extra_dump_files_alloced)
b5f47924 223 {
47e0da37 224 if (m_extra_dump_files_alloced == 0)
363dc72c 225 m_extra_dump_files_alloced = 512;
b5f47924 226 else
47e0da37
DM
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);
c3684b7b
MS
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 ();
b5f47924
SS
239 }
240
47e0da37
DM
241 m_extra_dump_files[count].suffix = suffix;
242 m_extra_dump_files[count].swtch = swtch;
243 m_extra_dump_files[count].glob = glob;
8264c84d 244 m_extra_dump_files[count].dkind = dkind;
47e0da37
DM
245 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
246 m_extra_dump_files[count].num = num;
10fdd6e9 247 m_extra_dump_files[count].owns_strings = take_ownership;
b5f47924
SS
248
249 return count + TDI_end;
250}
251
252
363dc72c
JJ
253/* Allow languages and middle-end to register their dumps before the
254 optimization passes. */
255
256void
257gcc::dump_manager::
258register_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
b5f47924
SS
272/* Return the dump_file_info for the given phase. */
273
274struct dump_file_info *
47e0da37
DM
275gcc::dump_manager::
276get_dump_file_info (int phase) const
b5f47924
SS
277{
278 if (phase < TDI_end)
279 return &dump_files[phase];
47e0da37 280 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
b5f47924
SS
281 return NULL;
282 else
47e0da37 283 return m_extra_dump_files + (phase - TDI_end);
b5f47924
SS
284}
285
799505ae
DM
286/* Locate the dump_file_info with swtch equal to SWTCH,
287 or return NULL if no such dump_file_info exists. */
288
289struct dump_file_info *
290gcc::dump_manager::
291get_dump_file_info_by_switch (const char *swtch) const
292{
293 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
01512446 294 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
799505ae
DM
295 return &m_extra_dump_files[i];
296
297 /* Not found. */
298 return NULL;
299}
300
b5f47924
SS
301
302/* Return the name of the dump file for the given phase.
799505ae
DM
303 The caller is responsible for calling free on the returned
304 buffer.
b5f47924
SS
305 If the dump is not enabled, returns NULL. */
306
307char *
47e0da37 308gcc::dump_manager::
75fdb07e 309get_dump_file_name (int phase, int part) const
b5f47924 310{
b5f47924
SS
311 struct dump_file_info *dfi;
312
313 if (phase == TDI_none)
314 return NULL;
315
316 dfi = get_dump_file_info (phase);
799505ae 317
75fdb07e 318 return get_dump_file_name (dfi, part);
799505ae
DM
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
326char *
327gcc::dump_manager::
75fdb07e 328get_dump_file_name (struct dump_file_info *dfi, int part) const
799505ae
DM
329{
330 char dump_id[10];
331
332 gcc_assert (dfi);
333
b5f47924
SS
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 {
8264c84d
ML
345 /* (null), LANG, TREE, RTL, IPA. */
346 char suffix = " ltri"[dfi->dkind];
a529e0a6 347
8264c84d 348 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
b5f47924
SS
349 dump_id[0] = '\0';
350 }
351
75fdb07e
JH
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);
b5f47924
SS
360}
361
5d8b352a
NS
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
367static FILE *
368dump_open (const char *filename, bool trunc)
369{
370 if (strcmp ("stderr", filename) == 0)
371 return stderr;
372
bd9918c4
NS
373 if (strcmp ("stdout", filename) == 0
374 || strcmp ("-", filename) == 0)
5d8b352a
NS
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
b5f47924
SS
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
388static FILE *
389dump_open_alternate_stream (struct dump_file_info *dfi)
390{
b5f47924
SS
391 if (!dfi->alt_filename)
392 return NULL;
393
394 if (dfi->alt_stream)
395 return dfi->alt_stream;
396
5d8b352a 397 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
b5f47924 398
5d8b352a 399 if (stream)
b5f47924
SS
400 dfi->alt_state = 1;
401
402 return stream;
403}
404
4f5b9c80
DM
405/* Construct a dump_user_location_t from STMT (using its location and
406 hotness). */
407
12c27c75 408dump_user_location_t::dump_user_location_t (const gimple *stmt)
4f5b9c80
DM
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
12c27c75 422dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
4f5b9c80
DM
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
437dump_user_location_t
438dump_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
ed2d9d37
DM
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
452static const char *
453kind_as_string (dump_flags_t dump_kind)
454{
7db960c5 455 switch (dump_kind & MSG_ALL_KINDS)
ed2d9d37
DM
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
b5f47924
SS
468/* Print source location on DFILE if enabled. */
469
4f5b9c80 470static void
620e594b 471dump_loc (dump_flags_t dump_kind, FILE *dfile, location_t loc)
b5f47924 472{
b5f47924
SS
473 if (dump_kind)
474 {
502498d5 475 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
ed2d9d37 476 fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc),
103ff0d6 477 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
a3d7af04 478 else if (current_function_decl)
ed2d9d37 479 fprintf (dfile, "%s:%d:%d: ",
b5f47924 480 DECL_SOURCE_FILE (current_function_decl),
103ff0d6
TJ
481 DECL_SOURCE_LINE (current_function_decl),
482 DECL_SOURCE_COLUMN (current_function_decl));
ed2d9d37 483 fprintf (dfile, "%s: ", kind_as_string (dump_kind));
6475e077
DM
484 /* Indentation based on scope depth. */
485 fprintf (dfile, "%*s", get_dump_scope_depth (), "");
b5f47924
SS
486 }
487}
488
b84e3bde
DM
489/* Print source location to PP if enabled. */
490
491static void
620e594b 492dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
b84e3bde
DM
493{
494 if (dump_kind)
495 {
496 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
ed2d9d37 497 pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc),
b84e3bde
DM
498 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
499 else if (current_function_decl)
ed2d9d37 500 pp_printf (pp, "%s:%d:%d: ",
b84e3bde
DM
501 DECL_SOURCE_FILE (current_function_decl),
502 DECL_SOURCE_LINE (current_function_decl),
503 DECL_SOURCE_COLUMN (current_function_decl));
ed2d9d37 504 pp_printf (pp, "%s: ", kind_as_string (dump_kind));
b84e3bde
DM
505 /* Indentation based on scope depth. */
506 for (unsigned i = 0; i < get_dump_scope_depth (); i++)
507 pp_character (pp, ' ');
508 }
509}
510
4df3629e
DM
511/* Implementation of dump_context member functions. */
512
513/* dump_context's dtor. */
514
515dump_context::~dump_context ()
516{
517 delete m_pending;
518}
519
8d1af516
DM
520void
521dump_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
531void
532dump_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
b84e3bde
DM
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
545void
546dump_context::refresh_dumps_are_enabled ()
547{
548 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
549 || m_test_pp);
550}
551
7db960c5
DM
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
558bool
559dump_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
1d8693a0
DM
581/* Print LOC to the appropriate dump destinations, given DUMP_KIND.
582 If optinfos are enabled, begin a new optinfo. */
583
584void
3da39f52
DM
585dump_context::dump_loc (const dump_metadata_t &metadata,
586 const dump_user_location_t &loc)
1d8693a0 587{
b84e3bde
DM
588 end_any_optinfo ();
589
3da39f52 590 dump_loc_immediate (metadata.get_dump_flags (), loc);
f4ebbd24
DM
591
592 if (optinfo_enabled_p ())
3da39f52 593 begin_next_optinfo (metadata, loc);
f4ebbd24
DM
594}
595
596/* As dump_loc above, but without starting a new optinfo. */
597
598void
599dump_context::dump_loc_immediate (dump_flags_t dump_kind,
3da39f52 600 const dump_user_location_t &loc)
f4ebbd24 601{
1d8693a0
DM
602 location_t srcloc = loc.get_location_t ();
603
7db960c5 604 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
1d8693a0
DM
605 ::dump_loc (dump_kind, dump_file, srcloc);
606
7db960c5 607 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
1d8693a0
DM
608 ::dump_loc (dump_kind, alt_dump_file, srcloc);
609
b84e3bde 610 /* Support for temp_dump_context in selftests. */
7db960c5 611 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
b84e3bde 612 ::dump_loc (dump_kind, m_test_pp, srcloc);
1d8693a0
DM
613}
614
b84e3bde
DM
615/* Make an item for the given dump call, equivalent to print_gimple_stmt. */
616
617static optinfo_item *
618make_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
b5f47924
SS
631/* Dump gimple statement GS with SPC indentation spaces and
632 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
633
634void
3da39f52 635dump_context::dump_gimple_stmt (const dump_metadata_t &metadata,
4df3629e
DM
636 dump_flags_t extra_dump_flags,
637 gimple *gs, int spc)
b5f47924 638{
b84e3bde
DM
639 optinfo_item *item
640 = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
3da39f52 641 emit_item (item, metadata.get_dump_flags ());
4df3629e
DM
642
643 if (optinfo_enabled_p ())
644 {
3da39f52 645 optinfo &info = ensure_pending_optinfo (metadata);
b84e3bde 646 info.add_item (item);
4df3629e 647 }
b84e3bde
DM
648 else
649 delete item;
b5f47924
SS
650}
651
652/* Similar to dump_gimple_stmt, except additionally print source location. */
653
654void
3da39f52
DM
655dump_context::dump_gimple_stmt_loc (const dump_metadata_t &metadata,
656 const dump_user_location_t &loc,
4df3629e
DM
657 dump_flags_t extra_dump_flags,
658 gimple *gs, int spc)
b5f47924 659{
3da39f52
DM
660 dump_loc (metadata, loc);
661 dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
b5f47924
SS
662}
663
b84e3bde
DM
664/* Make an item for the given dump call, equivalent to print_gimple_expr. */
665
666static optinfo_item *
667make_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
30f502ed
RB
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
684void
3da39f52 685dump_context::dump_gimple_expr (const dump_metadata_t &metadata,
4df3629e
DM
686 dump_flags_t extra_dump_flags,
687 gimple *gs, int spc)
30f502ed 688{
b84e3bde
DM
689 optinfo_item *item
690 = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
3da39f52 691 emit_item (item, metadata.get_dump_flags ());
4df3629e
DM
692
693 if (optinfo_enabled_p ())
694 {
3da39f52 695 optinfo &info = ensure_pending_optinfo (metadata);
b84e3bde 696 info.add_item (item);
4df3629e 697 }
b84e3bde
DM
698 else
699 delete item;
30f502ed
RB
700}
701
702/* Similar to dump_gimple_expr, except additionally print source location. */
703
704void
3da39f52
DM
705dump_context::dump_gimple_expr_loc (const dump_metadata_t &metadata,
706 const dump_user_location_t &loc,
4df3629e
DM
707 dump_flags_t extra_dump_flags,
708 gimple *gs,
709 int spc)
30f502ed 710{
3da39f52
DM
711 dump_loc (metadata, loc);
712 dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
30f502ed
RB
713}
714
b84e3bde
DM
715/* Make an item for the given dump call, equivalent to print_generic_expr. */
716
717static optinfo_item *
718make_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}
30f502ed 734
b5f47924
SS
735/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
736 DUMP_KIND is enabled. */
737
738void
3da39f52 739dump_context::dump_generic_expr (const dump_metadata_t &metadata,
4df3629e
DM
740 dump_flags_t extra_dump_flags,
741 tree t)
b5f47924 742{
b84e3bde
DM
743 optinfo_item *item
744 = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
3da39f52 745 emit_item (item, metadata.get_dump_flags ());
4df3629e
DM
746
747 if (optinfo_enabled_p ())
748 {
3da39f52 749 optinfo &info = ensure_pending_optinfo (metadata);
b84e3bde 750 info.add_item (item);
4df3629e 751 }
b84e3bde
DM
752 else
753 delete item;
b5f47924
SS
754}
755
d7259673
DM
756
757/* Similar to dump_generic_expr, except additionally print the source
758 location. */
759
760void
3da39f52
DM
761dump_context::dump_generic_expr_loc (const dump_metadata_t &metadata,
762 const dump_user_location_t &loc,
4df3629e
DM
763 dump_flags_t extra_dump_flags,
764 tree t)
d7259673 765{
3da39f52
DM
766 dump_loc (metadata, loc);
767 dump_generic_expr (metadata, extra_dump_flags, t);
d7259673
DM
768}
769
d8010ee4
DM
770/* Make an item for the given dump call. */
771
772static optinfo_item *
773make_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
6f795a92
DM
782/* dump_pretty_printer's ctor. */
783
784dump_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
805void
806dump_pretty_printer::emit_items (optinfo *dest)
b84e3bde 807{
6f795a92
DM
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
847void
848dump_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));
b84e3bde
DM
857 optinfo_item *item
858 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
859 formatted_text);
6f795a92
DM
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);
b84e3bde
DM
866}
867
6f795a92
DM
868/* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
869 to DEST; otherwise delete ITEM. */
b84e3bde 870
6f795a92
DM
871void
872dump_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}
b84e3bde 880
6f795a92
DM
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
884void
885dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item)
b84e3bde 886{
6f795a92
DM
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
898bool
899dump_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
d8010ee4
DM
915 %C: cgraph_node *:
916 Equivalent to: dump_symtab_node (MSG_*, node)
6f795a92
DM
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
d8010ee4
DM
924 TODO: add a format code that can handle (symtab_node*) *and* both
925 subclasses (presumably means teaching -Wformat about non-virtual
926 subclasses).
6f795a92
DM
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
931bool
932dump_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 {
d8010ee4
DM
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
6f795a92
DM
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 }
b84e3bde
DM
982}
983
b5f47924
SS
984/* Output a formatted message using FORMAT on appropriate dump streams. */
985
986void
3da39f52 987dump_context::dump_printf_va (const dump_metadata_t &metadata, const char *format,
6f795a92 988 va_list *ap)
b5f47924 989{
3da39f52 990 dump_pretty_printer pp (this, metadata.get_dump_flags ());
4df3629e 991
6f795a92
DM
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. */
4df3629e
DM
1001 if (optinfo_enabled_p ())
1002 {
3da39f52 1003 optinfo &info = ensure_pending_optinfo (metadata);
6f795a92 1004 pp.emit_items (&info);
b5f47924 1005 }
b84e3bde 1006 else
6f795a92 1007 pp.emit_items (NULL);
b5f47924
SS
1008}
1009
4df3629e
DM
1010/* Similar to dump_printf, except source location is also printed, and
1011 dump location captured. */
b5f47924
SS
1012
1013void
3da39f52
DM
1014dump_context::dump_printf_loc_va (const dump_metadata_t &metadata,
1015 const dump_user_location_t &loc,
6f795a92 1016 const char *format, va_list *ap)
b5f47924 1017{
3da39f52
DM
1018 dump_loc (metadata, loc);
1019 dump_printf_va (metadata, format, ap);
b5f47924
SS
1020}
1021
b84e3bde 1022/* Make an item for the given dump call, equivalent to print_dec. */
dc3f3805
RS
1023
1024template<unsigned int N, typename C>
b84e3bde
DM
1025static optinfo_item *
1026make_item_for_dump_dec (const poly_int<N, C> &value)
dc3f3805
RS
1027{
1028 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
1029 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
dc3f3805 1030
b84e3bde
DM
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
1053template<unsigned int N, typename C>
1054void
3da39f52 1055dump_context::dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
b84e3bde
DM
1056{
1057 optinfo_item *item = make_item_for_dump_dec (value);
3da39f52 1058 emit_item (item, metadata.get_dump_flags ());
4df3629e
DM
1059
1060 if (optinfo_enabled_p ())
1061 {
3da39f52 1062 optinfo &info = ensure_pending_optinfo (metadata);
b84e3bde 1063 info.add_item (item);
4df3629e 1064 }
b84e3bde
DM
1065 else
1066 delete item;
1067}
1068
4df3629e
DM
1069/* Output the name of NODE on appropriate dump streams. */
1070
1071void
3da39f52 1072dump_context::dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
4df3629e 1073{
b84e3bde 1074 optinfo_item *item = make_item_for_dump_symtab_node (node);
3da39f52 1075 emit_item (item, metadata.get_dump_flags ());
4df3629e
DM
1076
1077 if (optinfo_enabled_p ())
1078 {
3da39f52 1079 optinfo &info = ensure_pending_optinfo (metadata);
b84e3bde 1080 info.add_item (item);
4df3629e 1081 }
b84e3bde
DM
1082 else
1083 delete item;
4df3629e
DM
1084}
1085
1086/* Get the current dump scope-nesting depth.
1087 For use by -fopt-info (for showing nesting via indentation). */
1088
1089unsigned int
1090dump_context::get_scope_depth () const
1091{
1092 return m_scope_depth;
1093}
1094
1095/* Push a nested dump scope.
7db960c5 1096 Increment the scope depth.
4df3629e
DM
1097 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1098 destination, if any.
7db960c5 1099 Emit a "scope" optinfo if optinfos are enabled. */
4df3629e
DM
1100
1101void
3da39f52
DM
1102dump_context::begin_scope (const char *name,
1103 const dump_user_location_t &user_location,
1104 const dump_impl_location_t &impl_location)
4df3629e 1105{
7db960c5
DM
1106 m_scope_depth++;
1107
3da39f52
DM
1108 location_t src_loc = user_location.get_location_t ();
1109
7db960c5 1110 if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags))
3da39f52 1111 ::dump_loc (MSG_NOTE, dump_file, src_loc);
4df3629e 1112
7db960c5 1113 if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags))
3da39f52 1114 ::dump_loc (MSG_NOTE, alt_dump_file, src_loc);
b84e3bde
DM
1115
1116 /* Support for temp_dump_context in selftests. */
7db960c5 1117 if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
3da39f52 1118 ::dump_loc (MSG_NOTE, m_test_pp, src_loc);
b84e3bde 1119
6f795a92
DM
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)));
b84e3bde 1125 emit_item (item, MSG_NOTE);
4df3629e
DM
1126
1127 if (optinfo_enabled_p ())
1128 {
3da39f52
DM
1129 optinfo &info
1130 = begin_next_optinfo (dump_metadata_t (MSG_NOTE, impl_location),
1131 user_location);
b84e3bde
DM
1132 info.m_kind = OPTINFO_KIND_SCOPE;
1133 info.add_item (item);
c95c5528 1134 end_any_optinfo ();
4df3629e 1135 }
b84e3bde
DM
1136 else
1137 delete item;
4df3629e
DM
1138}
1139
1140/* Pop a nested dump scope. */
1141
1142void
1143dump_context::end_scope ()
1144{
1145 end_any_optinfo ();
1146 m_scope_depth--;
8d1af516
DM
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
1156bool
1157dump_context::optinfo_enabled_p () const
1158{
1159 return (optimization_records_enabled_p ());
4df3629e
DM
1160}
1161
1162/* Return the optinfo currently being accumulated, creating one if
1163 necessary. */
1164
1165optinfo &
3da39f52 1166dump_context::ensure_pending_optinfo (const dump_metadata_t &metadata)
4df3629e
DM
1167{
1168 if (!m_pending)
3da39f52 1169 return begin_next_optinfo (metadata, dump_user_location_t ());
4df3629e
DM
1170 return *m_pending;
1171}
1172
1173/* Start a new optinfo and return it, ending any optinfo that was already
1174 accumulated. */
1175
1176optinfo &
3da39f52
DM
1177dump_context::begin_next_optinfo (const dump_metadata_t &metadata,
1178 const dump_user_location_t &user_loc)
4df3629e
DM
1179{
1180 end_any_optinfo ();
1181 gcc_assert (m_pending == NULL);
3da39f52 1182 dump_location_t loc (user_loc, metadata.get_impl_location ());
4df3629e 1183 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
3da39f52 1184 m_pending->handle_dump_file_kind (metadata.get_dump_flags ());
4df3629e
DM
1185 return *m_pending;
1186}
1187
1188/* End any optinfo that has been accumulated within this context; emitting
4a4412b9 1189 it to any destinations as appropriate, such as optimization records. */
4df3629e
DM
1190
1191void
1192dump_context::end_any_optinfo ()
1193{
1194 if (m_pending)
8d1af516 1195 emit_optinfo (m_pending);
4df3629e
DM
1196 delete m_pending;
1197 m_pending = NULL;
1198}
1199
8d1af516
DM
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
1204void
1205dump_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
b84e3bde
DM
1212/* Emit ITEM to all item destinations (those that don't require
1213 consolidation into optinfo instances). */
1214
1215void
1216dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind)
1217{
7db960c5 1218 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
b84e3bde
DM
1219 fprintf (dump_file, "%s", item->get_text ());
1220
7db960c5 1221 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
b84e3bde
DM
1222 fprintf (alt_dump_file, "%s", item->get_text ());
1223
1224 /* Support for temp_dump_context in selftests. */
7db960c5 1225 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
b84e3bde
DM
1226 pp_string (m_test_pp, item->get_text ());
1227}
1228
4df3629e
DM
1229/* The current singleton dump_context, and its default. */
1230
1231dump_context *dump_context::s_current = &dump_context::s_default;
1232dump_context dump_context::s_default;
1233
1234/* Implementation of dump_* API calls, calling into dump_context
1235 member functions. */
1236
bbeeac91
DM
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
4df3629e
DM
1250/* Dump gimple statement GS with SPC indentation spaces and
1251 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
1252
1253void
3da39f52 1254dump_gimple_stmt (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
4df3629e
DM
1255 gimple *gs, int spc)
1256{
bbeeac91 1257 VERIFY_DUMP_ENABLED_P;
3da39f52 1258 dump_context::get ().dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
4df3629e
DM
1259}
1260
1261/* Similar to dump_gimple_stmt, except additionally print source location. */
1262
1263void
3da39f52
DM
1264dump_gimple_stmt_loc (const dump_metadata_t &metadata,
1265 const dump_user_location_t &loc,
4df3629e
DM
1266 dump_flags_t extra_dump_flags, gimple *gs, int spc)
1267{
bbeeac91 1268 VERIFY_DUMP_ENABLED_P;
3da39f52 1269 dump_context::get ().dump_gimple_stmt_loc (metadata, loc, extra_dump_flags,
4df3629e
DM
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
1277void
3da39f52
DM
1278dump_gimple_expr (const dump_metadata_t &metadata,
1279 dump_flags_t extra_dump_flags,
4df3629e
DM
1280 gimple *gs, int spc)
1281{
bbeeac91 1282 VERIFY_DUMP_ENABLED_P;
3da39f52 1283 dump_context::get ().dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
4df3629e
DM
1284}
1285
1286/* Similar to dump_gimple_expr, except additionally print source location. */
1287
1288void
3da39f52
DM
1289dump_gimple_expr_loc (const dump_metadata_t &metadata,
1290 const dump_user_location_t &loc,
4df3629e
DM
1291 dump_flags_t extra_dump_flags, gimple *gs, int spc)
1292{
bbeeac91 1293 VERIFY_DUMP_ENABLED_P;
3da39f52 1294 dump_context::get ().dump_gimple_expr_loc (metadata, loc, extra_dump_flags,
4df3629e
DM
1295 gs, spc);
1296}
1297
1298/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
1299 DUMP_KIND is enabled. */
1300
1301void
3da39f52 1302dump_generic_expr (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
4df3629e
DM
1303 tree t)
1304{
bbeeac91 1305 VERIFY_DUMP_ENABLED_P;
3da39f52 1306 dump_context::get ().dump_generic_expr (metadata, extra_dump_flags, t);
4df3629e
DM
1307}
1308
1309/* Similar to dump_generic_expr, except additionally print the source
1310 location. */
1311
1312void
3da39f52
DM
1313dump_generic_expr_loc (const dump_metadata_t &metadata,
1314 const dump_user_location_t &loc,
4df3629e
DM
1315 dump_flags_t extra_dump_flags, tree t)
1316{
bbeeac91 1317 VERIFY_DUMP_ENABLED_P;
3da39f52 1318 dump_context::get ().dump_generic_expr_loc (metadata, loc, extra_dump_flags,
4df3629e
DM
1319 t);
1320}
1321
1322/* Output a formatted message using FORMAT on appropriate dump streams. */
1323
1324void
3da39f52 1325dump_printf (const dump_metadata_t &metadata, const char *format, ...)
4df3629e 1326{
bbeeac91 1327 VERIFY_DUMP_ENABLED_P;
4df3629e
DM
1328 va_list ap;
1329 va_start (ap, format);
3da39f52 1330 dump_context::get ().dump_printf_va (metadata, format, &ap);
4df3629e
DM
1331 va_end (ap);
1332}
1333
1334/* Similar to dump_printf, except source location is also printed, and
1335 dump location captured. */
1336
1337void
3da39f52
DM
1338dump_printf_loc (const dump_metadata_t &metadata,
1339 const dump_user_location_t &loc,
4df3629e
DM
1340 const char *format, ...)
1341{
bbeeac91 1342 VERIFY_DUMP_ENABLED_P;
4df3629e
DM
1343 va_list ap;
1344 va_start (ap, format);
3da39f52 1345 dump_context::get ().dump_printf_loc_va (metadata, loc, format, &ap);
4df3629e
DM
1346 va_end (ap);
1347}
1348
1349/* Output VALUE in decimal to appropriate dump streams. */
1350
1351template<unsigned int N, typename C>
1352void
3da39f52 1353dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
4df3629e 1354{
bbeeac91 1355 VERIFY_DUMP_ENABLED_P;
3da39f52 1356 dump_context::get ().dump_dec (metadata, value);
dc3f3805
RS
1357}
1358
3da39f52
DM
1359template void dump_dec (const dump_metadata_t &metadata, const poly_uint16 &);
1360template void dump_dec (const dump_metadata_t &metadata, const poly_int64 &);
1361template void dump_dec (const dump_metadata_t &metadata, const poly_uint64 &);
1362template void dump_dec (const dump_metadata_t &metadata, const poly_offset_int &);
1363template void dump_dec (const dump_metadata_t &metadata, const poly_widest_int &);
dc3f3805 1364
370c2ebe
RS
1365void
1366dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
1367{
bbeeac91 1368 VERIFY_DUMP_ENABLED_P;
7db960c5
DM
1369 if (dump_file
1370 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
370c2ebe
RS
1371 print_dec (value, dump_file, sgn);
1372
7db960c5
DM
1373 if (alt_dump_file
1374 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
370c2ebe
RS
1375 print_dec (value, alt_dump_file, sgn);
1376}
1377
1378/* Output VALUE in hexadecimal to appropriate dump streams. */
1379
1380void
1381dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
1382{
bbeeac91 1383 VERIFY_DUMP_ENABLED_P;
7db960c5
DM
1384 if (dump_file
1385 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
370c2ebe
RS
1386 print_hex (value, dump_file);
1387
7db960c5
DM
1388 if (alt_dump_file
1389 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
370c2ebe
RS
1390 print_hex (value, alt_dump_file);
1391}
1392
4df3629e
DM
1393/* Emit and delete the currently pending optinfo, if there is one,
1394 without the caller needing to know about class dump_context. */
1395
1396void
1397dumpfile_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. */
6475e077 1403
4df3629e 1404void
3da39f52 1405dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
4df3629e 1406{
bbeeac91 1407 VERIFY_DUMP_ENABLED_P;
3da39f52 1408 dump_context::get ().dump_symtab_node (metadata, node);
4df3629e 1409}
6475e077
DM
1410
1411/* Get the current dump scope-nesting depth.
4df3629e 1412 For use by -fopt-info (for showing nesting via indentation). */
6475e077
DM
1413
1414unsigned int
1415get_dump_scope_depth ()
1416{
4df3629e 1417 return dump_context::get ().get_scope_depth ();
6475e077
DM
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.
4df3629e 1423 Emit a "scope" opinfo if optinfos are enabled.
6475e077
DM
1424 Increment the scope depth. */
1425
1426void
3da39f52
DM
1427dump_begin_scope (const char *name,
1428 const dump_user_location_t &user_location,
1429 const dump_impl_location_t &impl_location)
6475e077 1430{
3da39f52 1431 dump_context::get ().begin_scope (name, user_location, impl_location);
6475e077
DM
1432}
1433
1434/* Pop a nested dump scope. */
1435
1436void
1437dump_end_scope ()
1438{
4df3629e 1439 dump_context::get ().end_scope ();
6475e077
DM
1440}
1441
b5f47924
SS
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
2b4e6bf1
SS
1445 set dump_flags appropriately for both pass dump stream and
1446 -fopt-info stream. */
b5f47924
SS
1447
1448int
47e0da37 1449gcc::dump_manager::
1a817418 1450dump_start (int phase, dump_flags_t *flag_ptr)
b5f47924
SS
1451{
1452 int count = 0;
1453 char *name;
1454 struct dump_file_info *dfi;
1455 FILE *stream;
74911c3c 1456 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1457 return 0;
1458
1459 dfi = get_dump_file_info (phase);
1460 name = get_dump_file_name (phase);
1461 if (name)
1462 {
5d8b352a
NS
1463 stream = dump_open (name, dfi->pstate < 0);
1464 if (stream)
b5f47924
SS
1465 {
1466 dfi->pstate = 1;
1467 count++;
1468 }
1469 free (name);
1470 dfi->pstream = stream;
29b54a9d 1471 set_dump_file (dfi->pstream);
b5f47924 1472 /* Initialize current dump flags. */
8264c84d 1473 pflags = dfi->pflags;
b5f47924
SS
1474 }
1475
1476 stream = dump_open_alternate_stream (dfi);
1477 if (stream)
1478 {
1479 dfi->alt_stream = stream;
1480 count++;
29b54a9d 1481 set_alt_dump_file (dfi->alt_stream);
2b4e6bf1 1482 /* Initialize current -fopt-info flags. */
8264c84d 1483 alt_flags = dfi->alt_flags;
b5f47924
SS
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
1495void
47e0da37 1496gcc::dump_manager::
b5f47924
SS
1497dump_finish (int phase)
1498{
1499 struct dump_file_info *dfi;
1500
1501 if (phase < 0)
1502 return;
1503 dfi = get_dump_file_info (phase);
5d8b352a 1504 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
b5f47924
SS
1505 fclose (dfi->pstream);
1506
5d8b352a 1507 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
b5f47924
SS
1508 fclose (dfi->alt_stream);
1509
1510 dfi->alt_stream = NULL;
1511 dfi->pstream = NULL;
29b54a9d
DM
1512 set_dump_file (NULL);
1513 set_alt_dump_file (NULL);
4af78ef8
DM
1514 dump_flags = TDF_NONE;
1515 alt_flags = TDF_NONE;
1516 pflags = TDF_NONE;
b5f47924
SS
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.
75fdb07e
JH
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. */
b5f47924
SS
1525
1526FILE *
75fdb07e 1527dump_begin (int phase, dump_flags_t *flag_ptr, int part)
47e0da37 1528{
75fdb07e 1529 return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
47e0da37
DM
1530}
1531
1532FILE *
1533gcc::dump_manager::
75fdb07e 1534dump_begin (int phase, dump_flags_t *flag_ptr, int part)
b5f47924 1535{
74911c3c 1536 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1537 return NULL;
1538
84d2160d 1539 char *name = get_dump_file_name (phase, part);
b5f47924
SS
1540 if (!name)
1541 return NULL;
84d2160d 1542 struct dump_file_info *dfi = get_dump_file_info (phase);
b5f47924 1543
75fdb07e
JH
1544 /* We do not support re-opening of dump files with parts. This would require
1545 tracking pstate per part of the dump file. */
84d2160d 1546 FILE *stream = dump_open (name, part != -1 || dfi->pstate < 0);
5d8b352a 1547 if (stream)
b5f47924
SS
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
47e0da37
DM
1563int
1564gcc::dump_manager::
1565dump_phase_enabled_p (int phase) const
b5f47924
SS
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;
47e0da37
DM
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)
b5f47924
SS
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
1587int
47e0da37
DM
1588gcc::dump_manager::
1589dump_initialized_p (int phase) const
b5f47924
SS
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
1597const char *
1598dump_flag_name (int phase)
47e0da37
DM
1599{
1600 return g->get_dumps ()->dump_flag_name (phase);
1601}
1602
1603const char *
1604gcc::dump_manager::
1605dump_flag_name (int phase) const
b5f47924
SS
1606{
1607 struct dump_file_info *dfi = get_dump_file_info (phase);
1608 return dfi->swtch;
1609}
1610
5d98e5a6
DM
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
1624void
1625gcc::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
b5f47924
SS
1655/* Finish a tree dump for PHASE. STREAM is the stream created by
1656 dump_begin. */
1657
1658void
1659dump_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
47e0da37
DM
1668int
1669gcc::dump_manager::
8264c84d 1670dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
b5f47924 1671{
b5f47924
SS
1672 int n = 0;
1673 size_t i;
1674
1675 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1676 {
5433e401 1677 if (dump_files[i].dkind == dkind)
b5f47924
SS
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
47e0da37 1696 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 1697 {
5433e401 1698 if (m_extra_dump_files[i].dkind == dkind)
b5f47924 1699 {
47e0da37
DM
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;
b5f47924
SS
1703 n++;
1704 /* Override the existing filename. */
1705 if (filename)
1706 {
47e0da37 1707 m_extra_dump_files[i].pfilename = xstrdup (filename);
b5f47924
SS
1708 /* Since it is a command-line provided file, which is
1709 common to all the phases, use it in append mode. */
47e0da37 1710 m_extra_dump_files[i].pstate = 1;
b5f47924
SS
1711 }
1712 if (old_filename && filename != old_filename)
1713 free (CONST_CAST (char *, old_filename));
1714 }
1715 }
1716
1717 return n;
1718}
1719
2b4e6bf1
SS
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. */
b5f47924 1723
47e0da37
DM
1724int
1725gcc::dump_manager::
4af78ef8 1726opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1a817418 1727 const char *filename)
b5f47924
SS
1728{
1729 int n = 0;
b5f47924 1730
5d98e5a6
DM
1731 m_optgroup_flags = optgroup_flags;
1732 m_optinfo_flags = flags;
1733 m_optinfo_filename = xstrdup (filename);
b5f47924 1734
5d98e5a6
DM
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++;
b5f47924
SS
1742
1743 return n;
1744}
1745
5d98e5a6
DM
1746/* Use the saved -fopt-info options to update DFI.
1747 Return true if the dump is enabled. */
1748
1749bool
1750gcc::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
66d62d9f
HK
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. */
b5f47924 1774
66d62d9f
HK
1775dump_flags_t
1776parse_dump_option (const char *option_value, const char **pos_p)
b5f47924 1777{
b5f47924 1778 const char *ptr;
1a817418 1779 dump_flags_t flags;
b5f47924 1780
b5f47924 1781 ptr = option_value;
66d62d9f
HK
1782 if (pos_p)
1783 *pos_p = NULL;
f4ebbd24
DM
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;
b5f47924
SS
1790
1791 while (*ptr)
1792 {
4af78ef8 1793 const struct kv_pair<dump_flags_t> *option_ptr;
b5f47924
SS
1794 const char *end_ptr;
1795 const char *eq_ptr;
1796 unsigned length;
b5f47924
SS
1797 while (*ptr == '-')
1798 ptr++;
1799 end_ptr = strchr (ptr, '-');
1800 eq_ptr = strchr (ptr, '=');
1801
1802 if (eq_ptr && !end_ptr)
66d62d9f 1803 end_ptr = eq_ptr;
b5f47924
SS
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))
66d62d9f
HK
1812 {
1813 flags |= option_ptr->value;
b5f47924 1814 goto found;
66d62d9f 1815 }
b5f47924
SS
1816
1817 if (*ptr == '=')
66d62d9f 1818 {
b5f47924
SS
1819 /* Interpret rest of the argument as a dump filename. This
1820 filename overrides other command line filenames. */
66d62d9f
HK
1821 if (pos_p)
1822 *pos_p = ptr + 1;
1823 break;
1824 }
b5f47924 1825 else
66d62d9f
HK
1826 {
1827 warning (0, "ignoring unknown option %q.*s",
1828 length, ptr);
1829 flags = TDF_ERROR;
1830 }
1831 found:
b5f47924 1832 ptr = end_ptr;
66d62d9f
HK
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
1841int
1842gcc::dump_manager::
1843dump_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);
b5f47924
SS
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)
8264c84d 1873 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
b5f47924
SS
1874
1875 return 1;
1876}
1877
48c04103 1878void
47e0da37 1879gcc::dump_manager::
b5f47924
SS
1880dump_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
47e0da37
DM
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);
b5f47924
SS
1895
1896 if (!any)
47e0da37
DM
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);
b5f47924 1899
48c04103
ML
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 }
b5f47924
SS
1914}
1915
2b4e6bf1
SS
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. */
b5f47924
SS
1918
1919static int
4af78ef8
DM
1920opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
1921 optgroup_flags_t *optgroup_flags, char **filename)
b5f47924
SS
1922{
1923 const char *option_value;
1924 const char *ptr;
1925
1926 option_value = arg;
1927 ptr = option_value;
1928
1929 *filename = NULL;
7db960c5
DM
1930
1931 /* Default to filtering out "internals" messages, and retaining
f4ebbd24
DM
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;
7db960c5 1935
4af78ef8 1936 *optgroup_flags = OPTGROUP_NONE;
b5f47924
SS
1937
1938 if (!ptr)
2b4e6bf1 1939 return 1; /* Handle '-fopt-info' without any additional options. */
b5f47924
SS
1940
1941 while (*ptr)
1942 {
b5f47924
SS
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
2ab6839b 1952 if (eq_ptr && (!end_ptr || eq_ptr < end_ptr))
b5f47924 1953 end_ptr = eq_ptr;
2ab6839b 1954 else if (!end_ptr)
b5f47924
SS
1955 end_ptr = ptr + strlen (ptr);
1956 length = end_ptr - ptr;
1957
4af78ef8
DM
1958 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
1959 option_ptr->name; option_ptr++)
b5f47924
SS
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
4af78ef8
DM
1967 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
1968 option_ptr->name; option_ptr++)
2b4e6bf1
SS
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
b5f47924
SS
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
2b4e6bf1
SS
1984 {
1985 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1986 length, ptr, arg);
1987 return 0;
1988 }
b5f47924
SS
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
1999int
2000opt_info_switch_p (const char *arg)
2001{
1a817418 2002 dump_flags_t flags;
4af78ef8 2003 optgroup_flags_t optgroup_flags;
b5f47924 2004 char *filename;
2b4e6bf1 2005 static char *file_seen = NULL;
47e0da37 2006 gcc::dump_manager *dumps = g->get_dumps ();
b5f47924 2007
2b4e6bf1
SS
2008 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
2009 return 0;
b5f47924
SS
2010
2011 if (!filename)
2012 filename = xstrdup ("stderr");
2b4e6bf1
SS
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);
7db960c5
DM
2023 if (!(flags & MSG_ALL_KINDS))
2024 flags |= MSG_OPTIMIZED_LOCATIONS;
2b4e6bf1
SS
2025 if (!optgroup_flags)
2026 optgroup_flags = OPTGROUP_ALL;
b5f47924 2027
47e0da37 2028 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
b5f47924
SS
2029}
2030
b5f47924
SS
2031/* Print basic block on the dump streams. */
2032
2033void
4af78ef8 2034dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
b5f47924 2035{
7db960c5
DM
2036 if (dump_file
2037 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
b5f47924 2038 dump_bb (dump_file, bb, indent, TDF_DETAILS);
7db960c5
DM
2039 if (alt_dump_file
2040 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
b5f47924
SS
2041 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
2042}
2043
c24e924f
NS
2044/* Dump FUNCTION_DECL FN as tree dump PHASE. */
2045
2046void
2047dump_function (int phase, tree fn)
2048{
2049 FILE *stream;
1a817418 2050 dump_flags_t flags;
c24e924f
NS
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
b5f47924
SS
2060/* Print information from the combine pass on dump_file. */
2061
2062void
2063print_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
2071bool
2072enable_rtl_dump_file (void)
2073{
47e0da37
DM
2074 gcc::dump_manager *dumps = g->get_dumps ();
2075 int num_enabled =
8264c84d
ML
2076 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
2077 NULL);
47e0da37 2078 return num_enabled > 0;
b5f47924 2079}
4f5b9c80 2080
f61f9b28
RB
2081/* debug_dump_context's ctor. Temporarily override the dump_context
2082 (to forcibly enable output to stderr). */
2083
2084debug_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
2099debug_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
4f5b9c80
DM
2109#if CHECKING_P
2110
f4ebbd24
DM
2111namespace selftest {
2112
4df3629e
DM
2113/* temp_dump_context's ctor. Temporarily override the dump_context
2114 (to forcibly enable optinfo-generation). */
2115
b84e3bde 2116temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
f4ebbd24 2117 bool forcibly_enable_dumping,
b84e3bde 2118 dump_flags_t test_pp_flags)
4df3629e 2119: m_context (),
c00568f3 2120 m_saved (&dump_context::get ())
4df3629e
DM
2121{
2122 dump_context::s_current = &m_context;
8d1af516
DM
2123 if (forcibly_enable_optinfo)
2124 m_context.set_json_writer (new optrecord_json_writer ());
f4ebbd24
DM
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 }
b84e3bde
DM
2132
2133 dump_context::get ().refresh_dumps_are_enabled ();
4df3629e
DM
2134}
2135
2136/* temp_dump_context's dtor. Restore the saved dump_context. */
2137
2138temp_dump_context::~temp_dump_context ()
2139{
8d1af516
DM
2140 m_context.set_json_writer (NULL);
2141
4df3629e 2142 dump_context::s_current = m_saved;
b84e3bde
DM
2143
2144 dump_context::get ().refresh_dumps_are_enabled ();
2145}
2146
2147/* 0-terminate the text dumped so far, and return it. */
2148
2149const char *
2150temp_dump_context::get_dumped_text ()
2151{
2152 return pp_formatted_text (&m_pp);
4df3629e
DM
2153}
2154
3da39f52
DM
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
2159static void
2160assert_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
4f5b9c80
DM
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
2189static void
2190test_impl_location ()
2191{
4f5b9c80
DM
2192 /* Default ctor. */
2193 {
2194 dump_location_t loc;
2195 const int expected_line = __LINE__ - 1;
3da39f52
DM
2196 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2197 "dumpfile.c", expected_line, "test_impl_location");
4f5b9c80
DM
2198 }
2199
2200 /* Constructing from a gimple. */
2201 {
2202 dump_location_t loc ((gimple *)NULL);
2203 const int expected_line = __LINE__ - 1;
3da39f52
DM
2204 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2205 "dumpfile.c", expected_line, "test_impl_location");
4f5b9c80
DM
2206 }
2207
2208 /* Constructing from an rtx_insn. */
2209 {
2210 dump_location_t loc ((rtx_insn *)NULL);
2211 const int expected_line = __LINE__ - 1;
3da39f52
DM
2212 ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
2213 "dumpfile.c", expected_line, "test_impl_location");
4f5b9c80 2214 }
4f5b9c80
DM
2215}
2216
b84e3bde
DM
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
f4ebbd24 2221void
b84e3bde
DM
2222verify_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
4df3629e
DM
2231/* Verify that ITEM has the expected values. */
2232
f4ebbd24 2233void
4df3629e
DM
2234verify_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
4df3629e
DM
2245/* Verify that calls to the dump_* API are captured and consolidated into
2246 optimization records. */
2247
2248static void
2249test_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);
d8010ee4
DM
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)
b84e3bde 2259 return;
4df3629e 2260
3da39f52 2261 dump_user_location_t loc = dump_user_location_t::from_location_t (stmt_loc);
4df3629e 2262
6f795a92 2263 gimple *stmt = gimple_build_return (NULL);
d8010ee4 2264 gimple_set_location (stmt, stmt_loc);
4df3629e 2265
d8010ee4 2266 tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
6f795a92 2267 get_identifier ("test_decl"),
d8010ee4
DM
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
b84e3bde
DM
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++)
4df3629e 2280 {
b84e3bde
DM
2281 bool with_optinfo = (i == 0);
2282
2283 /* Test of dump_printf. */
2284 {
f4ebbd24 2285 temp_dump_context tmp (with_optinfo, true,
7db960c5 2286 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2287 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
3da39f52 2288 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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");
3da39f52
DM
2298 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2299 "dumpfile.c", expected_impl_line,
2300 "test_capture_of_dump_calls");
b84e3bde
DM
2301 }
2302 }
2303
6f795a92
DM
2304 /* Test of dump_printf with %T. */
2305 {
f4ebbd24 2306 temp_dump_context tmp (with_optinfo, true,
7db960c5 2307 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
6f795a92 2308 dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
3da39f52 2309 const int expected_impl_line = __LINE__ - 1;
6f795a92
DM
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");
3da39f52
DM
2320 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2321 "dumpfile.c", expected_impl_line,
2322 "test_capture_of_dump_calls");
6f795a92
DM
2323 }
2324 }
2325
2326 /* Test of dump_printf with %E. */
2327 {
f4ebbd24 2328 temp_dump_context tmp (with_optinfo, true,
7db960c5 2329 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
6f795a92 2330 dump_printf (MSG_NOTE, "gimple: %E", stmt);
3da39f52 2331 const int expected_impl_line = __LINE__ - 1;
6f795a92
DM
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: ");
d8010ee4 2341 ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
3da39f52
DM
2342 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2343 "dumpfile.c", expected_impl_line,
2344 "test_capture_of_dump_calls");
6f795a92
DM
2345 }
2346 }
2347
2348 /* Test of dump_printf with %G. */
2349 {
f4ebbd24 2350 temp_dump_context tmp (with_optinfo, true,
7db960c5 2351 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
6f795a92 2352 dump_printf (MSG_NOTE, "gimple: %G", stmt);
3da39f52 2353 const int expected_impl_line = __LINE__ - 1;
6f795a92
DM
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: ");
d8010ee4 2363 ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
3da39f52
DM
2364 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2365 "dumpfile.c", expected_impl_line,
2366 "test_capture_of_dump_calls");
d8010ee4
DM
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);
3da39f52 2375 const int expected_impl_line = __LINE__ - 1;
d8010ee4
DM
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");
3da39f52
DM
2386 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2387 "dumpfile.c", expected_impl_line,
2388 "test_capture_of_dump_calls");
6f795a92
DM
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 {
f4ebbd24 2399 temp_dump_context tmp (with_optinfo, true,
7db960c5 2400 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
6f795a92
DM
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 ");
d8010ee4
DM
2419 ASSERT_IS_GIMPLE (info->get_item (5), stmt_loc, "return;");
2420 ASSERT_IS_GIMPLE (info->get_item (6), stmt_loc, "return;");
6f795a92 2421 ASSERT_IS_TEXT (info->get_item (7), " after\n");
3da39f52
DM
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. */
6f795a92
DM
2425 }
2426 }
2427
b84e3bde
DM
2428 /* Tree, via dump_generic_expr. */
2429 {
f4ebbd24 2430 temp_dump_context tmp (with_optinfo, true,
7db960c5 2431 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2432 dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
3da39f52 2433 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2441 ASSERT_EQ (info->get_location_t (), stmt_loc);
b84e3bde
DM
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");
3da39f52
DM
2446 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2447 "dumpfile.c", expected_impl_line,
2448 "test_capture_of_dump_calls");
b84e3bde
DM
2449 }
2450 }
2451
2452 /* Tree, via dump_generic_expr_loc. */
2453 {
f4ebbd24 2454 temp_dump_context tmp (with_optinfo, true,
7db960c5 2455 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2456 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
3da39f52 2457 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2464 ASSERT_EQ (info->get_location_t (), stmt_loc);
b84e3bde
DM
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");
3da39f52
DM
2468 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2469 "dumpfile.c", expected_impl_line,
2470 "test_capture_of_dump_calls");
b84e3bde
DM
2471 }
2472 }
2473
2474 /* Gimple. */
2475 {
2476 /* dump_gimple_stmt_loc. */
2477 {
f4ebbd24 2478 temp_dump_context tmp (with_optinfo, true,
7db960c5 2479 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2480 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
3da39f52 2481 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2489 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
3da39f52
DM
2490 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2491 "dumpfile.c", expected_impl_line,
2492 "test_capture_of_dump_calls");
b84e3bde
DM
2493 }
2494 }
4df3629e 2495
b84e3bde
DM
2496 /* dump_gimple_stmt. */
2497 {
f4ebbd24 2498 temp_dump_context tmp (with_optinfo, true,
7db960c5 2499 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2500 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
3da39f52 2501 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2509 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
3da39f52
DM
2510 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2511 "dumpfile.c", expected_impl_line,
2512 "test_capture_of_dump_calls");
b84e3bde
DM
2513 }
2514 }
4df3629e 2515
b84e3bde
DM
2516 /* dump_gimple_expr_loc. */
2517 {
f4ebbd24 2518 temp_dump_context tmp (with_optinfo, true,
7db960c5 2519 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2520 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
3da39f52 2521 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2529 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
3da39f52
DM
2530 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2531 "dumpfile.c", expected_impl_line,
2532 "test_capture_of_dump_calls");
b84e3bde
DM
2533 }
2534 }
4df3629e 2535
b84e3bde
DM
2536 /* dump_gimple_expr. */
2537 {
f4ebbd24 2538 temp_dump_context tmp (with_optinfo, true,
7db960c5 2539 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2540 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
3da39f52 2541 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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);
d8010ee4 2549 ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
3da39f52
DM
2550 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2551 "dumpfile.c", expected_impl_line,
2552 "test_capture_of_dump_calls");
b84e3bde
DM
2553 }
2554 }
2555 }
2556
d8010ee4
DM
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);
3da39f52 2562 const int expected_impl_line = __LINE__ - 1;
d8010ee4
DM
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");
3da39f52
DM
2572 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2573 "dumpfile.c", expected_impl_line,
2574 "test_capture_of_dump_calls");
d8010ee4
DM
2575 }
2576 }
2577
b84e3bde
DM
2578 /* poly_int. */
2579 {
f4ebbd24 2580 temp_dump_context tmp (with_optinfo, true,
7db960c5 2581 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
b84e3bde 2582 dump_dec (MSG_NOTE, poly_int64 (42));
3da39f52 2583 const int expected_impl_line = __LINE__ - 1;
b84e3bde
DM
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");
3da39f52
DM
2592 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2593 "dumpfile.c", expected_impl_line,
2594 "test_capture_of_dump_calls");
b84e3bde
DM
2595 }
2596 }
2597
7db960c5
DM
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++)
b84e3bde 2602 {
7db960c5
DM
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
f4ebbd24 2609 temp_dump_context tmp (with_optinfo, true, dump_filter);
7db960c5
DM
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");
b84e3bde 2614 {
7db960c5
DM
2615 AUTO_DUMP_SCOPE ("outer scope", stmt);
2616 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
b84e3bde 2617 {
7db960c5
DM
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");
b84e3bde 2627 }
7db960c5 2628 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
b84e3bde 2629 }
7db960c5 2630 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
3da39f52 2631 const int expected_impl_line = __LINE__ - 1;
b84e3bde 2632
7db960c5
DM
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");
3da39f52
DM
2683 ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
2684 "dumpfile.c", expected_impl_line,
2685 "test_capture_of_dump_calls");
7db960c5
DM
2686 }
2687 }
4df3629e 2688 }
4df3629e
DM
2689
2690 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
2691 above. */
2692 {
2693 /* MSG_OPTIMIZED_LOCATIONS. */
2694 {
f4ebbd24 2695 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
4df3629e
DM
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 {
f4ebbd24 2703 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
4df3629e
DM
2704 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
2705 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
2706 OPTINFO_KIND_FAILURE);
2707 }
2708 }
c8d1534e
DM
2709
2710 /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
2711 {
f4ebbd24 2712 temp_dump_context tmp (false, true,
7db960c5 2713 MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
c8d1534e
DM
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
ed2d9d37 2731 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized: msg 4\n");
c8d1534e 2732 }
4df3629e
DM
2733}
2734
c95c5528
DM
2735static void
2736test_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
4f5b9c80
DM
2749/* Run all of the selftests within this file. */
2750
2751void
2752dumpfile_c_tests ()
2753{
2754 test_impl_location ();
4df3629e 2755 for_each_line_table_case (test_capture_of_dump_calls);
c95c5528 2756 test_pr87025 ();
4f5b9c80
DM
2757}
2758
2759} // namespace selftest
2760
2761#endif /* CHECKING_P */