]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dumpfile.c
PR libstdc++/86595 add missing noexcept
[thirdparty/gcc.git] / gcc / dumpfile.c
CommitLineData
b5f47924 1/* Dump infrastructure for optimizations and intermediate representation.
85ec4feb 2 Copyright (C) 2012-2018 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". */
b5f47924
SS
40
41/* If non-NULL, return one past-the-end of the matching SUBPART of
42 the WHOLE string. */
43#define skip_leading_substring(whole, part) \
44 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
45
1a817418 46static dump_flags_t pflags; /* current dump_flags */
b5f47924 47
1a817418 48static void dump_loc (dump_flags_t, FILE *, source_location);
29b54a9d
DM
49
50/* Current -fopt-info output stream, if any, and flags. */
51static FILE *alt_dump_file = NULL;
52static dump_flags_t alt_flags;
53
b5f47924
SS
54static FILE *dump_open_alternate_stream (struct dump_file_info *);
55
73fbfcad
SS
56/* These are currently used for communicating between passes.
57 However, instead of accessing them directly, the passes can use
58 dump_printf () for dumps. */
59FILE *dump_file = NULL;
73fbfcad 60const char *dump_file_name;
1a817418 61dump_flags_t dump_flags;
29b54a9d
DM
62bool dumps_are_enabled = false;
63
64
65/* Update the "dumps_are_enabled" global; to be called whenever dump_file
66 or alt_dump_file change. */
67
68static void
69refresh_dumps_are_enabled ()
70{
4df3629e 71 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ());
29b54a9d
DM
72}
73
74/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
75 global. */
76
77void
78set_dump_file (FILE *new_dump_file)
79{
4df3629e 80 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d
DM
81 dump_file = new_dump_file;
82 refresh_dumps_are_enabled ();
83}
84
85/* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
86 global. */
87
88static void
89set_alt_dump_file (FILE *new_alt_dump_file)
90{
4df3629e 91 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d
DM
92 alt_dump_file = new_alt_dump_file;
93 refresh_dumps_are_enabled ();
94}
73fbfcad 95
63523736 96#define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
4af78ef8
DM
97 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
98 OPTGROUP_NONE, 0, 0, num, false, false}
8264c84d 99
b5f47924
SS
100/* Table of tree dump switches. This must be consistent with the
101 TREE_DUMP_INDEX enumeration in dumpfile.h. */
102static struct dump_file_info dump_files[TDI_end] =
103{
63523736
ML
104 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
105 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
106 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
107 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
363dc72c
JJ
108 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
109 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
110 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
b4da704c 111 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
363dc72c 112#define FIRST_AUTO_NUMBERED_DUMP 1
29a50dfb 113#define FIRST_ME_AUTO_NUMBERED_DUMP 4
b5f47924 114
63523736
ML
115 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
116 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
117 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
118 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
b5f47924
SS
119};
120
b5f47924 121/* Define a name->number mapping for a dump flag value. */
4af78ef8
DM
122template <typename ValueType>
123struct kv_pair
b5f47924
SS
124{
125 const char *const name; /* the name of the value */
4af78ef8 126 const ValueType value; /* the value of the name */
b5f47924
SS
127};
128
129/* Table of dump options. This must be consistent with the TDF_* flags
130 in dumpfile.h and opt_info_options below. */
4af78ef8 131static const kv_pair<dump_flags_t> dump_options[] =
b5f47924
SS
132{
133 {"address", TDF_ADDRESS},
134 {"asmname", TDF_ASMNAME},
135 {"slim", TDF_SLIM},
136 {"raw", TDF_RAW},
137 {"graph", TDF_GRAPH},
138 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
139 | MSG_MISSED_OPTIMIZATION
140 | MSG_NOTE)},
141 {"cselib", TDF_CSELIB},
142 {"stats", TDF_STATS},
143 {"blocks", TDF_BLOCKS},
144 {"vops", TDF_VOPS},
145 {"lineno", TDF_LINENO},
146 {"uid", TDF_UID},
147 {"stmtaddr", TDF_STMTADDR},
148 {"memsyms", TDF_MEMSYMS},
b5f47924
SS
149 {"eh", TDF_EH},
150 {"alias", TDF_ALIAS},
151 {"nouid", TDF_NOUID},
152 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
153 {"scev", TDF_SCEV},
1ee62b92 154 {"gimple", TDF_GIMPLE},
56af751e 155 {"folding", TDF_FOLDING},
f14726bd
TJ
156 {"optimized", MSG_OPTIMIZED_LOCATIONS},
157 {"missed", MSG_MISSED_OPTIMIZATION},
158 {"note", MSG_NOTE},
159 {"optall", MSG_ALL},
f6b3ca5a
JJ
160 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
161 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
162 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
4af78ef8 163 {NULL, TDF_NONE}
b5f47924
SS
164};
165
2b4e6bf1
SS
166/* A subset of the dump_options table which is used for -fopt-info
167 types. This must be consistent with the MSG_* flags in dumpfile.h.
b5f47924 168 */
4af78ef8 169static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
b5f47924
SS
170{
171 {"optimized", MSG_OPTIMIZED_LOCATIONS},
172 {"missed", MSG_MISSED_OPTIMIZATION},
173 {"note", MSG_NOTE},
2b4e6bf1 174 {"all", MSG_ALL},
4af78ef8 175 {NULL, TDF_NONE}
2b4e6bf1
SS
176};
177
178/* Flags used for -fopt-info groups. */
4af78ef8 179static const kv_pair<optgroup_flags_t> optgroup_options[] =
2b4e6bf1
SS
180{
181 {"ipa", OPTGROUP_IPA},
182 {"loop", OPTGROUP_LOOP},
183 {"inline", OPTGROUP_INLINE},
fd2b8c8b 184 {"omp", OPTGROUP_OMP},
2b4e6bf1
SS
185 {"vec", OPTGROUP_VEC},
186 {"optall", OPTGROUP_ALL},
4af78ef8 187 {NULL, OPTGROUP_NONE}
b5f47924
SS
188};
189
47e0da37
DM
190gcc::dump_manager::dump_manager ():
191 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
192 m_extra_dump_files (NULL),
193 m_extra_dump_files_in_use (0),
194 m_extra_dump_files_alloced (0)
195{
196}
197
10fdd6e9
DM
198gcc::dump_manager::~dump_manager ()
199{
200 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
201 {
202 dump_file_info *dfi = &m_extra_dump_files[i];
203 /* suffix, swtch, glob are statically allocated for the entries
204 in dump_files, and for statistics, but are dynamically allocated
205 for those for passes. */
206 if (dfi->owns_strings)
207 {
208 XDELETEVEC (const_cast <char *> (dfi->suffix));
209 XDELETEVEC (const_cast <char *> (dfi->swtch));
210 XDELETEVEC (const_cast <char *> (dfi->glob));
211 }
212 /* These, if non-NULL, are always dynamically allocated. */
213 XDELETEVEC (const_cast <char *> (dfi->pfilename));
214 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
215 }
216 XDELETEVEC (m_extra_dump_files);
217}
218
b5f47924 219unsigned int
47e0da37 220gcc::dump_manager::
b5f47924 221dump_register (const char *suffix, const char *swtch, const char *glob,
4af78ef8
DM
222 dump_kind dkind, optgroup_flags_t optgroup_flags,
223 bool take_ownership)
b5f47924 224{
47e0da37 225 int num = m_next_dump++;
b5f47924 226
47e0da37 227 size_t count = m_extra_dump_files_in_use++;
b5f47924 228
47e0da37 229 if (count >= m_extra_dump_files_alloced)
b5f47924 230 {
47e0da37 231 if (m_extra_dump_files_alloced == 0)
363dc72c 232 m_extra_dump_files_alloced = 512;
b5f47924 233 else
47e0da37
DM
234 m_extra_dump_files_alloced *= 2;
235 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
236 m_extra_dump_files,
237 m_extra_dump_files_alloced);
c3684b7b
MS
238
239 /* Construct a new object in the space allocated above. */
240 new (m_extra_dump_files + count) dump_file_info ();
241 }
242 else
243 {
244 /* Zero out the already constructed object. */
245 m_extra_dump_files[count] = dump_file_info ();
b5f47924
SS
246 }
247
47e0da37
DM
248 m_extra_dump_files[count].suffix = suffix;
249 m_extra_dump_files[count].swtch = swtch;
250 m_extra_dump_files[count].glob = glob;
8264c84d 251 m_extra_dump_files[count].dkind = dkind;
47e0da37
DM
252 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
253 m_extra_dump_files[count].num = num;
10fdd6e9 254 m_extra_dump_files[count].owns_strings = take_ownership;
b5f47924
SS
255
256 return count + TDI_end;
257}
258
259
363dc72c
JJ
260/* Allow languages and middle-end to register their dumps before the
261 optimization passes. */
262
263void
264gcc::dump_manager::
265register_dumps ()
266{
267 lang_hooks.register_dumps (this);
268 /* If this assert fails, some FE registered more than
269 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
270 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
271 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
272 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
273 dump_files[TDI_original].num = m_next_dump++;
274 dump_files[TDI_gimple].num = m_next_dump++;
275 dump_files[TDI_nested].num = m_next_dump++;
276}
277
278
b5f47924
SS
279/* Return the dump_file_info for the given phase. */
280
281struct dump_file_info *
47e0da37
DM
282gcc::dump_manager::
283get_dump_file_info (int phase) const
b5f47924
SS
284{
285 if (phase < TDI_end)
286 return &dump_files[phase];
47e0da37 287 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
b5f47924
SS
288 return NULL;
289 else
47e0da37 290 return m_extra_dump_files + (phase - TDI_end);
b5f47924
SS
291}
292
799505ae
DM
293/* Locate the dump_file_info with swtch equal to SWTCH,
294 or return NULL if no such dump_file_info exists. */
295
296struct dump_file_info *
297gcc::dump_manager::
298get_dump_file_info_by_switch (const char *swtch) const
299{
300 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
01512446 301 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
799505ae
DM
302 return &m_extra_dump_files[i];
303
304 /* Not found. */
305 return NULL;
306}
307
b5f47924
SS
308
309/* Return the name of the dump file for the given phase.
799505ae
DM
310 The caller is responsible for calling free on the returned
311 buffer.
b5f47924
SS
312 If the dump is not enabled, returns NULL. */
313
314char *
47e0da37 315gcc::dump_manager::
75fdb07e 316get_dump_file_name (int phase, int part) const
b5f47924 317{
b5f47924
SS
318 struct dump_file_info *dfi;
319
320 if (phase == TDI_none)
321 return NULL;
322
323 dfi = get_dump_file_info (phase);
799505ae 324
75fdb07e 325 return get_dump_file_name (dfi, part);
799505ae
DM
326}
327
328/* Return the name of the dump file for the given dump_file_info.
329 The caller is responsible for calling free on the returned
330 buffer.
331 If the dump is not enabled, returns NULL. */
332
333char *
334gcc::dump_manager::
75fdb07e 335get_dump_file_name (struct dump_file_info *dfi, int part) const
799505ae
DM
336{
337 char dump_id[10];
338
339 gcc_assert (dfi);
340
b5f47924
SS
341 if (dfi->pstate == 0)
342 return NULL;
343
344 /* If available, use the command line dump filename. */
345 if (dfi->pfilename)
346 return xstrdup (dfi->pfilename);
347
348 if (dfi->num < 0)
349 dump_id[0] = '\0';
350 else
351 {
8264c84d
ML
352 /* (null), LANG, TREE, RTL, IPA. */
353 char suffix = " ltri"[dfi->dkind];
a529e0a6 354
8264c84d 355 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
b5f47924
SS
356 dump_id[0] = '\0';
357 }
358
75fdb07e
JH
359 if (part != -1)
360 {
361 char part_id[8];
362 snprintf (part_id, sizeof (part_id), ".%i", part);
363 return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
364 }
365 else
366 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
b5f47924
SS
367}
368
5d8b352a
NS
369/* Open a dump file called FILENAME. Some filenames are special and
370 refer to the standard streams. TRUNC indicates whether this is the
371 first open (so the file should be truncated, rather than appended).
372 An error message is emitted in the event of failure. */
373
374static FILE *
375dump_open (const char *filename, bool trunc)
376{
377 if (strcmp ("stderr", filename) == 0)
378 return stderr;
379
bd9918c4
NS
380 if (strcmp ("stdout", filename) == 0
381 || strcmp ("-", filename) == 0)
5d8b352a
NS
382 return stdout;
383
384 FILE *stream = fopen (filename, trunc ? "w" : "a");
385
386 if (!stream)
387 error ("could not open dump file %qs: %m", filename);
388 return stream;
389}
390
b5f47924
SS
391/* For a given DFI, open an alternate dump filename (which could also
392 be a standard stream such as stdout/stderr). If the alternate dump
393 file cannot be opened, return NULL. */
394
395static FILE *
396dump_open_alternate_stream (struct dump_file_info *dfi)
397{
b5f47924
SS
398 if (!dfi->alt_filename)
399 return NULL;
400
401 if (dfi->alt_stream)
402 return dfi->alt_stream;
403
5d8b352a 404 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
b5f47924 405
5d8b352a 406 if (stream)
b5f47924
SS
407 dfi->alt_state = 1;
408
409 return stream;
410}
411
4f5b9c80
DM
412/* Construct a dump_user_location_t from STMT (using its location and
413 hotness). */
414
415dump_user_location_t::dump_user_location_t (gimple *stmt)
416: m_count (), m_loc (UNKNOWN_LOCATION)
417{
418 if (stmt)
419 {
420 if (stmt->bb)
421 m_count = stmt->bb->count;
422 m_loc = gimple_location (stmt);
423 }
424}
425
426/* Construct a dump_user_location_t from an RTL instruction (using its
427 location and hotness). */
428
429dump_user_location_t::dump_user_location_t (rtx_insn *insn)
430: m_count (), m_loc (UNKNOWN_LOCATION)
431{
432 if (insn)
433 {
434 basic_block bb = BLOCK_FOR_INSN (insn);
435 if (bb)
436 m_count = bb->count;
437 m_loc = INSN_LOCATION (insn);
438 }
439}
440
441/* Construct from a function declaration. This one requires spelling out
442 to avoid accidentally constructing from other kinds of tree. */
443
444dump_user_location_t
445dump_user_location_t::from_function_decl (tree fndecl)
446{
447 gcc_assert (fndecl);
448
449 // FIXME: profile count for function?
450 return dump_user_location_t (profile_count (),
451 DECL_SOURCE_LOCATION (fndecl));
452}
453
b5f47924
SS
454/* Print source location on DFILE if enabled. */
455
4f5b9c80 456static void
1a817418 457dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
b5f47924 458{
b5f47924
SS
459 if (dump_kind)
460 {
502498d5 461 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
e645e942 462 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
103ff0d6 463 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
a3d7af04 464 else if (current_function_decl)
e645e942 465 fprintf (dfile, "%s:%d:%d: note: ",
b5f47924 466 DECL_SOURCE_FILE (current_function_decl),
103ff0d6
TJ
467 DECL_SOURCE_LINE (current_function_decl),
468 DECL_SOURCE_COLUMN (current_function_decl));
6475e077
DM
469 /* Indentation based on scope depth. */
470 fprintf (dfile, "%*s", get_dump_scope_depth (), "");
b5f47924
SS
471 }
472}
473
4df3629e
DM
474/* Implementation of dump_context member functions. */
475
476/* dump_context's dtor. */
477
478dump_context::~dump_context ()
479{
480 delete m_pending;
481}
482
b5f47924
SS
483/* Dump gimple statement GS with SPC indentation spaces and
484 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
485
486void
4df3629e
DM
487dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
488 dump_flags_t extra_dump_flags,
489 gimple *gs, int spc)
b5f47924
SS
490{
491 if (dump_file && (dump_kind & pflags))
492 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
493
494 if (alt_dump_file && (dump_kind & alt_flags))
495 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
4df3629e
DM
496
497 if (optinfo_enabled_p ())
498 {
499 optinfo &info = ensure_pending_optinfo ();
500 info.handle_dump_file_kind (dump_kind);
501 info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
502 }
b5f47924
SS
503}
504
505/* Similar to dump_gimple_stmt, except additionally print source location. */
506
507void
4df3629e
DM
508dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
509 const dump_location_t &loc,
510 dump_flags_t extra_dump_flags,
511 gimple *gs, int spc)
b5f47924 512{
4f5b9c80 513 location_t srcloc = loc.get_location_t ();
b5f47924
SS
514 if (dump_file && (dump_kind & pflags))
515 {
4f5b9c80 516 dump_loc (dump_kind, dump_file, srcloc);
b5f47924
SS
517 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
518 }
519
520 if (alt_dump_file && (dump_kind & alt_flags))
521 {
4f5b9c80 522 dump_loc (dump_kind, alt_dump_file, srcloc);
b5f47924
SS
523 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
524 }
4df3629e
DM
525
526 if (optinfo_enabled_p ())
527 {
528 optinfo &info = begin_next_optinfo (loc);
529 info.handle_dump_file_kind (dump_kind);
530 info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
531 }
b5f47924
SS
532}
533
30f502ed
RB
534/* Dump gimple statement GS with SPC indentation spaces and
535 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
536 Do not terminate with a newline or semicolon. */
537
538void
4df3629e
DM
539dump_context::dump_gimple_expr (dump_flags_t dump_kind,
540 dump_flags_t extra_dump_flags,
541 gimple *gs, int spc)
30f502ed
RB
542{
543 if (dump_file && (dump_kind & pflags))
544 print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
545
546 if (alt_dump_file && (dump_kind & alt_flags))
547 print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
4df3629e
DM
548
549 if (optinfo_enabled_p ())
550 {
551 optinfo &info = ensure_pending_optinfo ();
552 info.handle_dump_file_kind (dump_kind);
553 info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
554 }
30f502ed
RB
555}
556
557/* Similar to dump_gimple_expr, except additionally print source location. */
558
559void
4df3629e
DM
560dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind,
561 const dump_location_t &loc,
562 dump_flags_t extra_dump_flags,
563 gimple *gs,
564 int spc)
30f502ed
RB
565{
566 location_t srcloc = loc.get_location_t ();
567 if (dump_file && (dump_kind & pflags))
568 {
569 dump_loc (dump_kind, dump_file, srcloc);
570 print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
571 }
572
573 if (alt_dump_file && (dump_kind & alt_flags))
574 {
575 dump_loc (dump_kind, alt_dump_file, srcloc);
576 print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
577 }
4df3629e
DM
578
579 if (optinfo_enabled_p ())
580 {
581 optinfo &info = begin_next_optinfo (loc);
582 info.handle_dump_file_kind (dump_kind);
583 info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
584 }
30f502ed
RB
585}
586
587
b5f47924
SS
588/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
589 DUMP_KIND is enabled. */
590
591void
4df3629e
DM
592dump_context::dump_generic_expr (dump_flags_t dump_kind,
593 dump_flags_t extra_dump_flags,
594 tree t)
b5f47924
SS
595{
596 if (dump_file && (dump_kind & pflags))
597 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
598
599 if (alt_dump_file && (dump_kind & alt_flags))
600 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
4df3629e
DM
601
602 if (optinfo_enabled_p ())
603 {
604 optinfo &info = ensure_pending_optinfo ();
605 info.handle_dump_file_kind (dump_kind);
606 info.add_tree (t, dump_flags | extra_dump_flags);
607 }
b5f47924
SS
608}
609
d7259673
DM
610
611/* Similar to dump_generic_expr, except additionally print the source
612 location. */
613
614void
4df3629e
DM
615dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
616 const dump_location_t &loc,
617 dump_flags_t extra_dump_flags,
618 tree t)
d7259673
DM
619{
620 location_t srcloc = loc.get_location_t ();
621 if (dump_file && (dump_kind & pflags))
622 {
623 dump_loc (dump_kind, dump_file, srcloc);
624 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
625 }
626
627 if (alt_dump_file && (dump_kind & alt_flags))
628 {
629 dump_loc (dump_kind, alt_dump_file, srcloc);
630 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
631 }
4df3629e
DM
632
633 if (optinfo_enabled_p ())
634 {
635 optinfo &info = begin_next_optinfo (loc);
636 info.handle_dump_file_kind (dump_kind);
637 info.add_tree (t, dump_flags | extra_dump_flags);
638 }
d7259673
DM
639}
640
b5f47924
SS
641/* Output a formatted message using FORMAT on appropriate dump streams. */
642
643void
4df3629e
DM
644dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
645 va_list ap)
b5f47924
SS
646{
647 if (dump_file && (dump_kind & pflags))
648 {
4df3629e
DM
649 va_list aq;
650 va_copy (aq, ap);
651 vfprintf (dump_file, format, aq);
652 va_end (aq);
b5f47924
SS
653 }
654
655 if (alt_dump_file && (dump_kind & alt_flags))
656 {
4df3629e
DM
657 va_list aq;
658 va_copy (aq, ap);
659 vfprintf (alt_dump_file, format, aq);
660 va_end (aq);
661 }
662
663 if (optinfo_enabled_p ())
664 {
665 optinfo &info = ensure_pending_optinfo ();
666 va_list aq;
667 va_copy (aq, ap);
668 info.add_printf_va (format, aq);
669 va_end (aq);
b5f47924
SS
670 }
671}
672
4df3629e
DM
673/* Similar to dump_printf, except source location is also printed, and
674 dump location captured. */
b5f47924
SS
675
676void
4df3629e
DM
677dump_context::dump_printf_loc_va (dump_flags_t dump_kind,
678 const dump_location_t &loc,
679 const char *format, va_list ap)
b5f47924 680{
4f5b9c80 681 location_t srcloc = loc.get_location_t ();
4df3629e 682
b5f47924
SS
683 if (dump_file && (dump_kind & pflags))
684 {
4f5b9c80 685 dump_loc (dump_kind, dump_file, srcloc);
4df3629e
DM
686 va_list aq;
687 va_copy (aq, ap);
688 vfprintf (dump_file, format, aq);
689 va_end (aq);
b5f47924
SS
690 }
691
692 if (alt_dump_file && (dump_kind & alt_flags))
693 {
4f5b9c80 694 dump_loc (dump_kind, alt_dump_file, srcloc);
4df3629e
DM
695 va_list aq;
696 va_copy (aq, ap);
697 vfprintf (alt_dump_file, format, aq);
698 va_end (aq);
699 }
700
701 if (optinfo_enabled_p ())
702 {
703 optinfo &info = begin_next_optinfo (loc);
704 info.handle_dump_file_kind (dump_kind);
705 va_list aq;
706 va_copy (aq, ap);
707 info.add_printf_va (format, aq);
708 va_end (aq);
b5f47924
SS
709 }
710}
711
dc3f3805
RS
712/* Output VALUE in decimal to appropriate dump streams. */
713
714template<unsigned int N, typename C>
715void
4df3629e 716dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
dc3f3805
RS
717{
718 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
719 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
720 if (dump_file && (dump_kind & pflags))
721 print_dec (value, dump_file, sgn);
722
723 if (alt_dump_file && (dump_kind & alt_flags))
724 print_dec (value, alt_dump_file, sgn);
4df3629e
DM
725
726 if (optinfo_enabled_p ())
727 {
728 optinfo &info = ensure_pending_optinfo ();
729 info.handle_dump_file_kind (dump_kind);
730 info.add_poly_int<N,C> (value);
731 }
732}
733
734/* Output the name of NODE on appropriate dump streams. */
735
736void
737dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
738{
739 if (dump_file && (dump_kind & pflags))
740 fprintf (dump_file, "%s", node->dump_name ());
741
742 if (alt_dump_file && (dump_kind & alt_flags))
743 fprintf (alt_dump_file, "%s", node->dump_name ());
744
745 if (optinfo_enabled_p ())
746 {
747 optinfo &info = ensure_pending_optinfo ();
748 info.handle_dump_file_kind (dump_kind);
749 info.add_symtab_node (node);
750 }
751}
752
753/* Get the current dump scope-nesting depth.
754 For use by -fopt-info (for showing nesting via indentation). */
755
756unsigned int
757dump_context::get_scope_depth () const
758{
759 return m_scope_depth;
760}
761
762/* Push a nested dump scope.
763 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
764 destination, if any.
765 Emit a "scope" optinfo if optinfos are enabled.
766 Increment the scope depth. */
767
768void
769dump_context::begin_scope (const char *name, const dump_location_t &loc)
770{
771 /* Specialcase, to avoid going through dump_printf_loc,
772 so that we can create a optinfo of kind OPTINFO_KIND_SCOPE. */
773
774 if (dump_file)
775 {
776 dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
777 fprintf (dump_file, "=== %s ===\n", name);
778 }
779
780 if (alt_dump_file)
781 {
782 dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
783 fprintf (alt_dump_file, "=== %s ===\n", name);
784 }
785
786 if (optinfo_enabled_p ())
787 {
788 end_any_optinfo ();
789 optinfo info (loc, OPTINFO_KIND_SCOPE, current_pass);
790 info.add_printf ("=== %s ===", name);
791 info.emit ();
792 }
793
794 m_scope_depth++;
795}
796
797/* Pop a nested dump scope. */
798
799void
800dump_context::end_scope ()
801{
802 end_any_optinfo ();
803 m_scope_depth--;
804}
805
806/* Return the optinfo currently being accumulated, creating one if
807 necessary. */
808
809optinfo &
810dump_context::ensure_pending_optinfo ()
811{
812 if (!m_pending)
813 return begin_next_optinfo (dump_location_t (dump_user_location_t ()));
814 return *m_pending;
815}
816
817/* Start a new optinfo and return it, ending any optinfo that was already
818 accumulated. */
819
820optinfo &
821dump_context::begin_next_optinfo (const dump_location_t &loc)
822{
823 end_any_optinfo ();
824 gcc_assert (m_pending == NULL);
825 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
826 return *m_pending;
827}
828
829/* End any optinfo that has been accumulated within this context; emitting
830 it to any destinations as appropriate - though none have currently been
831 implemented. */
832
833void
834dump_context::end_any_optinfo ()
835{
836 if (m_pending)
837 m_pending->emit ();
838 delete m_pending;
839 m_pending = NULL;
840}
841
842/* The current singleton dump_context, and its default. */
843
844dump_context *dump_context::s_current = &dump_context::s_default;
845dump_context dump_context::s_default;
846
847/* Implementation of dump_* API calls, calling into dump_context
848 member functions. */
849
850/* Dump gimple statement GS with SPC indentation spaces and
851 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
852
853void
854dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
855 gimple *gs, int spc)
856{
857 dump_context::get ().dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
858}
859
860/* Similar to dump_gimple_stmt, except additionally print source location. */
861
862void
863dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
864 dump_flags_t extra_dump_flags, gimple *gs, int spc)
865{
866 dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc, extra_dump_flags,
867 gs, spc);
868}
869
870/* Dump gimple statement GS with SPC indentation spaces and
871 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
872 Do not terminate with a newline or semicolon. */
873
874void
875dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
876 gimple *gs, int spc)
877{
878 dump_context::get ().dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
879}
880
881/* Similar to dump_gimple_expr, except additionally print source location. */
882
883void
884dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
885 dump_flags_t extra_dump_flags, gimple *gs, int spc)
886{
887 dump_context::get ().dump_gimple_expr_loc (dump_kind, loc, extra_dump_flags,
888 gs, spc);
889}
890
891/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
892 DUMP_KIND is enabled. */
893
894void
895dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
896 tree t)
897{
898 dump_context::get ().dump_generic_expr (dump_kind, extra_dump_flags, t);
899}
900
901/* Similar to dump_generic_expr, except additionally print the source
902 location. */
903
904void
905dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
906 dump_flags_t extra_dump_flags, tree t)
907{
908 dump_context::get ().dump_generic_expr_loc (dump_kind, loc, extra_dump_flags,
909 t);
910}
911
912/* Output a formatted message using FORMAT on appropriate dump streams. */
913
914void
915dump_printf (dump_flags_t dump_kind, const char *format, ...)
916{
917 va_list ap;
918 va_start (ap, format);
919 dump_context::get ().dump_printf_va (dump_kind, format, ap);
920 va_end (ap);
921}
922
923/* Similar to dump_printf, except source location is also printed, and
924 dump location captured. */
925
926void
927dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
928 const char *format, ...)
929{
930 va_list ap;
931 va_start (ap, format);
932 dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, ap);
933 va_end (ap);
934}
935
936/* Output VALUE in decimal to appropriate dump streams. */
937
938template<unsigned int N, typename C>
939void
940dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
941{
942 dump_context::get ().dump_dec (dump_kind, value);
dc3f3805
RS
943}
944
4af78ef8
DM
945template void dump_dec (dump_flags_t, const poly_uint16 &);
946template void dump_dec (dump_flags_t, const poly_int64 &);
947template void dump_dec (dump_flags_t, const poly_uint64 &);
948template void dump_dec (dump_flags_t, const poly_offset_int &);
949template void dump_dec (dump_flags_t, const poly_widest_int &);
dc3f3805 950
370c2ebe
RS
951void
952dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
953{
954 if (dump_file && (dump_kind & pflags))
955 print_dec (value, dump_file, sgn);
956
957 if (alt_dump_file && (dump_kind & alt_flags))
958 print_dec (value, alt_dump_file, sgn);
959}
960
961/* Output VALUE in hexadecimal to appropriate dump streams. */
962
963void
964dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
965{
966 if (dump_file && (dump_kind & pflags))
967 print_hex (value, dump_file);
968
969 if (alt_dump_file && (dump_kind & alt_flags))
970 print_hex (value, alt_dump_file);
971}
972
4df3629e
DM
973/* Emit and delete the currently pending optinfo, if there is one,
974 without the caller needing to know about class dump_context. */
975
976void
977dumpfile_ensure_any_optinfo_are_flushed ()
978{
979 dump_context::get().end_any_optinfo ();
980}
981
982/* Output the name of NODE on appropriate dump streams. */
6475e077 983
4df3629e
DM
984void
985dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
986{
987 dump_context::get ().dump_symtab_node (dump_kind, node);
988}
6475e077
DM
989
990/* Get the current dump scope-nesting depth.
4df3629e 991 For use by -fopt-info (for showing nesting via indentation). */
6475e077
DM
992
993unsigned int
994get_dump_scope_depth ()
995{
4df3629e 996 return dump_context::get ().get_scope_depth ();
6475e077
DM
997}
998
999/* Push a nested dump scope.
1000 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1001 destination, if any.
4df3629e 1002 Emit a "scope" opinfo if optinfos are enabled.
6475e077
DM
1003 Increment the scope depth. */
1004
1005void
1006dump_begin_scope (const char *name, const dump_location_t &loc)
1007{
4df3629e 1008 dump_context::get ().begin_scope (name, loc);
6475e077
DM
1009}
1010
1011/* Pop a nested dump scope. */
1012
1013void
1014dump_end_scope ()
1015{
4df3629e 1016 dump_context::get ().end_scope ();
6475e077
DM
1017}
1018
b5f47924
SS
1019/* Start a dump for PHASE. Store user-supplied dump flags in
1020 *FLAG_PTR. Return the number of streams opened. Set globals
1021 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
2b4e6bf1
SS
1022 set dump_flags appropriately for both pass dump stream and
1023 -fopt-info stream. */
b5f47924
SS
1024
1025int
47e0da37 1026gcc::dump_manager::
1a817418 1027dump_start (int phase, dump_flags_t *flag_ptr)
b5f47924
SS
1028{
1029 int count = 0;
1030 char *name;
1031 struct dump_file_info *dfi;
1032 FILE *stream;
74911c3c 1033 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1034 return 0;
1035
1036 dfi = get_dump_file_info (phase);
1037 name = get_dump_file_name (phase);
1038 if (name)
1039 {
5d8b352a
NS
1040 stream = dump_open (name, dfi->pstate < 0);
1041 if (stream)
b5f47924
SS
1042 {
1043 dfi->pstate = 1;
1044 count++;
1045 }
1046 free (name);
1047 dfi->pstream = stream;
29b54a9d 1048 set_dump_file (dfi->pstream);
b5f47924 1049 /* Initialize current dump flags. */
8264c84d 1050 pflags = dfi->pflags;
b5f47924
SS
1051 }
1052
1053 stream = dump_open_alternate_stream (dfi);
1054 if (stream)
1055 {
1056 dfi->alt_stream = stream;
1057 count++;
29b54a9d 1058 set_alt_dump_file (dfi->alt_stream);
2b4e6bf1 1059 /* Initialize current -fopt-info flags. */
8264c84d 1060 alt_flags = dfi->alt_flags;
b5f47924
SS
1061 }
1062
1063 if (flag_ptr)
1064 *flag_ptr = dfi->pflags;
1065
1066 return count;
1067}
1068
1069/* Finish a tree dump for PHASE and close associated dump streams. Also
1070 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
1071
1072void
47e0da37 1073gcc::dump_manager::
b5f47924
SS
1074dump_finish (int phase)
1075{
1076 struct dump_file_info *dfi;
1077
1078 if (phase < 0)
1079 return;
1080 dfi = get_dump_file_info (phase);
5d8b352a 1081 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
b5f47924
SS
1082 fclose (dfi->pstream);
1083
5d8b352a 1084 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
b5f47924
SS
1085 fclose (dfi->alt_stream);
1086
1087 dfi->alt_stream = NULL;
1088 dfi->pstream = NULL;
29b54a9d
DM
1089 set_dump_file (NULL);
1090 set_alt_dump_file (NULL);
4af78ef8
DM
1091 dump_flags = TDF_NONE;
1092 alt_flags = TDF_NONE;
1093 pflags = TDF_NONE;
b5f47924
SS
1094}
1095
1096/* Begin a tree dump for PHASE. Stores any user supplied flag in
1097 *FLAG_PTR and returns a stream to write to. If the dump is not
1098 enabled, returns NULL.
75fdb07e
JH
1099 PART can be used for dump files which should be split to multiple
1100 parts. PART == -1 indicates dump file with no parts.
1101 If PART is -1, multiple calls will reopen and append to the dump file. */
b5f47924
SS
1102
1103FILE *
75fdb07e 1104dump_begin (int phase, dump_flags_t *flag_ptr, int part)
47e0da37 1105{
75fdb07e 1106 return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
47e0da37
DM
1107}
1108
1109FILE *
1110gcc::dump_manager::
75fdb07e 1111dump_begin (int phase, dump_flags_t *flag_ptr, int part)
b5f47924
SS
1112{
1113 char *name;
1114 struct dump_file_info *dfi;
1115 FILE *stream;
1116
74911c3c 1117 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1118 return NULL;
1119
75fdb07e 1120 name = get_dump_file_name (phase, part);
b5f47924
SS
1121 if (!name)
1122 return NULL;
1123 dfi = get_dump_file_info (phase);
1124
75fdb07e
JH
1125 /* We do not support re-opening of dump files with parts. This would require
1126 tracking pstate per part of the dump file. */
1127 stream = dump_open (name, part != -1 || dfi->pstate < 0);
5d8b352a 1128 if (stream)
b5f47924
SS
1129 dfi->pstate = 1;
1130 free (name);
1131
1132 if (flag_ptr)
1133 *flag_ptr = dfi->pflags;
1134
1135 /* Initialize current flags */
1136 pflags = dfi->pflags;
1137 return stream;
1138}
1139
1140/* Returns nonzero if dump PHASE is enabled for at least one stream.
1141 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1142 any phase. */
1143
47e0da37
DM
1144int
1145gcc::dump_manager::
1146dump_phase_enabled_p (int phase) const
b5f47924
SS
1147{
1148 if (phase == TDI_tree_all)
1149 {
1150 size_t i;
1151 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1152 if (dump_files[i].pstate || dump_files[i].alt_state)
1153 return 1;
47e0da37
DM
1154 for (i = 0; i < m_extra_dump_files_in_use; i++)
1155 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
b5f47924
SS
1156 return 1;
1157 return 0;
1158 }
1159 else
1160 {
1161 struct dump_file_info *dfi = get_dump_file_info (phase);
1162 return dfi->pstate || dfi->alt_state;
1163 }
1164}
1165
1166/* Returns nonzero if tree dump PHASE has been initialized. */
1167
1168int
47e0da37
DM
1169gcc::dump_manager::
1170dump_initialized_p (int phase) const
b5f47924
SS
1171{
1172 struct dump_file_info *dfi = get_dump_file_info (phase);
1173 return dfi->pstate > 0 || dfi->alt_state > 0;
1174}
1175
1176/* Returns the switch name of PHASE. */
1177
1178const char *
1179dump_flag_name (int phase)
47e0da37
DM
1180{
1181 return g->get_dumps ()->dump_flag_name (phase);
1182}
1183
1184const char *
1185gcc::dump_manager::
1186dump_flag_name (int phase) const
b5f47924
SS
1187{
1188 struct dump_file_info *dfi = get_dump_file_info (phase);
1189 return dfi->swtch;
1190}
1191
1192/* Finish a tree dump for PHASE. STREAM is the stream created by
1193 dump_begin. */
1194
1195void
1196dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
1197{
1198 if (stream != stderr && stream != stdout)
1199 fclose (stream);
1200}
1201
1202/* Enable all tree dumps with FLAGS on FILENAME. Return number of
1203 enabled tree dumps. */
1204
47e0da37
DM
1205int
1206gcc::dump_manager::
8264c84d 1207dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
b5f47924 1208{
b5f47924
SS
1209 int n = 0;
1210 size_t i;
1211
1212 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1213 {
8264c84d 1214 if ((dump_files[i].dkind == dkind))
b5f47924
SS
1215 {
1216 const char *old_filename = dump_files[i].pfilename;
1217 dump_files[i].pstate = -1;
1218 dump_files[i].pflags |= flags;
1219 n++;
1220 /* Override the existing filename. */
1221 if (filename)
1222 {
1223 dump_files[i].pfilename = xstrdup (filename);
1224 /* Since it is a command-line provided file, which is
1225 common to all the phases, use it in append mode. */
1226 dump_files[i].pstate = 1;
1227 }
1228 if (old_filename && filename != old_filename)
1229 free (CONST_CAST (char *, old_filename));
1230 }
1231 }
1232
47e0da37 1233 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 1234 {
8264c84d 1235 if ((m_extra_dump_files[i].dkind == dkind))
b5f47924 1236 {
47e0da37
DM
1237 const char *old_filename = m_extra_dump_files[i].pfilename;
1238 m_extra_dump_files[i].pstate = -1;
1239 m_extra_dump_files[i].pflags |= flags;
b5f47924
SS
1240 n++;
1241 /* Override the existing filename. */
1242 if (filename)
1243 {
47e0da37 1244 m_extra_dump_files[i].pfilename = xstrdup (filename);
b5f47924
SS
1245 /* Since it is a command-line provided file, which is
1246 common to all the phases, use it in append mode. */
47e0da37 1247 m_extra_dump_files[i].pstate = 1;
b5f47924
SS
1248 }
1249 if (old_filename && filename != old_filename)
1250 free (CONST_CAST (char *, old_filename));
1251 }
1252 }
1253
1254 return n;
1255}
1256
2b4e6bf1
SS
1257/* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1258 Enable dumps with FLAGS on FILENAME. Return the number of enabled
1259 dumps. */
b5f47924 1260
47e0da37
DM
1261int
1262gcc::dump_manager::
4af78ef8 1263opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1a817418 1264 const char *filename)
b5f47924
SS
1265{
1266 int n = 0;
1267 size_t i;
1268
1269 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1270 {
2b4e6bf1 1271 if ((dump_files[i].optgroup_flags & optgroup_flags))
b5f47924
SS
1272 {
1273 const char *old_filename = dump_files[i].alt_filename;
1274 /* Since this file is shared among different passes, it
1275 should be opened in append mode. */
1276 dump_files[i].alt_state = 1;
1277 dump_files[i].alt_flags |= flags;
1278 n++;
1279 /* Override the existing filename. */
1280 if (filename)
1281 dump_files[i].alt_filename = xstrdup (filename);
1282 if (old_filename && filename != old_filename)
1283 free (CONST_CAST (char *, old_filename));
1284 }
1285 }
1286
47e0da37 1287 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 1288 {
47e0da37 1289 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
b5f47924 1290 {
47e0da37 1291 const char *old_filename = m_extra_dump_files[i].alt_filename;
b5f47924
SS
1292 /* Since this file is shared among different passes, it
1293 should be opened in append mode. */
47e0da37
DM
1294 m_extra_dump_files[i].alt_state = 1;
1295 m_extra_dump_files[i].alt_flags |= flags;
b5f47924
SS
1296 n++;
1297 /* Override the existing filename. */
1298 if (filename)
47e0da37 1299 m_extra_dump_files[i].alt_filename = xstrdup (filename);
b5f47924
SS
1300 if (old_filename && filename != old_filename)
1301 free (CONST_CAST (char *, old_filename));
1302 }
1303 }
1304
1305 return n;
1306}
1307
1308/* Parse ARG as a dump switch. Return nonzero if it is, and store the
1309 relevant details in the dump_files array. */
1310
47e0da37
DM
1311int
1312gcc::dump_manager::
b5f47924
SS
1313dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1314{
1315 const char *option_value;
1316 const char *ptr;
1a817418 1317 dump_flags_t flags;
b5f47924
SS
1318
1319 if (doglob && !dfi->glob)
1320 return 0;
1321
1322 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1323 if (!option_value)
1324 return 0;
1325
1326 if (*option_value && *option_value != '-' && *option_value != '=')
1327 return 0;
1328
1329 ptr = option_value;
4af78ef8 1330 flags = TDF_NONE;
b5f47924
SS
1331
1332 while (*ptr)
1333 {
4af78ef8 1334 const struct kv_pair<dump_flags_t> *option_ptr;
b5f47924
SS
1335 const char *end_ptr;
1336 const char *eq_ptr;
1337 unsigned length;
1338
1339 while (*ptr == '-')
1340 ptr++;
1341 end_ptr = strchr (ptr, '-');
1342 eq_ptr = strchr (ptr, '=');
1343
1344 if (eq_ptr && !end_ptr)
1345 end_ptr = eq_ptr;
1346
1347 if (!end_ptr)
1348 end_ptr = ptr + strlen (ptr);
1349 length = end_ptr - ptr;
1350
1351 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1352 if (strlen (option_ptr->name) == length
1353 && !memcmp (option_ptr->name, ptr, length))
1354 {
1355 flags |= option_ptr->value;
1356 goto found;
1357 }
1358
1359 if (*ptr == '=')
1360 {
1361 /* Interpret rest of the argument as a dump filename. This
1362 filename overrides other command line filenames. */
1363 if (dfi->pfilename)
1364 free (CONST_CAST (char *, dfi->pfilename));
1365 dfi->pfilename = xstrdup (ptr + 1);
1366 break;
1367 }
1368 else
1369 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1370 length, ptr, dfi->swtch);
1371 found:;
1372 ptr = end_ptr;
1373 }
1374
1375 dfi->pstate = -1;
1376 dfi->pflags |= flags;
1377
1378 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1379 known dumps. */
1380 if (dfi->suffix == NULL)
8264c84d 1381 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
b5f47924
SS
1382
1383 return 1;
1384}
1385
1386int
47e0da37 1387gcc::dump_manager::
b5f47924
SS
1388dump_switch_p (const char *arg)
1389{
1390 size_t i;
1391 int any = 0;
1392
1393 for (i = TDI_none + 1; i != TDI_end; i++)
1394 any |= dump_switch_p_1 (arg, &dump_files[i], false);
1395
1396 /* Don't glob if we got a hit already */
1397 if (!any)
1398 for (i = TDI_none + 1; i != TDI_end; i++)
1399 any |= dump_switch_p_1 (arg, &dump_files[i], true);
1400
47e0da37
DM
1401 for (i = 0; i < m_extra_dump_files_in_use; i++)
1402 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
b5f47924
SS
1403
1404 if (!any)
47e0da37
DM
1405 for (i = 0; i < m_extra_dump_files_in_use; i++)
1406 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
b5f47924
SS
1407
1408
1409 return any;
1410}
1411
2b4e6bf1
SS
1412/* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1413 and filename. Return non-zero if it is a recognized switch. */
b5f47924
SS
1414
1415static int
4af78ef8
DM
1416opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
1417 optgroup_flags_t *optgroup_flags, char **filename)
b5f47924
SS
1418{
1419 const char *option_value;
1420 const char *ptr;
1421
1422 option_value = arg;
1423 ptr = option_value;
1424
1425 *filename = NULL;
4af78ef8
DM
1426 *flags = TDF_NONE;
1427 *optgroup_flags = OPTGROUP_NONE;
b5f47924
SS
1428
1429 if (!ptr)
2b4e6bf1 1430 return 1; /* Handle '-fopt-info' without any additional options. */
b5f47924
SS
1431
1432 while (*ptr)
1433 {
b5f47924
SS
1434 const char *end_ptr;
1435 const char *eq_ptr;
1436 unsigned length;
1437
1438 while (*ptr == '-')
1439 ptr++;
1440 end_ptr = strchr (ptr, '-');
1441 eq_ptr = strchr (ptr, '=');
1442
1443 if (eq_ptr && !end_ptr)
1444 end_ptr = eq_ptr;
1445
1446 if (!end_ptr)
1447 end_ptr = ptr + strlen (ptr);
1448 length = end_ptr - ptr;
1449
4af78ef8
DM
1450 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
1451 option_ptr->name; option_ptr++)
b5f47924
SS
1452 if (strlen (option_ptr->name) == length
1453 && !memcmp (option_ptr->name, ptr, length))
1454 {
1455 *flags |= option_ptr->value;
1456 goto found;
1457 }
1458
4af78ef8
DM
1459 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
1460 option_ptr->name; option_ptr++)
2b4e6bf1
SS
1461 if (strlen (option_ptr->name) == length
1462 && !memcmp (option_ptr->name, ptr, length))
1463 {
1464 *optgroup_flags |= option_ptr->value;
1465 goto found;
1466 }
1467
b5f47924
SS
1468 if (*ptr == '=')
1469 {
1470 /* Interpret rest of the argument as a dump filename. This
1471 filename overrides other command line filenames. */
1472 *filename = xstrdup (ptr + 1);
1473 break;
1474 }
1475 else
2b4e6bf1
SS
1476 {
1477 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1478 length, ptr, arg);
1479 return 0;
1480 }
b5f47924
SS
1481 found:;
1482 ptr = end_ptr;
1483 }
1484
1485 return 1;
1486}
1487
1488/* Return non-zero if ARG is a recognized switch for
1489 -fopt-info. Return zero otherwise. */
1490
1491int
1492opt_info_switch_p (const char *arg)
1493{
1a817418 1494 dump_flags_t flags;
4af78ef8 1495 optgroup_flags_t optgroup_flags;
b5f47924 1496 char *filename;
2b4e6bf1 1497 static char *file_seen = NULL;
47e0da37 1498 gcc::dump_manager *dumps = g->get_dumps ();
b5f47924 1499
2b4e6bf1
SS
1500 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
1501 return 0;
b5f47924
SS
1502
1503 if (!filename)
1504 filename = xstrdup ("stderr");
2b4e6bf1
SS
1505
1506 /* Bail out if a different filename has been specified. */
1507 if (file_seen && strcmp (file_seen, filename))
1508 {
1509 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1510 arg);
1511 return 1;
1512 }
1513
1514 file_seen = xstrdup (filename);
b5f47924 1515 if (!flags)
5d318fd4 1516 flags = MSG_OPTIMIZED_LOCATIONS;
2b4e6bf1
SS
1517 if (!optgroup_flags)
1518 optgroup_flags = OPTGROUP_ALL;
b5f47924 1519
47e0da37 1520 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
b5f47924
SS
1521}
1522
b5f47924
SS
1523/* Print basic block on the dump streams. */
1524
1525void
4af78ef8 1526dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
b5f47924
SS
1527{
1528 if (dump_file && (dump_kind & pflags))
1529 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1530 if (alt_dump_file && (dump_kind & alt_flags))
1531 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1532}
1533
c24e924f
NS
1534/* Dump FUNCTION_DECL FN as tree dump PHASE. */
1535
1536void
1537dump_function (int phase, tree fn)
1538{
1539 FILE *stream;
1a817418 1540 dump_flags_t flags;
c24e924f
NS
1541
1542 stream = dump_begin (phase, &flags);
1543 if (stream)
1544 {
1545 dump_function_to_file (fn, stream, flags);
1546 dump_end (phase, stream);
1547 }
1548}
1549
b5f47924
SS
1550/* Print information from the combine pass on dump_file. */
1551
1552void
1553print_combine_total_stats (void)
1554{
1555 if (dump_file)
1556 dump_combine_total_stats (dump_file);
1557}
1558
1559/* Enable RTL dump for all the RTL passes. */
1560
1561bool
1562enable_rtl_dump_file (void)
1563{
47e0da37
DM
1564 gcc::dump_manager *dumps = g->get_dumps ();
1565 int num_enabled =
8264c84d
ML
1566 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1567 NULL);
47e0da37 1568 return num_enabled > 0;
b5f47924 1569}
4f5b9c80
DM
1570
1571#if CHECKING_P
1572
4df3629e
DM
1573/* temp_dump_context's ctor. Temporarily override the dump_context
1574 (to forcibly enable optinfo-generation). */
1575
1576temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo)
1577: m_context (),
1578 m_saved (&dump_context ().get ())
1579{
1580 dump_context::s_current = &m_context;
1581 m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
1582}
1583
1584/* temp_dump_context's dtor. Restore the saved dump_context. */
1585
1586temp_dump_context::~temp_dump_context ()
1587{
1588 dump_context::s_current = m_saved;
1589}
1590
4f5b9c80
DM
1591namespace selftest {
1592
1593/* Verify that the dump_location_t constructors capture the source location
1594 at which they were called (provided that the build compiler is sufficiently
1595 recent). */
1596
1597static void
1598test_impl_location ()
1599{
1600#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
1601 /* Default ctor. */
1602 {
1603 dump_location_t loc;
1604 const int expected_line = __LINE__ - 1;
1605 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1606 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1607 }
1608
1609 /* Constructing from a gimple. */
1610 {
1611 dump_location_t loc ((gimple *)NULL);
1612 const int expected_line = __LINE__ - 1;
1613 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1614 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1615 }
1616
1617 /* Constructing from an rtx_insn. */
1618 {
1619 dump_location_t loc ((rtx_insn *)NULL);
1620 const int expected_line = __LINE__ - 1;
1621 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1622 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1623 }
1624#endif
1625}
1626
4df3629e
DM
1627/* Verify that ITEM has the expected values. */
1628
1629static void
1630verify_item (const location &loc,
1631 const optinfo_item *item,
1632 enum optinfo_item_kind expected_kind,
1633 location_t expected_location,
1634 const char *expected_text)
1635{
1636 ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
1637 ASSERT_EQ_AT (loc, item->get_location (), expected_location);
1638 ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
1639}
1640
1641/* Verify that ITEM is a text item, with EXPECTED_TEXT. */
1642
1643#define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
1644 SELFTEST_BEGIN_STMT \
1645 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
1646 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \
1647 SELFTEST_END_STMT
1648
1649/* Verify that ITEM is a tree item, with the expected values. */
1650
1651#define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1652 SELFTEST_BEGIN_STMT \
1653 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
1654 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
1655 SELFTEST_END_STMT
1656
1657/* Verify that ITEM is a gimple item, with the expected values. */
1658
1659#define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1660 SELFTEST_BEGIN_STMT \
1661 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
1662 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
1663 SELFTEST_END_STMT
1664
1665/* Verify that calls to the dump_* API are captured and consolidated into
1666 optimization records. */
1667
1668static void
1669test_capture_of_dump_calls (const line_table_case &case_)
1670{
1671 /* Generate a location_t for testing. */
1672 line_table_test ltt (case_);
1673 linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
1674 linemap_line_start (line_table, 5, 100);
1675 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
1676 location_t where = linemap_position_for_column (line_table, 10);
1677
1678 dump_location_t loc = dump_location_t::from_location_t (where);
1679
1680 /* Test of dump_printf. */
1681 {
1682 temp_dump_context tmp (true);
1683 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
1684
1685 optinfo *info = tmp.get_pending_optinfo ();
1686 ASSERT_TRUE (info != NULL);
1687 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1688 ASSERT_EQ (info->num_items (), 1);
1689 ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
1690 }
1691
1692 /* Tree, via dump_generic_expr. */
1693 {
1694 temp_dump_context tmp (true);
1695 dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
1696 dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
1697
1698 optinfo *info = tmp.get_pending_optinfo ();
1699 ASSERT_TRUE (info != NULL);
1700 ASSERT_EQ (info->get_location_t (), where);
1701 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1702 ASSERT_EQ (info->num_items (), 2);
1703 ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
1704 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
1705 }
1706
1707 /* Tree, via dump_generic_expr_loc. */
1708 {
1709 temp_dump_context tmp (true);
1710 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
1711
1712 optinfo *info = tmp.get_pending_optinfo ();
1713 ASSERT_TRUE (info != NULL);
1714 ASSERT_EQ (info->get_location_t (), where);
1715 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1716 ASSERT_EQ (info->num_items (), 1);
1717 ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
1718 }
1719
1720 /* Gimple. */
1721 {
1722 greturn *stmt = gimple_build_return (NULL);
1723 gimple_set_location (stmt, where);
1724
1725 /* dump_gimple_stmt_loc. */
1726 {
1727 temp_dump_context tmp (true);
1728 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
1729
1730 optinfo *info = tmp.get_pending_optinfo ();
1731 ASSERT_TRUE (info != NULL);
1732 ASSERT_EQ (info->num_items (), 1);
1733 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
1734 }
1735
1736 /* dump_gimple_stmt. */
1737 {
1738 temp_dump_context tmp (true);
1739 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
1740
1741 optinfo *info = tmp.get_pending_optinfo ();
1742 ASSERT_TRUE (info != NULL);
1743 ASSERT_EQ (info->num_items (), 1);
1744 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
1745 }
1746
1747 /* dump_gimple_expr_loc. */
1748 {
1749 temp_dump_context tmp (true);
1750 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
1751
1752 optinfo *info = tmp.get_pending_optinfo ();
1753 ASSERT_TRUE (info != NULL);
1754 ASSERT_EQ (info->num_items (), 1);
1755 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
1756 }
1757
1758 /* dump_gimple_expr. */
1759 {
1760 temp_dump_context tmp (true);
1761 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
1762
1763 optinfo *info = tmp.get_pending_optinfo ();
1764 ASSERT_TRUE (info != NULL);
1765 ASSERT_EQ (info->num_items (), 1);
1766 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
1767 }
1768 }
1769
1770 /* poly_int. */
1771 {
1772 temp_dump_context tmp (true);
1773 dump_dec (MSG_NOTE, poly_int64 (42));
1774
1775 optinfo *info = tmp.get_pending_optinfo ();
1776 ASSERT_TRUE (info != NULL);
1777 ASSERT_EQ (info->num_items (), 1);
1778 ASSERT_IS_TEXT (info->get_item (0), "42");
1779 }
1780
1781 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
1782 above. */
1783 {
1784 /* MSG_OPTIMIZED_LOCATIONS. */
1785 {
1786 temp_dump_context tmp (true);
1787 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
1788 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
1789 OPTINFO_KIND_SUCCESS);
1790 }
1791
1792 /* MSG_MISSED_OPTIMIZATION. */
1793 {
1794 temp_dump_context tmp (true);
1795 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
1796 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
1797 OPTINFO_KIND_FAILURE);
1798 }
1799 }
1800}
1801
4f5b9c80
DM
1802/* Run all of the selftests within this file. */
1803
1804void
1805dumpfile_c_tests ()
1806{
1807 test_impl_location ();
4df3629e 1808 for_each_line_table_case (test_capture_of_dump_calls);
4f5b9c80
DM
1809}
1810
1811} // namespace selftest
1812
1813#endif /* CHECKING_P */