re PR c++/58516 (ICE with __transaction_atomic)
[official-gcc.git] / gcc / dumpfile.c
blobdc87ab35e8c87e575db08eb1788e53eac85bd99d
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2013 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 "gimple-pretty-print.h"
26 #include "tree.h"
28 /* If non-NULL, return one past-the-end of the matching SUBPART of
29 the WHOLE string. */
30 #define skip_leading_substring(whole, part) \
31 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
33 static int pflags; /* current dump_flags */
34 static int alt_flags; /* current opt_info flags */
36 static void dump_loc (int, FILE *, source_location);
37 static int dump_phase_enabled_p (int);
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 /* Dynamically registered tree dump files and switches. */
78 static struct dump_file_info *extra_dump_files;
79 static size_t extra_dump_files_in_use;
80 static size_t extra_dump_files_alloced;
82 /* Define a name->number mapping for a dump flag value. */
83 struct dump_option_value_info
85 const char *const name; /* the name of the value */
86 const int value; /* the value of the name */
89 /* Table of dump options. This must be consistent with the TDF_* flags
90 in dumpfile.h and opt_info_options below. */
91 static const struct dump_option_value_info dump_options[] =
93 {"address", TDF_ADDRESS},
94 {"asmname", TDF_ASMNAME},
95 {"slim", TDF_SLIM},
96 {"raw", TDF_RAW},
97 {"graph", TDF_GRAPH},
98 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
99 | MSG_MISSED_OPTIMIZATION
100 | MSG_NOTE)},
101 {"cselib", TDF_CSELIB},
102 {"stats", TDF_STATS},
103 {"blocks", TDF_BLOCKS},
104 {"vops", TDF_VOPS},
105 {"lineno", TDF_LINENO},
106 {"uid", TDF_UID},
107 {"stmtaddr", TDF_STMTADDR},
108 {"memsyms", TDF_MEMSYMS},
109 {"verbose", TDF_VERBOSE},
110 {"eh", TDF_EH},
111 {"alias", TDF_ALIAS},
112 {"nouid", TDF_NOUID},
113 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
114 {"scev", TDF_SCEV},
115 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
116 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
117 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
118 {NULL, 0}
121 /* A subset of the dump_options table which is used for -fopt-info
122 types. This must be consistent with the MSG_* flags in dumpfile.h.
124 static const struct dump_option_value_info optinfo_verbosity_options[] =
126 {"optimized", MSG_OPTIMIZED_LOCATIONS},
127 {"missed", MSG_MISSED_OPTIMIZATION},
128 {"note", MSG_NOTE},
129 {"all", MSG_ALL},
130 {NULL, 0}
133 /* Flags used for -fopt-info groups. */
134 static const struct dump_option_value_info optgroup_options[] =
136 {"ipa", OPTGROUP_IPA},
137 {"loop", OPTGROUP_LOOP},
138 {"inline", OPTGROUP_INLINE},
139 {"vec", OPTGROUP_VEC},
140 {"optall", OPTGROUP_ALL},
141 {NULL, 0}
144 unsigned int
145 dump_register (const char *suffix, const char *swtch, const char *glob,
146 int flags, int optgroup_flags)
148 static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
149 int num = next_dump++;
151 size_t count = extra_dump_files_in_use++;
153 if (count >= extra_dump_files_alloced)
155 if (extra_dump_files_alloced == 0)
156 extra_dump_files_alloced = 32;
157 else
158 extra_dump_files_alloced *= 2;
159 extra_dump_files = XRESIZEVEC (struct dump_file_info,
160 extra_dump_files,
161 extra_dump_files_alloced);
164 memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
165 extra_dump_files[count].suffix = suffix;
166 extra_dump_files[count].swtch = swtch;
167 extra_dump_files[count].glob = glob;
168 extra_dump_files[count].pflags = flags;
169 extra_dump_files[count].optgroup_flags = optgroup_flags;
170 extra_dump_files[count].num = num;
172 return count + TDI_end;
176 /* Return the dump_file_info for the given phase. */
178 struct dump_file_info *
179 get_dump_file_info (int phase)
181 if (phase < TDI_end)
182 return &dump_files[phase];
183 else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
184 return NULL;
185 else
186 return extra_dump_files + (phase - TDI_end);
190 /* Return the name of the dump file for the given phase.
191 If the dump is not enabled, returns NULL. */
193 char *
194 get_dump_file_name (int phase)
196 char dump_id[10];
197 struct dump_file_info *dfi;
199 if (phase == TDI_none)
200 return NULL;
202 dfi = get_dump_file_info (phase);
203 if (dfi->pstate == 0)
204 return NULL;
206 /* If available, use the command line dump filename. */
207 if (dfi->pfilename)
208 return xstrdup (dfi->pfilename);
210 if (dfi->num < 0)
211 dump_id[0] = '\0';
212 else
214 char suffix;
215 if (dfi->pflags & TDF_TREE)
216 suffix = 't';
217 else if (dfi->pflags & TDF_IPA)
218 suffix = 'i';
219 else
220 suffix = 'r';
222 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
223 dump_id[0] = '\0';
226 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
229 /* For a given DFI, open an alternate dump filename (which could also
230 be a standard stream such as stdout/stderr). If the alternate dump
231 file cannot be opened, return NULL. */
233 static FILE *
234 dump_open_alternate_stream (struct dump_file_info *dfi)
236 FILE *stream ;
237 if (!dfi->alt_filename)
238 return NULL;
240 if (dfi->alt_stream)
241 return dfi->alt_stream;
243 stream = strcmp("stderr", dfi->alt_filename) == 0
244 ? stderr
245 : strcmp("stdout", dfi->alt_filename) == 0
246 ? stdout
247 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
249 if (!stream)
250 error ("could not open dump file %qs: %m", dfi->alt_filename);
251 else
252 dfi->alt_state = 1;
254 return stream;
257 /* Print source location on DFILE if enabled. */
259 void
260 dump_loc (int dump_kind, FILE *dfile, source_location loc)
262 if (dump_kind)
264 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
265 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
266 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
267 else if (current_function_decl)
268 fprintf (dfile, "%s:%d:%d: note: ",
269 DECL_SOURCE_FILE (current_function_decl),
270 DECL_SOURCE_LINE (current_function_decl),
271 DECL_SOURCE_COLUMN (current_function_decl));
275 /* Dump gimple statement GS with SPC indentation spaces and
276 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
278 void
279 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
281 if (dump_file && (dump_kind & pflags))
282 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
284 if (alt_dump_file && (dump_kind & alt_flags))
285 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
288 /* Similar to dump_gimple_stmt, except additionally print source location. */
290 void
291 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
292 gimple gs, int spc)
294 if (dump_file && (dump_kind & pflags))
296 dump_loc (dump_kind, dump_file, loc);
297 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
300 if (alt_dump_file && (dump_kind & alt_flags))
302 dump_loc (dump_kind, alt_dump_file, loc);
303 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
307 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
308 DUMP_KIND is enabled. */
310 void
311 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
313 if (dump_file && (dump_kind & pflags))
314 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
316 if (alt_dump_file && (dump_kind & alt_flags))
317 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
321 /* Similar to dump_generic_expr, except additionally print the source
322 location. */
324 void
325 dump_generic_expr_loc (int dump_kind, source_location loc,
326 int extra_dump_flags, tree t)
328 if (dump_file && (dump_kind & pflags))
330 dump_loc (dump_kind, dump_file, loc);
331 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
334 if (alt_dump_file && (dump_kind & alt_flags))
336 dump_loc (dump_kind, alt_dump_file, loc);
337 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
341 /* Output a formatted message using FORMAT on appropriate dump streams. */
343 void
344 dump_printf (int dump_kind, const char *format, ...)
346 if (dump_file && (dump_kind & pflags))
348 va_list ap;
349 va_start (ap, format);
350 vfprintf (dump_file, format, ap);
351 va_end (ap);
354 if (alt_dump_file && (dump_kind & alt_flags))
356 va_list ap;
357 va_start (ap, format);
358 vfprintf (alt_dump_file, format, ap);
359 va_end (ap);
363 /* Similar to dump_printf, except source location is also printed. */
365 void
366 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
368 if (dump_file && (dump_kind & pflags))
370 va_list ap;
371 dump_loc (dump_kind, dump_file, loc);
372 va_start (ap, format);
373 vfprintf (dump_file, format, ap);
374 va_end (ap);
377 if (alt_dump_file && (dump_kind & alt_flags))
379 va_list ap;
380 dump_loc (dump_kind, alt_dump_file, loc);
381 va_start (ap, format);
382 vfprintf (alt_dump_file, format, ap);
383 va_end (ap);
387 /* Start a dump for PHASE. Store user-supplied dump flags in
388 *FLAG_PTR. Return the number of streams opened. Set globals
389 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
390 set dump_flags appropriately for both pass dump stream and
391 -fopt-info stream. */
394 dump_start (int phase, int *flag_ptr)
396 int count = 0;
397 char *name;
398 struct dump_file_info *dfi;
399 FILE *stream;
400 if (phase == TDI_none || !dump_phase_enabled_p (phase))
401 return 0;
403 dfi = get_dump_file_info (phase);
404 name = get_dump_file_name (phase);
405 if (name)
407 stream = strcmp("stderr", name) == 0
408 ? stderr
409 : strcmp("stdout", name) == 0
410 ? stdout
411 : fopen (name, dfi->pstate < 0 ? "w" : "a");
412 if (!stream)
413 error ("could not open dump file %qs: %m", name);
414 else
416 dfi->pstate = 1;
417 count++;
419 free (name);
420 dfi->pstream = stream;
421 dump_file = dfi->pstream;
422 /* Initialize current dump flags. */
423 pflags = dfi->pflags;
426 stream = dump_open_alternate_stream (dfi);
427 if (stream)
429 dfi->alt_stream = stream;
430 count++;
431 alt_dump_file = dfi->alt_stream;
432 /* Initialize current -fopt-info flags. */
433 alt_flags = dfi->alt_flags;
436 if (flag_ptr)
437 *flag_ptr = dfi->pflags;
439 return count;
442 /* Finish a tree dump for PHASE and close associated dump streams. Also
443 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
445 void
446 dump_finish (int phase)
448 struct dump_file_info *dfi;
450 if (phase < 0)
451 return;
452 dfi = get_dump_file_info (phase);
453 if (dfi->pstream && (!dfi->pfilename
454 || (strcmp("stderr", dfi->pfilename) != 0
455 && strcmp("stdout", dfi->pfilename) != 0)))
456 fclose (dfi->pstream);
458 if (dfi->alt_stream && strcmp("stderr", dfi->alt_filename) != 0
459 && strcmp("stdout", dfi->alt_filename) != 0)
460 fclose (dfi->alt_stream);
462 dfi->alt_stream = NULL;
463 dfi->pstream = NULL;
464 dump_file = NULL;
465 alt_dump_file = NULL;
466 dump_flags = TDI_none;
467 alt_flags = 0;
468 pflags = 0;
471 /* Begin a tree dump for PHASE. Stores any user supplied flag in
472 *FLAG_PTR and returns a stream to write to. If the dump is not
473 enabled, returns NULL.
474 Multiple calls will reopen and append to the dump file. */
476 FILE *
477 dump_begin (int phase, int *flag_ptr)
479 char *name;
480 struct dump_file_info *dfi;
481 FILE *stream;
483 if (phase == TDI_none || !dump_phase_enabled_p (phase))
484 return NULL;
486 name = get_dump_file_name (phase);
487 if (!name)
488 return NULL;
489 dfi = get_dump_file_info (phase);
491 stream = strcmp("stderr", name) == 0
492 ? stderr
493 : strcmp("stdout", name) == 0
494 ? stdout
495 : fopen (name, dfi->pstate < 0 ? "w" : "a");
497 if (!stream)
498 error ("could not open dump file %qs: %m", name);
499 else
500 dfi->pstate = 1;
501 free (name);
503 if (flag_ptr)
504 *flag_ptr = dfi->pflags;
506 /* Initialize current flags */
507 pflags = dfi->pflags;
508 return stream;
511 /* Returns nonzero if dump PHASE is enabled for at least one stream.
512 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
513 any phase. */
515 static int
516 dump_phase_enabled_p (int phase)
518 if (phase == TDI_tree_all)
520 size_t i;
521 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
522 if (dump_files[i].pstate || dump_files[i].alt_state)
523 return 1;
524 for (i = 0; i < extra_dump_files_in_use; i++)
525 if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state)
526 return 1;
527 return 0;
529 else
531 struct dump_file_info *dfi = get_dump_file_info (phase);
532 return dfi->pstate || dfi->alt_state;
536 /* Returns nonzero if tree dump PHASE has been initialized. */
539 dump_initialized_p (int phase)
541 struct dump_file_info *dfi = get_dump_file_info (phase);
542 return dfi->pstate > 0 || dfi->alt_state > 0;
545 /* Returns the switch name of PHASE. */
547 const char *
548 dump_flag_name (int phase)
550 struct dump_file_info *dfi = get_dump_file_info (phase);
551 return dfi->swtch;
554 /* Finish a tree dump for PHASE. STREAM is the stream created by
555 dump_begin. */
557 void
558 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
560 if (stream != stderr && stream != stdout)
561 fclose (stream);
564 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
565 enabled tree dumps. */
567 static int
568 dump_enable_all (int flags, const char *filename)
570 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
571 int n = 0;
572 size_t i;
574 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
576 if ((dump_files[i].pflags & ir_dump_type))
578 const char *old_filename = dump_files[i].pfilename;
579 dump_files[i].pstate = -1;
580 dump_files[i].pflags |= flags;
581 n++;
582 /* Override the existing filename. */
583 if (filename)
585 dump_files[i].pfilename = xstrdup (filename);
586 /* Since it is a command-line provided file, which is
587 common to all the phases, use it in append mode. */
588 dump_files[i].pstate = 1;
590 if (old_filename && filename != old_filename)
591 free (CONST_CAST (char *, old_filename));
595 for (i = 0; i < extra_dump_files_in_use; i++)
597 if ((extra_dump_files[i].pflags & ir_dump_type))
599 const char *old_filename = extra_dump_files[i].pfilename;
600 extra_dump_files[i].pstate = -1;
601 extra_dump_files[i].pflags |= flags;
602 n++;
603 /* Override the existing filename. */
604 if (filename)
606 extra_dump_files[i].pfilename = xstrdup (filename);
607 /* Since it is a command-line provided file, which is
608 common to all the phases, use it in append mode. */
609 extra_dump_files[i].pstate = 1;
611 if (old_filename && filename != old_filename)
612 free (CONST_CAST (char *, old_filename));
616 return n;
619 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
620 Enable dumps with FLAGS on FILENAME. Return the number of enabled
621 dumps. */
623 static int
624 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
626 int n = 0;
627 size_t i;
629 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
631 if ((dump_files[i].optgroup_flags & optgroup_flags))
633 const char *old_filename = dump_files[i].alt_filename;
634 /* Since this file is shared among different passes, it
635 should be opened in append mode. */
636 dump_files[i].alt_state = 1;
637 dump_files[i].alt_flags |= flags;
638 n++;
639 /* Override the existing filename. */
640 if (filename)
641 dump_files[i].alt_filename = xstrdup (filename);
642 if (old_filename && filename != old_filename)
643 free (CONST_CAST (char *, old_filename));
647 for (i = 0; i < extra_dump_files_in_use; i++)
649 if ((extra_dump_files[i].optgroup_flags & optgroup_flags))
651 const char *old_filename = extra_dump_files[i].alt_filename;
652 /* Since this file is shared among different passes, it
653 should be opened in append mode. */
654 extra_dump_files[i].alt_state = 1;
655 extra_dump_files[i].alt_flags |= flags;
656 n++;
657 /* Override the existing filename. */
658 if (filename)
659 extra_dump_files[i].alt_filename = xstrdup (filename);
660 if (old_filename && filename != old_filename)
661 free (CONST_CAST (char *, old_filename));
665 return n;
668 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
669 relevant details in the dump_files array. */
671 static int
672 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
674 const char *option_value;
675 const char *ptr;
676 int flags;
678 if (doglob && !dfi->glob)
679 return 0;
681 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
682 if (!option_value)
683 return 0;
685 if (*option_value && *option_value != '-' && *option_value != '=')
686 return 0;
688 ptr = option_value;
689 flags = 0;
691 while (*ptr)
693 const struct dump_option_value_info *option_ptr;
694 const char *end_ptr;
695 const char *eq_ptr;
696 unsigned length;
698 while (*ptr == '-')
699 ptr++;
700 end_ptr = strchr (ptr, '-');
701 eq_ptr = strchr (ptr, '=');
703 if (eq_ptr && !end_ptr)
704 end_ptr = eq_ptr;
706 if (!end_ptr)
707 end_ptr = ptr + strlen (ptr);
708 length = end_ptr - ptr;
710 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
711 if (strlen (option_ptr->name) == length
712 && !memcmp (option_ptr->name, ptr, length))
714 flags |= option_ptr->value;
715 goto found;
718 if (*ptr == '=')
720 /* Interpret rest of the argument as a dump filename. This
721 filename overrides other command line filenames. */
722 if (dfi->pfilename)
723 free (CONST_CAST (char *, dfi->pfilename));
724 dfi->pfilename = xstrdup (ptr + 1);
725 break;
727 else
728 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
729 length, ptr, dfi->swtch);
730 found:;
731 ptr = end_ptr;
734 dfi->pstate = -1;
735 dfi->pflags |= flags;
737 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
738 known dumps. */
739 if (dfi->suffix == NULL)
740 dump_enable_all (dfi->pflags, dfi->pfilename);
742 return 1;
746 dump_switch_p (const char *arg)
748 size_t i;
749 int any = 0;
751 for (i = TDI_none + 1; i != TDI_end; i++)
752 any |= dump_switch_p_1 (arg, &dump_files[i], false);
754 /* Don't glob if we got a hit already */
755 if (!any)
756 for (i = TDI_none + 1; i != TDI_end; i++)
757 any |= dump_switch_p_1 (arg, &dump_files[i], true);
759 for (i = 0; i < extra_dump_files_in_use; i++)
760 any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
762 if (!any)
763 for (i = 0; i < extra_dump_files_in_use; i++)
764 any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
767 return any;
770 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
771 and filename. Return non-zero if it is a recognized switch. */
773 static int
774 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
775 char **filename)
777 const char *option_value;
778 const char *ptr;
780 option_value = arg;
781 ptr = option_value;
783 *filename = NULL;
784 *flags = 0;
785 *optgroup_flags = 0;
787 if (!ptr)
788 return 1; /* Handle '-fopt-info' without any additional options. */
790 while (*ptr)
792 const struct dump_option_value_info *option_ptr;
793 const char *end_ptr;
794 const char *eq_ptr;
795 unsigned length;
797 while (*ptr == '-')
798 ptr++;
799 end_ptr = strchr (ptr, '-');
800 eq_ptr = strchr (ptr, '=');
802 if (eq_ptr && !end_ptr)
803 end_ptr = eq_ptr;
805 if (!end_ptr)
806 end_ptr = ptr + strlen (ptr);
807 length = end_ptr - ptr;
809 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
810 option_ptr++)
811 if (strlen (option_ptr->name) == length
812 && !memcmp (option_ptr->name, ptr, length))
814 *flags |= option_ptr->value;
815 goto found;
818 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
819 if (strlen (option_ptr->name) == length
820 && !memcmp (option_ptr->name, ptr, length))
822 *optgroup_flags |= option_ptr->value;
823 goto found;
826 if (*ptr == '=')
828 /* Interpret rest of the argument as a dump filename. This
829 filename overrides other command line filenames. */
830 *filename = xstrdup (ptr + 1);
831 break;
833 else
835 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
836 length, ptr, arg);
837 return 0;
839 found:;
840 ptr = end_ptr;
843 return 1;
846 /* Return non-zero if ARG is a recognized switch for
847 -fopt-info. Return zero otherwise. */
850 opt_info_switch_p (const char *arg)
852 int flags;
853 int optgroup_flags;
854 char *filename;
855 static char *file_seen = NULL;
857 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
858 return 0;
860 if (!filename)
861 filename = xstrdup ("stderr");
863 /* Bail out if a different filename has been specified. */
864 if (file_seen && strcmp (file_seen, filename))
866 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
867 arg);
868 return 1;
871 file_seen = xstrdup (filename);
872 if (!flags)
873 flags = MSG_OPTIMIZED_LOCATIONS;
874 if (!optgroup_flags)
875 optgroup_flags = OPTGROUP_ALL;
877 return opt_info_enable_passes (optgroup_flags, flags, filename);
880 /* Print basic block on the dump streams. */
882 void
883 dump_basic_block (int dump_kind, basic_block bb, int indent)
885 if (dump_file && (dump_kind & pflags))
886 dump_bb (dump_file, bb, indent, TDF_DETAILS);
887 if (alt_dump_file && (dump_kind & alt_flags))
888 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
891 /* Print information from the combine pass on dump_file. */
893 void
894 print_combine_total_stats (void)
896 if (dump_file)
897 dump_combine_total_stats (dump_file);
900 /* Enable RTL dump for all the RTL passes. */
902 bool
903 enable_rtl_dump_file (void)
905 return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;