2015-07-02 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / dumpfile.c
blobd5f601f139de66d6a1d5020ab8e79867820aff9a
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2015 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 "diagnostic-core.h"
24 #include "dumpfile.h"
25 #include "alias.h"
26 #include "symtab.h"
27 #include "options.h"
28 #include "tree.h"
29 #include "gimple-pretty-print.h"
30 #include "context.h"
32 /* If non-NULL, return one past-the-end of the matching SUBPART of
33 the WHOLE string. */
34 #define skip_leading_substring(whole, part) \
35 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
37 static int pflags; /* current dump_flags */
38 static int alt_flags; /* current opt_info flags */
40 static void dump_loc (int, FILE *, source_location);
41 static FILE *dump_open_alternate_stream (struct dump_file_info *);
43 /* These are currently used for communicating between passes.
44 However, instead of accessing them directly, the passes can use
45 dump_printf () for dumps. */
46 FILE *dump_file = NULL;
47 FILE *alt_dump_file = NULL;
48 const char *dump_file_name;
49 int dump_flags;
51 /* Table of tree dump switches. This must be consistent with the
52 TREE_DUMP_INDEX enumeration in dumpfile.h. */
53 static struct dump_file_info dump_files[TDI_end] =
55 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, false},
56 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
57 0, 0, 0, 0, 0, false},
58 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
59 0, 0, 0, 0, 0, false},
60 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
61 0, 0, 0, 0, 1, false},
62 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
63 0, 0, 0, 0, 2, false},
64 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
65 0, 0, 0, 0, 3, false},
66 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
67 0, 0, 0, 0, 4, false},
68 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
69 0, 0, 0, 0, 5, false},
70 #define FIRST_AUTO_NUMBERED_DUMP 6
72 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
73 0, 0, 0, 0, 0, false},
74 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
75 0, 0, 0, 0, 0, false},
76 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
77 0, 0, 0, 0, 0, false},
80 /* Define a name->number mapping for a dump flag value. */
81 struct dump_option_value_info
83 const char *const name; /* the name of the value */
84 const int value; /* the value of the name */
87 /* Table of dump options. This must be consistent with the TDF_* flags
88 in dumpfile.h and opt_info_options below. */
89 static const struct dump_option_value_info dump_options[] =
91 {"address", TDF_ADDRESS},
92 {"asmname", TDF_ASMNAME},
93 {"slim", TDF_SLIM},
94 {"raw", TDF_RAW},
95 {"graph", TDF_GRAPH},
96 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
97 | MSG_MISSED_OPTIMIZATION
98 | MSG_NOTE)},
99 {"cselib", TDF_CSELIB},
100 {"stats", TDF_STATS},
101 {"blocks", TDF_BLOCKS},
102 {"vops", TDF_VOPS},
103 {"lineno", TDF_LINENO},
104 {"uid", TDF_UID},
105 {"stmtaddr", TDF_STMTADDR},
106 {"memsyms", TDF_MEMSYMS},
107 {"verbose", TDF_VERBOSE},
108 {"eh", TDF_EH},
109 {"alias", TDF_ALIAS},
110 {"nouid", TDF_NOUID},
111 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
112 {"scev", TDF_SCEV},
113 {"optimized", MSG_OPTIMIZED_LOCATIONS},
114 {"missed", MSG_MISSED_OPTIMIZATION},
115 {"note", MSG_NOTE},
116 {"optall", MSG_ALL},
117 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
118 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
119 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
120 {NULL, 0}
123 /* A subset of the dump_options table which is used for -fopt-info
124 types. This must be consistent with the MSG_* flags in dumpfile.h.
126 static const struct dump_option_value_info optinfo_verbosity_options[] =
128 {"optimized", MSG_OPTIMIZED_LOCATIONS},
129 {"missed", MSG_MISSED_OPTIMIZATION},
130 {"note", MSG_NOTE},
131 {"all", MSG_ALL},
132 {NULL, 0}
135 /* Flags used for -fopt-info groups. */
136 static const struct dump_option_value_info optgroup_options[] =
138 {"ipa", OPTGROUP_IPA},
139 {"loop", OPTGROUP_LOOP},
140 {"inline", OPTGROUP_INLINE},
141 {"vec", OPTGROUP_VEC},
142 {"optall", OPTGROUP_ALL},
143 {NULL, 0}
146 gcc::dump_manager::dump_manager ():
147 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
148 m_extra_dump_files (NULL),
149 m_extra_dump_files_in_use (0),
150 m_extra_dump_files_alloced (0)
154 gcc::dump_manager::~dump_manager ()
156 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
158 dump_file_info *dfi = &m_extra_dump_files[i];
159 /* suffix, swtch, glob are statically allocated for the entries
160 in dump_files, and for statistics, but are dynamically allocated
161 for those for passes. */
162 if (dfi->owns_strings)
164 XDELETEVEC (const_cast <char *> (dfi->suffix));
165 XDELETEVEC (const_cast <char *> (dfi->swtch));
166 XDELETEVEC (const_cast <char *> (dfi->glob));
168 /* These, if non-NULL, are always dynamically allocated. */
169 XDELETEVEC (const_cast <char *> (dfi->pfilename));
170 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
172 XDELETEVEC (m_extra_dump_files);
175 unsigned int
176 gcc::dump_manager::
177 dump_register (const char *suffix, const char *swtch, const char *glob,
178 int flags, int optgroup_flags,
179 bool take_ownership)
181 int num = m_next_dump++;
183 size_t count = m_extra_dump_files_in_use++;
185 if (count >= m_extra_dump_files_alloced)
187 if (m_extra_dump_files_alloced == 0)
188 m_extra_dump_files_alloced = 32;
189 else
190 m_extra_dump_files_alloced *= 2;
191 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
192 m_extra_dump_files,
193 m_extra_dump_files_alloced);
196 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
197 m_extra_dump_files[count].suffix = suffix;
198 m_extra_dump_files[count].swtch = swtch;
199 m_extra_dump_files[count].glob = glob;
200 m_extra_dump_files[count].pflags = flags;
201 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
202 m_extra_dump_files[count].num = num;
203 m_extra_dump_files[count].owns_strings = take_ownership;
205 return count + TDI_end;
209 /* Return the dump_file_info for the given phase. */
211 struct dump_file_info *
212 gcc::dump_manager::
213 get_dump_file_info (int phase) const
215 if (phase < TDI_end)
216 return &dump_files[phase];
217 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
218 return NULL;
219 else
220 return m_extra_dump_files + (phase - TDI_end);
223 /* Locate the dump_file_info with swtch equal to SWTCH,
224 or return NULL if no such dump_file_info exists. */
226 struct dump_file_info *
227 gcc::dump_manager::
228 get_dump_file_info_by_switch (const char *swtch) const
230 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
231 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
232 return &m_extra_dump_files[i];
234 /* Not found. */
235 return NULL;
239 /* Return the name of the dump file for the given phase.
240 The caller is responsible for calling free on the returned
241 buffer.
242 If the dump is not enabled, returns NULL. */
244 char *
245 gcc::dump_manager::
246 get_dump_file_name (int phase) const
248 struct dump_file_info *dfi;
250 if (phase == TDI_none)
251 return NULL;
253 dfi = get_dump_file_info (phase);
255 return get_dump_file_name (dfi);
258 /* Return the name of the dump file for the given dump_file_info.
259 The caller is responsible for calling free on the returned
260 buffer.
261 If the dump is not enabled, returns NULL. */
263 char *
264 gcc::dump_manager::
265 get_dump_file_name (struct dump_file_info *dfi) const
267 char dump_id[10];
269 gcc_assert (dfi);
271 if (dfi->pstate == 0)
272 return NULL;
274 /* If available, use the command line dump filename. */
275 if (dfi->pfilename)
276 return xstrdup (dfi->pfilename);
278 if (dfi->num < 0)
279 dump_id[0] = '\0';
280 else
282 char suffix;
283 if (dfi->pflags & TDF_TREE)
284 suffix = 't';
285 else if (dfi->pflags & TDF_IPA)
286 suffix = 'i';
287 else
288 suffix = 'r';
290 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
291 dump_id[0] = '\0';
294 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
297 /* For a given DFI, open an alternate dump filename (which could also
298 be a standard stream such as stdout/stderr). If the alternate dump
299 file cannot be opened, return NULL. */
301 static FILE *
302 dump_open_alternate_stream (struct dump_file_info *dfi)
304 FILE *stream ;
305 if (!dfi->alt_filename)
306 return NULL;
308 if (dfi->alt_stream)
309 return dfi->alt_stream;
311 stream = strcmp ("stderr", dfi->alt_filename) == 0
312 ? stderr
313 : strcmp ("stdout", dfi->alt_filename) == 0
314 ? stdout
315 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
317 if (!stream)
318 error ("could not open dump file %qs: %m", dfi->alt_filename);
319 else
320 dfi->alt_state = 1;
322 return stream;
325 /* Print source location on DFILE if enabled. */
327 void
328 dump_loc (int dump_kind, FILE *dfile, source_location loc)
330 if (dump_kind)
332 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
333 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
334 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
335 else if (current_function_decl)
336 fprintf (dfile, "%s:%d:%d: note: ",
337 DECL_SOURCE_FILE (current_function_decl),
338 DECL_SOURCE_LINE (current_function_decl),
339 DECL_SOURCE_COLUMN (current_function_decl));
343 /* Dump gimple statement GS with SPC indentation spaces and
344 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
346 void
347 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
349 if (dump_file && (dump_kind & pflags))
350 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
352 if (alt_dump_file && (dump_kind & alt_flags))
353 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
356 /* Similar to dump_gimple_stmt, except additionally print source location. */
358 void
359 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
360 gimple gs, int spc)
362 if (dump_file && (dump_kind & pflags))
364 dump_loc (dump_kind, dump_file, loc);
365 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
368 if (alt_dump_file && (dump_kind & alt_flags))
370 dump_loc (dump_kind, alt_dump_file, loc);
371 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
375 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
376 DUMP_KIND is enabled. */
378 void
379 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
381 if (dump_file && (dump_kind & pflags))
382 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
384 if (alt_dump_file && (dump_kind & alt_flags))
385 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
389 /* Similar to dump_generic_expr, except additionally print the source
390 location. */
392 void
393 dump_generic_expr_loc (int dump_kind, source_location loc,
394 int extra_dump_flags, tree t)
396 if (dump_file && (dump_kind & pflags))
398 dump_loc (dump_kind, dump_file, loc);
399 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
402 if (alt_dump_file && (dump_kind & alt_flags))
404 dump_loc (dump_kind, alt_dump_file, loc);
405 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
409 /* Output a formatted message using FORMAT on appropriate dump streams. */
411 void
412 dump_printf (int dump_kind, const char *format, ...)
414 if (dump_file && (dump_kind & pflags))
416 va_list ap;
417 va_start (ap, format);
418 vfprintf (dump_file, format, ap);
419 va_end (ap);
422 if (alt_dump_file && (dump_kind & alt_flags))
424 va_list ap;
425 va_start (ap, format);
426 vfprintf (alt_dump_file, format, ap);
427 va_end (ap);
431 /* Similar to dump_printf, except source location is also printed. */
433 void
434 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
436 if (dump_file && (dump_kind & pflags))
438 va_list ap;
439 dump_loc (dump_kind, dump_file, loc);
440 va_start (ap, format);
441 vfprintf (dump_file, format, ap);
442 va_end (ap);
445 if (alt_dump_file && (dump_kind & alt_flags))
447 va_list ap;
448 dump_loc (dump_kind, alt_dump_file, loc);
449 va_start (ap, format);
450 vfprintf (alt_dump_file, format, ap);
451 va_end (ap);
455 /* Start a dump for PHASE. Store user-supplied dump flags in
456 *FLAG_PTR. Return the number of streams opened. Set globals
457 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
458 set dump_flags appropriately for both pass dump stream and
459 -fopt-info stream. */
462 gcc::dump_manager::
463 dump_start (int phase, int *flag_ptr)
465 int count = 0;
466 char *name;
467 struct dump_file_info *dfi;
468 FILE *stream;
469 if (phase == TDI_none || !dump_phase_enabled_p (phase))
470 return 0;
472 dfi = get_dump_file_info (phase);
473 name = get_dump_file_name (phase);
474 if (name)
476 stream = strcmp ("stderr", name) == 0
477 ? stderr
478 : strcmp ("stdout", name) == 0
479 ? stdout
480 : fopen (name, dfi->pstate < 0 ? "w" : "a");
481 if (!stream)
482 error ("could not open dump file %qs: %m", name);
483 else
485 dfi->pstate = 1;
486 count++;
488 free (name);
489 dfi->pstream = stream;
490 dump_file = dfi->pstream;
491 /* Initialize current dump flags. */
492 pflags = dfi->pflags;
495 stream = dump_open_alternate_stream (dfi);
496 if (stream)
498 dfi->alt_stream = stream;
499 count++;
500 alt_dump_file = dfi->alt_stream;
501 /* Initialize current -fopt-info flags. */
502 alt_flags = dfi->alt_flags;
505 if (flag_ptr)
506 *flag_ptr = dfi->pflags;
508 return count;
511 /* Finish a tree dump for PHASE and close associated dump streams. Also
512 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
514 void
515 gcc::dump_manager::
516 dump_finish (int phase)
518 struct dump_file_info *dfi;
520 if (phase < 0)
521 return;
522 dfi = get_dump_file_info (phase);
523 if (dfi->pstream && (!dfi->pfilename
524 || (strcmp ("stderr", dfi->pfilename) != 0
525 && strcmp ("stdout", dfi->pfilename) != 0)))
526 fclose (dfi->pstream);
528 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
529 && strcmp ("stdout", dfi->alt_filename) != 0)
530 fclose (dfi->alt_stream);
532 dfi->alt_stream = NULL;
533 dfi->pstream = NULL;
534 dump_file = NULL;
535 alt_dump_file = NULL;
536 dump_flags = TDI_none;
537 alt_flags = 0;
538 pflags = 0;
541 /* Begin a tree dump for PHASE. Stores any user supplied flag in
542 *FLAG_PTR and returns a stream to write to. If the dump is not
543 enabled, returns NULL.
544 Multiple calls will reopen and append to the dump file. */
546 FILE *
547 dump_begin (int phase, int *flag_ptr)
549 return g->get_dumps ()->dump_begin (phase, flag_ptr);
552 FILE *
553 gcc::dump_manager::
554 dump_begin (int phase, int *flag_ptr)
556 char *name;
557 struct dump_file_info *dfi;
558 FILE *stream;
560 if (phase == TDI_none || !dump_phase_enabled_p (phase))
561 return NULL;
563 name = get_dump_file_name (phase);
564 if (!name)
565 return NULL;
566 dfi = get_dump_file_info (phase);
568 stream = strcmp ("stderr", name) == 0
569 ? stderr
570 : strcmp ("stdout", name) == 0
571 ? stdout
572 : fopen (name, dfi->pstate < 0 ? "w" : "a");
574 if (!stream)
575 error ("could not open dump file %qs: %m", name);
576 else
577 dfi->pstate = 1;
578 free (name);
580 if (flag_ptr)
581 *flag_ptr = dfi->pflags;
583 /* Initialize current flags */
584 pflags = dfi->pflags;
585 return stream;
588 /* Returns nonzero if dump PHASE is enabled for at least one stream.
589 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
590 any phase. */
593 gcc::dump_manager::
594 dump_phase_enabled_p (int phase) const
596 if (phase == TDI_tree_all)
598 size_t i;
599 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
600 if (dump_files[i].pstate || dump_files[i].alt_state)
601 return 1;
602 for (i = 0; i < m_extra_dump_files_in_use; i++)
603 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
604 return 1;
605 return 0;
607 else
609 struct dump_file_info *dfi = get_dump_file_info (phase);
610 return dfi->pstate || dfi->alt_state;
614 /* Returns nonzero if tree dump PHASE has been initialized. */
617 gcc::dump_manager::
618 dump_initialized_p (int phase) const
620 struct dump_file_info *dfi = get_dump_file_info (phase);
621 return dfi->pstate > 0 || dfi->alt_state > 0;
624 /* Returns the switch name of PHASE. */
626 const char *
627 dump_flag_name (int phase)
629 return g->get_dumps ()->dump_flag_name (phase);
632 const char *
633 gcc::dump_manager::
634 dump_flag_name (int phase) const
636 struct dump_file_info *dfi = get_dump_file_info (phase);
637 return dfi->swtch;
640 /* Finish a tree dump for PHASE. STREAM is the stream created by
641 dump_begin. */
643 void
644 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
646 if (stream != stderr && stream != stdout)
647 fclose (stream);
650 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
651 enabled tree dumps. */
654 gcc::dump_manager::
655 dump_enable_all (int flags, const char *filename)
657 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
658 int n = 0;
659 size_t i;
661 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
663 if ((dump_files[i].pflags & ir_dump_type))
665 const char *old_filename = dump_files[i].pfilename;
666 dump_files[i].pstate = -1;
667 dump_files[i].pflags |= flags;
668 n++;
669 /* Override the existing filename. */
670 if (filename)
672 dump_files[i].pfilename = xstrdup (filename);
673 /* Since it is a command-line provided file, which is
674 common to all the phases, use it in append mode. */
675 dump_files[i].pstate = 1;
677 if (old_filename && filename != old_filename)
678 free (CONST_CAST (char *, old_filename));
682 for (i = 0; i < m_extra_dump_files_in_use; i++)
684 if ((m_extra_dump_files[i].pflags & ir_dump_type))
686 const char *old_filename = m_extra_dump_files[i].pfilename;
687 m_extra_dump_files[i].pstate = -1;
688 m_extra_dump_files[i].pflags |= flags;
689 n++;
690 /* Override the existing filename. */
691 if (filename)
693 m_extra_dump_files[i].pfilename = xstrdup (filename);
694 /* Since it is a command-line provided file, which is
695 common to all the phases, use it in append mode. */
696 m_extra_dump_files[i].pstate = 1;
698 if (old_filename && filename != old_filename)
699 free (CONST_CAST (char *, old_filename));
703 return n;
706 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
707 Enable dumps with FLAGS on FILENAME. Return the number of enabled
708 dumps. */
711 gcc::dump_manager::
712 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
714 int n = 0;
715 size_t i;
717 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
719 if ((dump_files[i].optgroup_flags & optgroup_flags))
721 const char *old_filename = dump_files[i].alt_filename;
722 /* Since this file is shared among different passes, it
723 should be opened in append mode. */
724 dump_files[i].alt_state = 1;
725 dump_files[i].alt_flags |= flags;
726 n++;
727 /* Override the existing filename. */
728 if (filename)
729 dump_files[i].alt_filename = xstrdup (filename);
730 if (old_filename && filename != old_filename)
731 free (CONST_CAST (char *, old_filename));
735 for (i = 0; i < m_extra_dump_files_in_use; i++)
737 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
739 const char *old_filename = m_extra_dump_files[i].alt_filename;
740 /* Since this file is shared among different passes, it
741 should be opened in append mode. */
742 m_extra_dump_files[i].alt_state = 1;
743 m_extra_dump_files[i].alt_flags |= flags;
744 n++;
745 /* Override the existing filename. */
746 if (filename)
747 m_extra_dump_files[i].alt_filename = xstrdup (filename);
748 if (old_filename && filename != old_filename)
749 free (CONST_CAST (char *, old_filename));
753 return n;
756 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
757 relevant details in the dump_files array. */
760 gcc::dump_manager::
761 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
763 const char *option_value;
764 const char *ptr;
765 int flags;
767 if (doglob && !dfi->glob)
768 return 0;
770 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
771 if (!option_value)
772 return 0;
774 if (*option_value && *option_value != '-' && *option_value != '=')
775 return 0;
777 ptr = option_value;
778 flags = 0;
780 while (*ptr)
782 const struct dump_option_value_info *option_ptr;
783 const char *end_ptr;
784 const char *eq_ptr;
785 unsigned length;
787 while (*ptr == '-')
788 ptr++;
789 end_ptr = strchr (ptr, '-');
790 eq_ptr = strchr (ptr, '=');
792 if (eq_ptr && !end_ptr)
793 end_ptr = eq_ptr;
795 if (!end_ptr)
796 end_ptr = ptr + strlen (ptr);
797 length = end_ptr - ptr;
799 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
800 if (strlen (option_ptr->name) == length
801 && !memcmp (option_ptr->name, ptr, length))
803 flags |= option_ptr->value;
804 goto found;
807 if (*ptr == '=')
809 /* Interpret rest of the argument as a dump filename. This
810 filename overrides other command line filenames. */
811 if (dfi->pfilename)
812 free (CONST_CAST (char *, dfi->pfilename));
813 dfi->pfilename = xstrdup (ptr + 1);
814 break;
816 else
817 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
818 length, ptr, dfi->swtch);
819 found:;
820 ptr = end_ptr;
823 dfi->pstate = -1;
824 dfi->pflags |= flags;
826 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
827 known dumps. */
828 if (dfi->suffix == NULL)
829 dump_enable_all (dfi->pflags, dfi->pfilename);
831 return 1;
835 gcc::dump_manager::
836 dump_switch_p (const char *arg)
838 size_t i;
839 int any = 0;
841 for (i = TDI_none + 1; i != TDI_end; i++)
842 any |= dump_switch_p_1 (arg, &dump_files[i], false);
844 /* Don't glob if we got a hit already */
845 if (!any)
846 for (i = TDI_none + 1; i != TDI_end; i++)
847 any |= dump_switch_p_1 (arg, &dump_files[i], true);
849 for (i = 0; i < m_extra_dump_files_in_use; i++)
850 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
852 if (!any)
853 for (i = 0; i < m_extra_dump_files_in_use; i++)
854 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
857 return any;
860 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
861 and filename. Return non-zero if it is a recognized switch. */
863 static int
864 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
865 char **filename)
867 const char *option_value;
868 const char *ptr;
870 option_value = arg;
871 ptr = option_value;
873 *filename = NULL;
874 *flags = 0;
875 *optgroup_flags = 0;
877 if (!ptr)
878 return 1; /* Handle '-fopt-info' without any additional options. */
880 while (*ptr)
882 const struct dump_option_value_info *option_ptr;
883 const char *end_ptr;
884 const char *eq_ptr;
885 unsigned length;
887 while (*ptr == '-')
888 ptr++;
889 end_ptr = strchr (ptr, '-');
890 eq_ptr = strchr (ptr, '=');
892 if (eq_ptr && !end_ptr)
893 end_ptr = eq_ptr;
895 if (!end_ptr)
896 end_ptr = ptr + strlen (ptr);
897 length = end_ptr - ptr;
899 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
900 option_ptr++)
901 if (strlen (option_ptr->name) == length
902 && !memcmp (option_ptr->name, ptr, length))
904 *flags |= option_ptr->value;
905 goto found;
908 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
909 if (strlen (option_ptr->name) == length
910 && !memcmp (option_ptr->name, ptr, length))
912 *optgroup_flags |= option_ptr->value;
913 goto found;
916 if (*ptr == '=')
918 /* Interpret rest of the argument as a dump filename. This
919 filename overrides other command line filenames. */
920 *filename = xstrdup (ptr + 1);
921 break;
923 else
925 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
926 length, ptr, arg);
927 return 0;
929 found:;
930 ptr = end_ptr;
933 return 1;
936 /* Return non-zero if ARG is a recognized switch for
937 -fopt-info. Return zero otherwise. */
940 opt_info_switch_p (const char *arg)
942 int flags;
943 int optgroup_flags;
944 char *filename;
945 static char *file_seen = NULL;
946 gcc::dump_manager *dumps = g->get_dumps ();
948 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
949 return 0;
951 if (!filename)
952 filename = xstrdup ("stderr");
954 /* Bail out if a different filename has been specified. */
955 if (file_seen && strcmp (file_seen, filename))
957 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
958 arg);
959 return 1;
962 file_seen = xstrdup (filename);
963 if (!flags)
964 flags = MSG_OPTIMIZED_LOCATIONS;
965 if (!optgroup_flags)
966 optgroup_flags = OPTGROUP_ALL;
968 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
971 /* Print basic block on the dump streams. */
973 void
974 dump_basic_block (int dump_kind, basic_block bb, int indent)
976 if (dump_file && (dump_kind & pflags))
977 dump_bb (dump_file, bb, indent, TDF_DETAILS);
978 if (alt_dump_file && (dump_kind & alt_flags))
979 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
982 /* Print information from the combine pass on dump_file. */
984 void
985 print_combine_total_stats (void)
987 if (dump_file)
988 dump_combine_total_stats (dump_file);
991 /* Enable RTL dump for all the RTL passes. */
993 bool
994 enable_rtl_dump_file (void)
996 gcc::dump_manager *dumps = g->get_dumps ();
997 int num_enabled =
998 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
999 return num_enabled > 0;