Small ChangeLog tweak.
[official-gcc.git] / gcc / dumpfile.c
blob233e6b1991618ebbee07c5086cd7e7914723a5ed
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "options.h"
24 #include "tree.h"
25 #include "gimple-pretty-print.h"
26 #include "diagnostic-core.h"
27 #include "dumpfile.h"
28 #include "context.h"
29 #include "tree-cfg.h"
31 /* If non-NULL, return one past-the-end of the matching SUBPART of
32 the WHOLE string. */
33 #define skip_leading_substring(whole, part) \
34 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
36 static dump_flags_t pflags; /* current dump_flags */
37 static dump_flags_t alt_flags; /* current opt_info flags */
39 static void dump_loc (dump_flags_t, FILE *, source_location);
40 static FILE *dump_open_alternate_stream (struct dump_file_info *);
42 /* These are currently used for communicating between passes.
43 However, instead of accessing them directly, the passes can use
44 dump_printf () for dumps. */
45 FILE *dump_file = NULL;
46 FILE *alt_dump_file = NULL;
47 const char *dump_file_name;
48 dump_flags_t dump_flags;
50 CONSTEXPR dump_file_info::dump_file_info (): suffix (NULL), swtch (NULL),
51 glob (NULL), pfilename (NULL), alt_filename (NULL), pstream (NULL),
52 alt_stream (NULL), dkind (DK_none), pflags (), alt_flags (0),
53 optgroup_flags (0), pstate (0), alt_state (0), num (0), owns_strings (false),
54 graph_dump_initialized (false)
58 dump_file_info::dump_file_info (const char *_suffix, const char *_swtch,
59 dump_kind _dkind, int _num):
60 suffix (_suffix), swtch (_swtch), glob (NULL),
61 pfilename (NULL), alt_filename (NULL), pstream (NULL), alt_stream (NULL),
62 dkind (_dkind), pflags (), alt_flags (0), optgroup_flags (0),
63 pstate (0), alt_state (0), num (_num), owns_strings (false),
64 graph_dump_initialized (false)
68 /* Table of tree dump switches. This must be consistent with the
69 TREE_DUMP_INDEX enumeration in dumpfile.h. */
70 static struct dump_file_info dump_files[TDI_end] =
72 dump_file_info (),
73 dump_file_info (".cgraph", "ipa-cgraph", DK_ipa, 0),
74 dump_file_info (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
75 dump_file_info (".ipa-clones", "ipa-clones", DK_ipa, 0),
76 dump_file_info (".original", "tree-original", DK_tree, 3),
77 dump_file_info (".gimple", "tree-gimple", DK_tree, 4),
78 dump_file_info (".nested", "tree-nested", DK_tree, 5),
79 #define FIRST_AUTO_NUMBERED_DUMP 3
81 dump_file_info (NULL, "lang-all", DK_lang, 0),
82 dump_file_info (NULL, "tree-all", DK_tree, 0),
83 dump_file_info (NULL, "rtl-all", DK_rtl, 0),
84 dump_file_info (NULL, "ipa-all", DK_ipa, 0),
87 /* Define a name->number mapping for a dump flag value. */
88 struct dump_option_value_info
90 const char *const name; /* the name of the value */
91 const dump_flags_t value; /* the value of the name */
94 /* Table of dump options. This must be consistent with the TDF_* flags
95 in dumpfile.h and opt_info_options below. */
96 static const struct dump_option_value_info dump_options[] =
98 {"address", TDF_ADDRESS},
99 {"asmname", TDF_ASMNAME},
100 {"slim", TDF_SLIM},
101 {"raw", TDF_RAW},
102 {"graph", TDF_GRAPH},
103 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
104 | MSG_MISSED_OPTIMIZATION
105 | MSG_NOTE)},
106 {"cselib", TDF_CSELIB},
107 {"stats", TDF_STATS},
108 {"blocks", TDF_BLOCKS},
109 {"vops", TDF_VOPS},
110 {"lineno", TDF_LINENO},
111 {"uid", TDF_UID},
112 {"stmtaddr", TDF_STMTADDR},
113 {"memsyms", TDF_MEMSYMS},
114 {"eh", TDF_EH},
115 {"alias", TDF_ALIAS},
116 {"nouid", TDF_NOUID},
117 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
118 {"scev", TDF_SCEV},
119 {"gimple", TDF_GIMPLE},
120 {"folding", TDF_FOLDING},
121 {"optimized", MSG_OPTIMIZED_LOCATIONS},
122 {"missed", MSG_MISSED_OPTIMIZATION},
123 {"note", MSG_NOTE},
124 {"optall", MSG_ALL},
125 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH | TDF_STMTADDR
126 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV
127 | TDF_GIMPLE)},
128 {NULL, 0}
131 /* A subset of the dump_options table which is used for -fopt-info
132 types. This must be consistent with the MSG_* flags in dumpfile.h.
134 static const struct dump_option_value_info optinfo_verbosity_options[] =
136 {"optimized", MSG_OPTIMIZED_LOCATIONS},
137 {"missed", MSG_MISSED_OPTIMIZATION},
138 {"note", MSG_NOTE},
139 {"all", MSG_ALL},
140 {NULL, 0}
143 /* Flags used for -fopt-info groups. */
144 static const struct dump_option_value_info optgroup_options[] =
146 {"ipa", OPTGROUP_IPA},
147 {"loop", OPTGROUP_LOOP},
148 {"inline", OPTGROUP_INLINE},
149 {"omp", OPTGROUP_OMP},
150 {"vec", OPTGROUP_VEC},
151 {"optall", OPTGROUP_ALL},
152 {NULL, 0}
155 gcc::dump_manager::dump_manager ():
156 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
157 m_extra_dump_files (NULL),
158 m_extra_dump_files_in_use (0),
159 m_extra_dump_files_alloced (0)
163 gcc::dump_manager::~dump_manager ()
165 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
167 dump_file_info *dfi = &m_extra_dump_files[i];
168 /* suffix, swtch, glob are statically allocated for the entries
169 in dump_files, and for statistics, but are dynamically allocated
170 for those for passes. */
171 if (dfi->owns_strings)
173 XDELETEVEC (const_cast <char *> (dfi->suffix));
174 XDELETEVEC (const_cast <char *> (dfi->swtch));
175 XDELETEVEC (const_cast <char *> (dfi->glob));
177 /* These, if non-NULL, are always dynamically allocated. */
178 XDELETEVEC (const_cast <char *> (dfi->pfilename));
179 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
181 XDELETEVEC (m_extra_dump_files);
184 unsigned int
185 gcc::dump_manager::
186 dump_register (const char *suffix, const char *swtch, const char *glob,
187 dump_kind dkind, int optgroup_flags, bool take_ownership)
189 int num = m_next_dump++;
191 size_t count = m_extra_dump_files_in_use++;
193 if (count >= m_extra_dump_files_alloced)
195 if (m_extra_dump_files_alloced == 0)
196 m_extra_dump_files_alloced = 32;
197 else
198 m_extra_dump_files_alloced *= 2;
199 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
200 m_extra_dump_files,
201 m_extra_dump_files_alloced);
204 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
205 m_extra_dump_files[count].suffix = suffix;
206 m_extra_dump_files[count].swtch = swtch;
207 m_extra_dump_files[count].glob = glob;
208 m_extra_dump_files[count].dkind = dkind;
209 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
210 m_extra_dump_files[count].num = num;
211 m_extra_dump_files[count].owns_strings = take_ownership;
213 return count + TDI_end;
217 /* Return the dump_file_info for the given phase. */
219 struct dump_file_info *
220 gcc::dump_manager::
221 get_dump_file_info (int phase) const
223 if (phase < TDI_end)
224 return &dump_files[phase];
225 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
226 return NULL;
227 else
228 return m_extra_dump_files + (phase - TDI_end);
231 /* Locate the dump_file_info with swtch equal to SWTCH,
232 or return NULL if no such dump_file_info exists. */
234 struct dump_file_info *
235 gcc::dump_manager::
236 get_dump_file_info_by_switch (const char *swtch) const
238 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
239 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
240 return &m_extra_dump_files[i];
242 /* Not found. */
243 return NULL;
247 /* Return the name of the dump file for the given phase.
248 The caller is responsible for calling free on the returned
249 buffer.
250 If the dump is not enabled, returns NULL. */
252 char *
253 gcc::dump_manager::
254 get_dump_file_name (int phase) const
256 struct dump_file_info *dfi;
258 if (phase == TDI_none)
259 return NULL;
261 dfi = get_dump_file_info (phase);
263 return get_dump_file_name (dfi);
266 /* Return the name of the dump file for the given dump_file_info.
267 The caller is responsible for calling free on the returned
268 buffer.
269 If the dump is not enabled, returns NULL. */
271 char *
272 gcc::dump_manager::
273 get_dump_file_name (struct dump_file_info *dfi) const
275 char dump_id[10];
277 gcc_assert (dfi);
279 if (dfi->pstate == 0)
280 return NULL;
282 /* If available, use the command line dump filename. */
283 if (dfi->pfilename)
284 return xstrdup (dfi->pfilename);
286 if (dfi->num < 0)
287 dump_id[0] = '\0';
288 else
290 /* (null), LANG, TREE, RTL, IPA. */
291 char suffix = " ltri"[dfi->dkind];
293 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
294 dump_id[0] = '\0';
297 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
300 /* For a given DFI, open an alternate dump filename (which could also
301 be a standard stream such as stdout/stderr). If the alternate dump
302 file cannot be opened, return NULL. */
304 static FILE *
305 dump_open_alternate_stream (struct dump_file_info *dfi)
307 FILE *stream ;
308 if (!dfi->alt_filename)
309 return NULL;
311 if (dfi->alt_stream)
312 return dfi->alt_stream;
314 stream = strcmp ("stderr", dfi->alt_filename) == 0
315 ? stderr
316 : strcmp ("stdout", dfi->alt_filename) == 0
317 ? stdout
318 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
320 if (!stream)
321 error ("could not open dump file %qs: %m", dfi->alt_filename);
322 else
323 dfi->alt_state = 1;
325 return stream;
328 /* Print source location on DFILE if enabled. */
330 void
331 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
333 if (dump_kind)
335 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
336 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
337 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
338 else if (current_function_decl)
339 fprintf (dfile, "%s:%d:%d: note: ",
340 DECL_SOURCE_FILE (current_function_decl),
341 DECL_SOURCE_LINE (current_function_decl),
342 DECL_SOURCE_COLUMN (current_function_decl));
346 /* Dump gimple statement GS with SPC indentation spaces and
347 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
349 void
350 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
351 gimple *gs, int spc)
353 if (dump_file && (dump_kind & pflags))
354 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
356 if (alt_dump_file && (dump_kind & alt_flags))
357 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
360 /* Similar to dump_gimple_stmt, except additionally print source location. */
362 void
363 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
364 dump_flags_t extra_dump_flags, gimple *gs, int spc)
366 if (dump_file && (dump_kind & pflags))
368 dump_loc (dump_kind, dump_file, loc);
369 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
372 if (alt_dump_file && (dump_kind & alt_flags))
374 dump_loc (dump_kind, alt_dump_file, loc);
375 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
379 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
380 DUMP_KIND is enabled. */
382 void
383 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
384 tree t)
386 if (dump_file && (dump_kind & pflags))
387 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
389 if (alt_dump_file && (dump_kind & alt_flags))
390 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
394 /* Similar to dump_generic_expr, except additionally print the source
395 location. */
397 void
398 dump_generic_expr_loc (int dump_kind, source_location loc,
399 dump_flags_t extra_dump_flags, tree t)
401 if (dump_file && (dump_kind & pflags))
403 dump_loc (dump_kind, dump_file, loc);
404 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
407 if (alt_dump_file && (dump_kind & alt_flags))
409 dump_loc (dump_kind, alt_dump_file, loc);
410 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
414 /* Output a formatted message using FORMAT on appropriate dump streams. */
416 void
417 dump_printf (dump_flags_t dump_kind, const char *format, ...)
419 if (dump_file && (dump_kind & pflags))
421 va_list ap;
422 va_start (ap, format);
423 vfprintf (dump_file, format, ap);
424 va_end (ap);
427 if (alt_dump_file && (dump_kind & alt_flags))
429 va_list ap;
430 va_start (ap, format);
431 vfprintf (alt_dump_file, format, ap);
432 va_end (ap);
436 /* Similar to dump_printf, except source location is also printed. */
438 void
439 dump_printf_loc (dump_flags_t dump_kind, source_location loc,
440 const char *format, ...)
442 if (dump_file && (dump_kind & pflags))
444 va_list ap;
445 dump_loc (dump_kind, dump_file, loc);
446 va_start (ap, format);
447 vfprintf (dump_file, format, ap);
448 va_end (ap);
451 if (alt_dump_file && (dump_kind & alt_flags))
453 va_list ap;
454 dump_loc (dump_kind, alt_dump_file, loc);
455 va_start (ap, format);
456 vfprintf (alt_dump_file, format, ap);
457 va_end (ap);
461 /* Start a dump for PHASE. Store user-supplied dump flags in
462 *FLAG_PTR. Return the number of streams opened. Set globals
463 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
464 set dump_flags appropriately for both pass dump stream and
465 -fopt-info stream. */
468 gcc::dump_manager::
469 dump_start (int phase, dump_flags_t *flag_ptr)
471 int count = 0;
472 char *name;
473 struct dump_file_info *dfi;
474 FILE *stream;
475 if (phase == TDI_none || !dump_phase_enabled_p (phase))
476 return 0;
478 dfi = get_dump_file_info (phase);
479 name = get_dump_file_name (phase);
480 if (name)
482 stream = strcmp ("stderr", name) == 0
483 ? stderr
484 : strcmp ("stdout", name) == 0
485 ? stdout
486 : fopen (name, dfi->pstate < 0 ? "w" : "a");
487 if (!stream)
488 error ("could not open dump file %qs: %m", name);
489 else
491 dfi->pstate = 1;
492 count++;
494 free (name);
495 dfi->pstream = stream;
496 dump_file = dfi->pstream;
497 /* Initialize current dump flags. */
498 pflags = dfi->pflags;
501 stream = dump_open_alternate_stream (dfi);
502 if (stream)
504 dfi->alt_stream = stream;
505 count++;
506 alt_dump_file = dfi->alt_stream;
507 /* Initialize current -fopt-info flags. */
508 alt_flags = dfi->alt_flags;
511 if (flag_ptr)
512 *flag_ptr = dfi->pflags;
514 return count;
517 /* Finish a tree dump for PHASE and close associated dump streams. Also
518 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
520 void
521 gcc::dump_manager::
522 dump_finish (int phase)
524 struct dump_file_info *dfi;
526 if (phase < 0)
527 return;
528 dfi = get_dump_file_info (phase);
529 if (dfi->pstream && (!dfi->pfilename
530 || (strcmp ("stderr", dfi->pfilename) != 0
531 && strcmp ("stdout", dfi->pfilename) != 0)))
532 fclose (dfi->pstream);
534 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
535 && strcmp ("stdout", dfi->alt_filename) != 0)
536 fclose (dfi->alt_stream);
538 dfi->alt_stream = NULL;
539 dfi->pstream = NULL;
540 dump_file = NULL;
541 alt_dump_file = NULL;
542 dump_flags = TDI_none;
543 alt_flags = 0;
544 pflags = 0;
547 /* Begin a tree dump for PHASE. Stores any user supplied flag in
548 *FLAG_PTR and returns a stream to write to. If the dump is not
549 enabled, returns NULL.
550 Multiple calls will reopen and append to the dump file. */
552 FILE *
553 dump_begin (int phase, dump_flags_t *flag_ptr)
555 return g->get_dumps ()->dump_begin (phase, flag_ptr);
558 FILE *
559 gcc::dump_manager::
560 dump_begin (int phase, dump_flags_t *flag_ptr)
562 char *name;
563 struct dump_file_info *dfi;
564 FILE *stream;
566 if (phase == TDI_none || !dump_phase_enabled_p (phase))
567 return NULL;
569 name = get_dump_file_name (phase);
570 if (!name)
571 return NULL;
572 dfi = get_dump_file_info (phase);
574 stream = strcmp ("stderr", name) == 0
575 ? stderr
576 : strcmp ("stdout", name) == 0
577 ? stdout
578 : fopen (name, dfi->pstate < 0 ? "w" : "a");
580 if (!stream)
581 error ("could not open dump file %qs: %m", name);
582 else
583 dfi->pstate = 1;
584 free (name);
586 if (flag_ptr)
587 *flag_ptr = dfi->pflags;
589 /* Initialize current flags */
590 pflags = dfi->pflags;
591 return stream;
594 /* Returns nonzero if dump PHASE is enabled for at least one stream.
595 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
596 any phase. */
599 gcc::dump_manager::
600 dump_phase_enabled_p (int phase) const
602 if (phase == TDI_tree_all)
604 size_t i;
605 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
606 if (dump_files[i].pstate || dump_files[i].alt_state)
607 return 1;
608 for (i = 0; i < m_extra_dump_files_in_use; i++)
609 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
610 return 1;
611 return 0;
613 else
615 struct dump_file_info *dfi = get_dump_file_info (phase);
616 return dfi->pstate || dfi->alt_state;
620 /* Returns nonzero if tree dump PHASE has been initialized. */
623 gcc::dump_manager::
624 dump_initialized_p (int phase) const
626 struct dump_file_info *dfi = get_dump_file_info (phase);
627 return dfi->pstate > 0 || dfi->alt_state > 0;
630 /* Returns the switch name of PHASE. */
632 const char *
633 dump_flag_name (int phase)
635 return g->get_dumps ()->dump_flag_name (phase);
638 const char *
639 gcc::dump_manager::
640 dump_flag_name (int phase) const
642 struct dump_file_info *dfi = get_dump_file_info (phase);
643 return dfi->swtch;
646 /* Finish a tree dump for PHASE. STREAM is the stream created by
647 dump_begin. */
649 void
650 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
652 if (stream != stderr && stream != stdout)
653 fclose (stream);
656 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
657 enabled tree dumps. */
660 gcc::dump_manager::
661 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
663 int n = 0;
664 size_t i;
666 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
668 if ((dump_files[i].dkind == dkind))
670 const char *old_filename = dump_files[i].pfilename;
671 dump_files[i].pstate = -1;
672 dump_files[i].pflags |= flags;
673 n++;
674 /* Override the existing filename. */
675 if (filename)
677 dump_files[i].pfilename = xstrdup (filename);
678 /* Since it is a command-line provided file, which is
679 common to all the phases, use it in append mode. */
680 dump_files[i].pstate = 1;
682 if (old_filename && filename != old_filename)
683 free (CONST_CAST (char *, old_filename));
687 for (i = 0; i < m_extra_dump_files_in_use; i++)
689 if ((m_extra_dump_files[i].dkind == dkind))
691 const char *old_filename = m_extra_dump_files[i].pfilename;
692 m_extra_dump_files[i].pstate = -1;
693 m_extra_dump_files[i].pflags |= flags;
694 n++;
695 /* Override the existing filename. */
696 if (filename)
698 m_extra_dump_files[i].pfilename = xstrdup (filename);
699 /* Since it is a command-line provided file, which is
700 common to all the phases, use it in append mode. */
701 m_extra_dump_files[i].pstate = 1;
703 if (old_filename && filename != old_filename)
704 free (CONST_CAST (char *, old_filename));
708 return n;
711 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
712 Enable dumps with FLAGS on FILENAME. Return the number of enabled
713 dumps. */
716 gcc::dump_manager::
717 opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
718 const char *filename)
720 int n = 0;
721 size_t i;
723 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
725 if ((dump_files[i].optgroup_flags & optgroup_flags))
727 const char *old_filename = dump_files[i].alt_filename;
728 /* Since this file is shared among different passes, it
729 should be opened in append mode. */
730 dump_files[i].alt_state = 1;
731 dump_files[i].alt_flags |= flags;
732 n++;
733 /* Override the existing filename. */
734 if (filename)
735 dump_files[i].alt_filename = xstrdup (filename);
736 if (old_filename && filename != old_filename)
737 free (CONST_CAST (char *, old_filename));
741 for (i = 0; i < m_extra_dump_files_in_use; i++)
743 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
745 const char *old_filename = m_extra_dump_files[i].alt_filename;
746 /* Since this file is shared among different passes, it
747 should be opened in append mode. */
748 m_extra_dump_files[i].alt_state = 1;
749 m_extra_dump_files[i].alt_flags |= flags;
750 n++;
751 /* Override the existing filename. */
752 if (filename)
753 m_extra_dump_files[i].alt_filename = xstrdup (filename);
754 if (old_filename && filename != old_filename)
755 free (CONST_CAST (char *, old_filename));
759 return n;
762 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
763 relevant details in the dump_files array. */
766 gcc::dump_manager::
767 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
769 const char *option_value;
770 const char *ptr;
771 dump_flags_t flags;
773 if (doglob && !dfi->glob)
774 return 0;
776 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
777 if (!option_value)
778 return 0;
780 if (*option_value && *option_value != '-' && *option_value != '=')
781 return 0;
783 ptr = option_value;
784 flags = 0;
786 while (*ptr)
788 const struct dump_option_value_info *option_ptr;
789 const char *end_ptr;
790 const char *eq_ptr;
791 unsigned length;
793 while (*ptr == '-')
794 ptr++;
795 end_ptr = strchr (ptr, '-');
796 eq_ptr = strchr (ptr, '=');
798 if (eq_ptr && !end_ptr)
799 end_ptr = eq_ptr;
801 if (!end_ptr)
802 end_ptr = ptr + strlen (ptr);
803 length = end_ptr - ptr;
805 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
806 if (strlen (option_ptr->name) == length
807 && !memcmp (option_ptr->name, ptr, length))
809 flags |= option_ptr->value;
810 goto found;
813 if (*ptr == '=')
815 /* Interpret rest of the argument as a dump filename. This
816 filename overrides other command line filenames. */
817 if (dfi->pfilename)
818 free (CONST_CAST (char *, dfi->pfilename));
819 dfi->pfilename = xstrdup (ptr + 1);
820 break;
822 else
823 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
824 length, ptr, dfi->swtch);
825 found:;
826 ptr = end_ptr;
829 dfi->pstate = -1;
830 dfi->pflags |= flags;
832 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
833 known dumps. */
834 if (dfi->suffix == NULL)
835 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
837 return 1;
841 gcc::dump_manager::
842 dump_switch_p (const char *arg)
844 size_t i;
845 int any = 0;
847 for (i = TDI_none + 1; i != TDI_end; i++)
848 any |= dump_switch_p_1 (arg, &dump_files[i], false);
850 /* Don't glob if we got a hit already */
851 if (!any)
852 for (i = TDI_none + 1; i != TDI_end; i++)
853 any |= dump_switch_p_1 (arg, &dump_files[i], true);
855 for (i = 0; i < m_extra_dump_files_in_use; i++)
856 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
858 if (!any)
859 for (i = 0; i < m_extra_dump_files_in_use; i++)
860 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
863 return any;
866 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
867 and filename. Return non-zero if it is a recognized switch. */
869 static int
870 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
871 char **filename)
873 const char *option_value;
874 const char *ptr;
876 option_value = arg;
877 ptr = option_value;
879 *filename = NULL;
880 *flags = 0;
881 *optgroup_flags = 0;
883 if (!ptr)
884 return 1; /* Handle '-fopt-info' without any additional options. */
886 while (*ptr)
888 const struct dump_option_value_info *option_ptr;
889 const char *end_ptr;
890 const char *eq_ptr;
891 unsigned length;
893 while (*ptr == '-')
894 ptr++;
895 end_ptr = strchr (ptr, '-');
896 eq_ptr = strchr (ptr, '=');
898 if (eq_ptr && !end_ptr)
899 end_ptr = eq_ptr;
901 if (!end_ptr)
902 end_ptr = ptr + strlen (ptr);
903 length = end_ptr - ptr;
905 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
906 option_ptr++)
907 if (strlen (option_ptr->name) == length
908 && !memcmp (option_ptr->name, ptr, length))
910 *flags |= option_ptr->value;
911 goto found;
914 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
915 if (strlen (option_ptr->name) == length
916 && !memcmp (option_ptr->name, ptr, length))
918 *optgroup_flags |= option_ptr->value;
919 goto found;
922 if (*ptr == '=')
924 /* Interpret rest of the argument as a dump filename. This
925 filename overrides other command line filenames. */
926 *filename = xstrdup (ptr + 1);
927 break;
929 else
931 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
932 length, ptr, arg);
933 return 0;
935 found:;
936 ptr = end_ptr;
939 return 1;
942 /* Return non-zero if ARG is a recognized switch for
943 -fopt-info. Return zero otherwise. */
946 opt_info_switch_p (const char *arg)
948 dump_flags_t flags;
949 int optgroup_flags;
950 char *filename;
951 static char *file_seen = NULL;
952 gcc::dump_manager *dumps = g->get_dumps ();
954 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
955 return 0;
957 if (!filename)
958 filename = xstrdup ("stderr");
960 /* Bail out if a different filename has been specified. */
961 if (file_seen && strcmp (file_seen, filename))
963 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
964 arg);
965 return 1;
968 file_seen = xstrdup (filename);
969 if (!flags)
970 flags = MSG_OPTIMIZED_LOCATIONS;
971 if (!optgroup_flags)
972 optgroup_flags = OPTGROUP_ALL;
974 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
977 /* Print basic block on the dump streams. */
979 void
980 dump_basic_block (int dump_kind, basic_block bb, int indent)
982 if (dump_file && (dump_kind & pflags))
983 dump_bb (dump_file, bb, indent, TDF_DETAILS);
984 if (alt_dump_file && (dump_kind & alt_flags))
985 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
988 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
990 void
991 dump_function (int phase, tree fn)
993 FILE *stream;
994 dump_flags_t flags;
996 stream = dump_begin (phase, &flags);
997 if (stream)
999 dump_function_to_file (fn, stream, flags);
1000 dump_end (phase, stream);
1004 /* Print information from the combine pass on dump_file. */
1006 void
1007 print_combine_total_stats (void)
1009 if (dump_file)
1010 dump_combine_total_stats (dump_file);
1013 /* Enable RTL dump for all the RTL passes. */
1015 bool
1016 enable_rtl_dump_file (void)
1018 gcc::dump_manager *dumps = g->get_dumps ();
1019 int num_enabled =
1020 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1021 NULL);
1022 return num_enabled > 0;