2014-04-24 Segher Boessenkool <segher@kernel.crashing.org>
[official-gcc.git] / gcc / dumpfile.c
blobfd630a69933e93dc9f039f007557995691b364bd
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2014 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 "tree.h"
26 #include "gimple-pretty-print.h"
27 #include "context.h"
29 /* If non-NULL, return one past-the-end of the matching SUBPART of
30 the WHOLE string. */
31 #define skip_leading_substring(whole, part) \
32 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
34 static int pflags; /* current dump_flags */
35 static int alt_flags; /* current opt_info flags */
37 static void dump_loc (int, FILE *, source_location);
38 static FILE *dump_open_alternate_stream (struct dump_file_info *);
40 /* These are currently used for communicating between passes.
41 However, instead of accessing them directly, the passes can use
42 dump_printf () for dumps. */
43 FILE *dump_file = NULL;
44 FILE *alt_dump_file = NULL;
45 const char *dump_file_name;
46 int dump_flags;
48 /* Table of tree dump switches. This must be consistent with the
49 TREE_DUMP_INDEX enumeration in dumpfile.h. */
50 static struct dump_file_info dump_files[TDI_end] =
52 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0},
53 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
54 0, 0, 0, 0, 0},
55 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
56 0, 0, 0, 0, 0},
57 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
58 0, 0, 0, 0, 1},
59 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
60 0, 0, 0, 0, 2},
61 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
62 0, 0, 0, 0, 3},
63 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
64 0, 0, 0, 0, 4},
65 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
66 0, 0, 0, 0, 5},
67 #define FIRST_AUTO_NUMBERED_DUMP 6
69 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
70 0, 0, 0, 0, 0},
71 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
72 0, 0, 0, 0, 0},
73 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
74 0, 0, 0, 0, 0},
77 /* Define a name->number mapping for a dump flag value. */
78 struct dump_option_value_info
80 const char *const name; /* the name of the value */
81 const int value; /* the value of the name */
84 /* Table of dump options. This must be consistent with the TDF_* flags
85 in dumpfile.h and opt_info_options below. */
86 static const struct dump_option_value_info dump_options[] =
88 {"address", TDF_ADDRESS},
89 {"asmname", TDF_ASMNAME},
90 {"slim", TDF_SLIM},
91 {"raw", TDF_RAW},
92 {"graph", TDF_GRAPH},
93 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
94 | MSG_MISSED_OPTIMIZATION
95 | MSG_NOTE)},
96 {"cselib", TDF_CSELIB},
97 {"stats", TDF_STATS},
98 {"blocks", TDF_BLOCKS},
99 {"vops", TDF_VOPS},
100 {"lineno", TDF_LINENO},
101 {"uid", TDF_UID},
102 {"stmtaddr", TDF_STMTADDR},
103 {"memsyms", TDF_MEMSYMS},
104 {"verbose", TDF_VERBOSE},
105 {"eh", TDF_EH},
106 {"alias", TDF_ALIAS},
107 {"nouid", TDF_NOUID},
108 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
109 {"scev", TDF_SCEV},
110 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
111 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
112 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
113 {NULL, 0}
116 /* A subset of the dump_options table which is used for -fopt-info
117 types. This must be consistent with the MSG_* flags in dumpfile.h.
119 static const struct dump_option_value_info optinfo_verbosity_options[] =
121 {"optimized", MSG_OPTIMIZED_LOCATIONS},
122 {"missed", MSG_MISSED_OPTIMIZATION},
123 {"note", MSG_NOTE},
124 {"all", MSG_ALL},
125 {NULL, 0}
128 /* Flags used for -fopt-info groups. */
129 static const struct dump_option_value_info optgroup_options[] =
131 {"ipa", OPTGROUP_IPA},
132 {"loop", OPTGROUP_LOOP},
133 {"inline", OPTGROUP_INLINE},
134 {"vec", OPTGROUP_VEC},
135 {"optall", OPTGROUP_ALL},
136 {NULL, 0}
139 gcc::dump_manager::dump_manager ():
140 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
141 m_extra_dump_files (NULL),
142 m_extra_dump_files_in_use (0),
143 m_extra_dump_files_alloced (0)
147 unsigned int
148 gcc::dump_manager::
149 dump_register (const char *suffix, const char *swtch, const char *glob,
150 int flags, int optgroup_flags)
152 int num = m_next_dump++;
154 size_t count = m_extra_dump_files_in_use++;
156 if (count >= m_extra_dump_files_alloced)
158 if (m_extra_dump_files_alloced == 0)
159 m_extra_dump_files_alloced = 32;
160 else
161 m_extra_dump_files_alloced *= 2;
162 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
163 m_extra_dump_files,
164 m_extra_dump_files_alloced);
167 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
168 m_extra_dump_files[count].suffix = suffix;
169 m_extra_dump_files[count].swtch = swtch;
170 m_extra_dump_files[count].glob = glob;
171 m_extra_dump_files[count].pflags = flags;
172 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
173 m_extra_dump_files[count].num = num;
175 return count + TDI_end;
179 /* Return the dump_file_info for the given phase. */
181 struct dump_file_info *
182 gcc::dump_manager::
183 get_dump_file_info (int phase) const
185 if (phase < TDI_end)
186 return &dump_files[phase];
187 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
188 return NULL;
189 else
190 return m_extra_dump_files + (phase - TDI_end);
194 /* Return the name of the dump file for the given phase.
195 If the dump is not enabled, returns NULL. */
197 char *
198 gcc::dump_manager::
199 get_dump_file_name (int phase) const
201 char dump_id[10];
202 struct dump_file_info *dfi;
204 if (phase == TDI_none)
205 return NULL;
207 dfi = get_dump_file_info (phase);
208 if (dfi->pstate == 0)
209 return NULL;
211 /* If available, use the command line dump filename. */
212 if (dfi->pfilename)
213 return xstrdup (dfi->pfilename);
215 if (dfi->num < 0)
216 dump_id[0] = '\0';
217 else
219 char suffix;
220 if (dfi->pflags & TDF_TREE)
221 suffix = 't';
222 else if (dfi->pflags & TDF_IPA)
223 suffix = 'i';
224 else
225 suffix = 'r';
227 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
228 dump_id[0] = '\0';
231 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
234 /* For a given DFI, open an alternate dump filename (which could also
235 be a standard stream such as stdout/stderr). If the alternate dump
236 file cannot be opened, return NULL. */
238 static FILE *
239 dump_open_alternate_stream (struct dump_file_info *dfi)
241 FILE *stream ;
242 if (!dfi->alt_filename)
243 return NULL;
245 if (dfi->alt_stream)
246 return dfi->alt_stream;
248 stream = strcmp ("stderr", dfi->alt_filename) == 0
249 ? stderr
250 : strcmp ("stdout", dfi->alt_filename) == 0
251 ? stdout
252 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
254 if (!stream)
255 error ("could not open dump file %qs: %m", dfi->alt_filename);
256 else
257 dfi->alt_state = 1;
259 return stream;
262 /* Print source location on DFILE if enabled. */
264 void
265 dump_loc (int dump_kind, FILE *dfile, source_location loc)
267 if (dump_kind)
269 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
270 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
271 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
272 else if (current_function_decl)
273 fprintf (dfile, "%s:%d:%d: note: ",
274 DECL_SOURCE_FILE (current_function_decl),
275 DECL_SOURCE_LINE (current_function_decl),
276 DECL_SOURCE_COLUMN (current_function_decl));
280 /* Dump gimple statement GS with SPC indentation spaces and
281 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
283 void
284 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
286 if (dump_file && (dump_kind & pflags))
287 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
289 if (alt_dump_file && (dump_kind & alt_flags))
290 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
293 /* Similar to dump_gimple_stmt, except additionally print source location. */
295 void
296 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
297 gimple gs, int spc)
299 if (dump_file && (dump_kind & pflags))
301 dump_loc (dump_kind, dump_file, loc);
302 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
305 if (alt_dump_file && (dump_kind & alt_flags))
307 dump_loc (dump_kind, alt_dump_file, loc);
308 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
312 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
313 DUMP_KIND is enabled. */
315 void
316 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
318 if (dump_file && (dump_kind & pflags))
319 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
321 if (alt_dump_file && (dump_kind & alt_flags))
322 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
326 /* Similar to dump_generic_expr, except additionally print the source
327 location. */
329 void
330 dump_generic_expr_loc (int dump_kind, source_location loc,
331 int extra_dump_flags, tree t)
333 if (dump_file && (dump_kind & pflags))
335 dump_loc (dump_kind, dump_file, loc);
336 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
339 if (alt_dump_file && (dump_kind & alt_flags))
341 dump_loc (dump_kind, alt_dump_file, loc);
342 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
346 /* Output a formatted message using FORMAT on appropriate dump streams. */
348 void
349 dump_printf (int dump_kind, const char *format, ...)
351 if (dump_file && (dump_kind & pflags))
353 va_list ap;
354 va_start (ap, format);
355 vfprintf (dump_file, format, ap);
356 va_end (ap);
359 if (alt_dump_file && (dump_kind & alt_flags))
361 va_list ap;
362 va_start (ap, format);
363 vfprintf (alt_dump_file, format, ap);
364 va_end (ap);
368 /* Similar to dump_printf, except source location is also printed. */
370 void
371 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
373 if (dump_file && (dump_kind & pflags))
375 va_list ap;
376 dump_loc (dump_kind, dump_file, loc);
377 va_start (ap, format);
378 vfprintf (dump_file, format, ap);
379 va_end (ap);
382 if (alt_dump_file && (dump_kind & alt_flags))
384 va_list ap;
385 dump_loc (dump_kind, alt_dump_file, loc);
386 va_start (ap, format);
387 vfprintf (alt_dump_file, format, ap);
388 va_end (ap);
392 /* Start a dump for PHASE. Store user-supplied dump flags in
393 *FLAG_PTR. Return the number of streams opened. Set globals
394 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
395 set dump_flags appropriately for both pass dump stream and
396 -fopt-info stream. */
399 gcc::dump_manager::
400 dump_start (int phase, int *flag_ptr)
402 int count = 0;
403 char *name;
404 struct dump_file_info *dfi;
405 FILE *stream;
406 if (phase == TDI_none || !dump_phase_enabled_p (phase))
407 return 0;
409 dfi = get_dump_file_info (phase);
410 name = get_dump_file_name (phase);
411 if (name)
413 stream = strcmp ("stderr", name) == 0
414 ? stderr
415 : strcmp ("stdout", name) == 0
416 ? stdout
417 : fopen (name, dfi->pstate < 0 ? "w" : "a");
418 if (!stream)
419 error ("could not open dump file %qs: %m", name);
420 else
422 dfi->pstate = 1;
423 count++;
425 free (name);
426 dfi->pstream = stream;
427 dump_file = dfi->pstream;
428 /* Initialize current dump flags. */
429 pflags = dfi->pflags;
432 stream = dump_open_alternate_stream (dfi);
433 if (stream)
435 dfi->alt_stream = stream;
436 count++;
437 alt_dump_file = dfi->alt_stream;
438 /* Initialize current -fopt-info flags. */
439 alt_flags = dfi->alt_flags;
442 if (flag_ptr)
443 *flag_ptr = dfi->pflags;
445 return count;
448 /* Finish a tree dump for PHASE and close associated dump streams. Also
449 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
451 void
452 gcc::dump_manager::
453 dump_finish (int phase)
455 struct dump_file_info *dfi;
457 if (phase < 0)
458 return;
459 dfi = get_dump_file_info (phase);
460 if (dfi->pstream && (!dfi->pfilename
461 || (strcmp ("stderr", dfi->pfilename) != 0
462 && strcmp ("stdout", dfi->pfilename) != 0)))
463 fclose (dfi->pstream);
465 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
466 && strcmp ("stdout", dfi->alt_filename) != 0)
467 fclose (dfi->alt_stream);
469 dfi->alt_stream = NULL;
470 dfi->pstream = NULL;
471 dump_file = NULL;
472 alt_dump_file = NULL;
473 dump_flags = TDI_none;
474 alt_flags = 0;
475 pflags = 0;
478 /* Begin a tree dump for PHASE. Stores any user supplied flag in
479 *FLAG_PTR and returns a stream to write to. If the dump is not
480 enabled, returns NULL.
481 Multiple calls will reopen and append to the dump file. */
483 FILE *
484 dump_begin (int phase, int *flag_ptr)
486 return g->get_dumps ()->dump_begin (phase, flag_ptr);
489 FILE *
490 gcc::dump_manager::
491 dump_begin (int phase, int *flag_ptr)
493 char *name;
494 struct dump_file_info *dfi;
495 FILE *stream;
497 if (phase == TDI_none || !dump_phase_enabled_p (phase))
498 return NULL;
500 name = get_dump_file_name (phase);
501 if (!name)
502 return NULL;
503 dfi = get_dump_file_info (phase);
505 stream = strcmp ("stderr", name) == 0
506 ? stderr
507 : strcmp ("stdout", name) == 0
508 ? stdout
509 : fopen (name, dfi->pstate < 0 ? "w" : "a");
511 if (!stream)
512 error ("could not open dump file %qs: %m", name);
513 else
514 dfi->pstate = 1;
515 free (name);
517 if (flag_ptr)
518 *flag_ptr = dfi->pflags;
520 /* Initialize current flags */
521 pflags = dfi->pflags;
522 return stream;
525 /* Returns nonzero if dump PHASE is enabled for at least one stream.
526 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
527 any phase. */
530 gcc::dump_manager::
531 dump_phase_enabled_p (int phase) const
533 if (phase == TDI_tree_all)
535 size_t i;
536 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
537 if (dump_files[i].pstate || dump_files[i].alt_state)
538 return 1;
539 for (i = 0; i < m_extra_dump_files_in_use; i++)
540 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
541 return 1;
542 return 0;
544 else
546 struct dump_file_info *dfi = get_dump_file_info (phase);
547 return dfi->pstate || dfi->alt_state;
551 /* Returns nonzero if tree dump PHASE has been initialized. */
554 gcc::dump_manager::
555 dump_initialized_p (int phase) const
557 struct dump_file_info *dfi = get_dump_file_info (phase);
558 return dfi->pstate > 0 || dfi->alt_state > 0;
561 /* Returns the switch name of PHASE. */
563 const char *
564 dump_flag_name (int phase)
566 return g->get_dumps ()->dump_flag_name (phase);
569 const char *
570 gcc::dump_manager::
571 dump_flag_name (int phase) const
573 struct dump_file_info *dfi = get_dump_file_info (phase);
574 return dfi->swtch;
577 /* Finish a tree dump for PHASE. STREAM is the stream created by
578 dump_begin. */
580 void
581 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
583 if (stream != stderr && stream != stdout)
584 fclose (stream);
587 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
588 enabled tree dumps. */
591 gcc::dump_manager::
592 dump_enable_all (int flags, const char *filename)
594 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
595 int n = 0;
596 size_t i;
598 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
600 if ((dump_files[i].pflags & ir_dump_type))
602 const char *old_filename = dump_files[i].pfilename;
603 dump_files[i].pstate = -1;
604 dump_files[i].pflags |= flags;
605 n++;
606 /* Override the existing filename. */
607 if (filename)
609 dump_files[i].pfilename = xstrdup (filename);
610 /* Since it is a command-line provided file, which is
611 common to all the phases, use it in append mode. */
612 dump_files[i].pstate = 1;
614 if (old_filename && filename != old_filename)
615 free (CONST_CAST (char *, old_filename));
619 for (i = 0; i < m_extra_dump_files_in_use; i++)
621 if ((m_extra_dump_files[i].pflags & ir_dump_type))
623 const char *old_filename = m_extra_dump_files[i].pfilename;
624 m_extra_dump_files[i].pstate = -1;
625 m_extra_dump_files[i].pflags |= flags;
626 n++;
627 /* Override the existing filename. */
628 if (filename)
630 m_extra_dump_files[i].pfilename = xstrdup (filename);
631 /* Since it is a command-line provided file, which is
632 common to all the phases, use it in append mode. */
633 m_extra_dump_files[i].pstate = 1;
635 if (old_filename && filename != old_filename)
636 free (CONST_CAST (char *, old_filename));
640 return n;
643 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
644 Enable dumps with FLAGS on FILENAME. Return the number of enabled
645 dumps. */
648 gcc::dump_manager::
649 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
651 int n = 0;
652 size_t i;
654 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
656 if ((dump_files[i].optgroup_flags & optgroup_flags))
658 const char *old_filename = dump_files[i].alt_filename;
659 /* Since this file is shared among different passes, it
660 should be opened in append mode. */
661 dump_files[i].alt_state = 1;
662 dump_files[i].alt_flags |= flags;
663 n++;
664 /* Override the existing filename. */
665 if (filename)
666 dump_files[i].alt_filename = xstrdup (filename);
667 if (old_filename && filename != old_filename)
668 free (CONST_CAST (char *, old_filename));
672 for (i = 0; i < m_extra_dump_files_in_use; i++)
674 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
676 const char *old_filename = m_extra_dump_files[i].alt_filename;
677 /* Since this file is shared among different passes, it
678 should be opened in append mode. */
679 m_extra_dump_files[i].alt_state = 1;
680 m_extra_dump_files[i].alt_flags |= flags;
681 n++;
682 /* Override the existing filename. */
683 if (filename)
684 m_extra_dump_files[i].alt_filename = xstrdup (filename);
685 if (old_filename && filename != old_filename)
686 free (CONST_CAST (char *, old_filename));
690 return n;
693 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
694 relevant details in the dump_files array. */
697 gcc::dump_manager::
698 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
700 const char *option_value;
701 const char *ptr;
702 int flags;
704 if (doglob && !dfi->glob)
705 return 0;
707 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
708 if (!option_value)
709 return 0;
711 if (*option_value && *option_value != '-' && *option_value != '=')
712 return 0;
714 ptr = option_value;
715 flags = 0;
717 while (*ptr)
719 const struct dump_option_value_info *option_ptr;
720 const char *end_ptr;
721 const char *eq_ptr;
722 unsigned length;
724 while (*ptr == '-')
725 ptr++;
726 end_ptr = strchr (ptr, '-');
727 eq_ptr = strchr (ptr, '=');
729 if (eq_ptr && !end_ptr)
730 end_ptr = eq_ptr;
732 if (!end_ptr)
733 end_ptr = ptr + strlen (ptr);
734 length = end_ptr - ptr;
736 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
737 if (strlen (option_ptr->name) == length
738 && !memcmp (option_ptr->name, ptr, length))
740 flags |= option_ptr->value;
741 goto found;
744 if (*ptr == '=')
746 /* Interpret rest of the argument as a dump filename. This
747 filename overrides other command line filenames. */
748 if (dfi->pfilename)
749 free (CONST_CAST (char *, dfi->pfilename));
750 dfi->pfilename = xstrdup (ptr + 1);
751 break;
753 else
754 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
755 length, ptr, dfi->swtch);
756 found:;
757 ptr = end_ptr;
760 dfi->pstate = -1;
761 dfi->pflags |= flags;
763 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
764 known dumps. */
765 if (dfi->suffix == NULL)
766 dump_enable_all (dfi->pflags, dfi->pfilename);
768 return 1;
772 gcc::dump_manager::
773 dump_switch_p (const char *arg)
775 size_t i;
776 int any = 0;
778 for (i = TDI_none + 1; i != TDI_end; i++)
779 any |= dump_switch_p_1 (arg, &dump_files[i], false);
781 /* Don't glob if we got a hit already */
782 if (!any)
783 for (i = TDI_none + 1; i != TDI_end; i++)
784 any |= dump_switch_p_1 (arg, &dump_files[i], true);
786 for (i = 0; i < m_extra_dump_files_in_use; i++)
787 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
789 if (!any)
790 for (i = 0; i < m_extra_dump_files_in_use; i++)
791 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
794 return any;
797 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
798 and filename. Return non-zero if it is a recognized switch. */
800 static int
801 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
802 char **filename)
804 const char *option_value;
805 const char *ptr;
807 option_value = arg;
808 ptr = option_value;
810 *filename = NULL;
811 *flags = 0;
812 *optgroup_flags = 0;
814 if (!ptr)
815 return 1; /* Handle '-fopt-info' without any additional options. */
817 while (*ptr)
819 const struct dump_option_value_info *option_ptr;
820 const char *end_ptr;
821 const char *eq_ptr;
822 unsigned length;
824 while (*ptr == '-')
825 ptr++;
826 end_ptr = strchr (ptr, '-');
827 eq_ptr = strchr (ptr, '=');
829 if (eq_ptr && !end_ptr)
830 end_ptr = eq_ptr;
832 if (!end_ptr)
833 end_ptr = ptr + strlen (ptr);
834 length = end_ptr - ptr;
836 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
837 option_ptr++)
838 if (strlen (option_ptr->name) == length
839 && !memcmp (option_ptr->name, ptr, length))
841 *flags |= option_ptr->value;
842 goto found;
845 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
846 if (strlen (option_ptr->name) == length
847 && !memcmp (option_ptr->name, ptr, length))
849 *optgroup_flags |= option_ptr->value;
850 goto found;
853 if (*ptr == '=')
855 /* Interpret rest of the argument as a dump filename. This
856 filename overrides other command line filenames. */
857 *filename = xstrdup (ptr + 1);
858 break;
860 else
862 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
863 length, ptr, arg);
864 return 0;
866 found:;
867 ptr = end_ptr;
870 return 1;
873 /* Return non-zero if ARG is a recognized switch for
874 -fopt-info. Return zero otherwise. */
877 opt_info_switch_p (const char *arg)
879 int flags;
880 int optgroup_flags;
881 char *filename;
882 static char *file_seen = NULL;
883 gcc::dump_manager *dumps = g->get_dumps ();
885 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
886 return 0;
888 if (!filename)
889 filename = xstrdup ("stderr");
891 /* Bail out if a different filename has been specified. */
892 if (file_seen && strcmp (file_seen, filename))
894 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
895 arg);
896 return 1;
899 file_seen = xstrdup (filename);
900 if (!flags)
901 flags = MSG_OPTIMIZED_LOCATIONS;
902 if (!optgroup_flags)
903 optgroup_flags = OPTGROUP_ALL;
905 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
908 /* Print basic block on the dump streams. */
910 void
911 dump_basic_block (int dump_kind, basic_block bb, int indent)
913 if (dump_file && (dump_kind & pflags))
914 dump_bb (dump_file, bb, indent, TDF_DETAILS);
915 if (alt_dump_file && (dump_kind & alt_flags))
916 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
919 /* Print information from the combine pass on dump_file. */
921 void
922 print_combine_total_stats (void)
924 if (dump_file)
925 dump_combine_total_stats (dump_file);
928 /* Enable RTL dump for all the RTL passes. */
930 bool
931 enable_rtl_dump_file (void)
933 gcc::dump_manager *dumps = g->get_dumps ();
934 int num_enabled =
935 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
936 return num_enabled > 0;