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