OSDN Git Service

2012-10-08 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / dumpfile.c
1 /* Dump infrastructure for optimizations and intermediate representation.
2    Copyright (C) 2012 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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/>.  */
19
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"
27
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))
32
33 static int pflags;                   /* current dump_flags */
34 static int alt_flags;                /* current opt_info flags */
35 static FILE *alt_dump_file = NULL;
36
37 static void dump_loc (int, FILE *, source_location);
38 static int dump_enabled_p (int);
39 static FILE *dump_open_alternate_stream (struct dump_file_info *);
40
41 /* Table of tree dump switches. This must be consistent with the
42    TREE_DUMP_INDEX enumeration in dumpfile.h.  */
43 static struct dump_file_info dump_files[TDI_end] =
44 {
45   {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0},
46   {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
47    0, 0, 0, 0},
48   {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
49    0, 0, 0, 1},
50   {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
51    0, 0, 0, 2},
52   {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
53    0, 0, 0, 3},
54   {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
55    0, 0, 0, 4},
56   {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
57    0, 0, 0, 5},
58   {".vcg", "tree-vcg", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
59    0, 0, 0, 6},
60 #define FIRST_AUTO_NUMBERED_DUMP 7
61
62   {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
63    0, 0, 0, 0},
64   {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
65    0, 0, 0, 0},
66   {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
67    0, 0, 0, 0},
68 };
69
70 /* Dynamically registered tree dump files and switches.  */
71 static struct dump_file_info *extra_dump_files;
72 static size_t extra_dump_files_in_use;
73 static size_t extra_dump_files_alloced;
74
75 /* Define a name->number mapping for a dump flag value.  */
76 struct dump_option_value_info
77 {
78   const char *const name;       /* the name of the value */
79   const int value;              /* the value of the name */
80 };
81
82 /* Table of dump options. This must be consistent with the TDF_* flags
83    in dumpfile.h and opt_info_options below. */
84 static const struct dump_option_value_info dump_options[] =
85 {
86   {"address", TDF_ADDRESS},
87   {"asmname", TDF_ASMNAME},
88   {"slim", TDF_SLIM},
89   {"raw", TDF_RAW},
90   {"graph", TDF_GRAPH},
91   {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
92                | MSG_MISSED_OPTIMIZATION
93                | MSG_NOTE)},
94   {"cselib", TDF_CSELIB},
95   {"stats", TDF_STATS},
96   {"blocks", TDF_BLOCKS},
97   {"vops", TDF_VOPS},
98   {"lineno", TDF_LINENO},
99   {"uid", TDF_UID},
100   {"stmtaddr", TDF_STMTADDR},
101   {"memsyms", TDF_MEMSYMS},
102   {"verbose", TDF_VERBOSE},
103   {"eh", TDF_EH},
104   {"alias", TDF_ALIAS},
105   {"nouid", TDF_NOUID},
106   {"enumerate_locals", TDF_ENUMERATE_LOCALS},
107   {"scev", TDF_SCEV},
108   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
109             | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
110             | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
111   {NULL, 0}
112 };
113
114 /* A subset of the dump_options table which is used for opt-info
115    options. This must be consistent with the MSG_* flags in
116    dump_options.
117  */
118 static const struct dump_option_value_info opt_info_options[] =
119 {
120   {"optimized", MSG_OPTIMIZED_LOCATIONS},
121   {"missed", MSG_MISSED_OPTIMIZATION},
122   {"note", MSG_NOTE},
123   {"optall", (MSG_OPTIMIZED_LOCATIONS
124            | MSG_MISSED_OPTIMIZATION
125            | MSG_NOTE)},
126   {NULL, 0}
127 };
128
129 unsigned int
130 dump_register (const char *suffix, const char *swtch, const char *glob,
131                int flags)
132 {
133   static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
134   int num = next_dump++;
135
136   size_t count = extra_dump_files_in_use++;
137
138   if (count >= extra_dump_files_alloced)
139     {
140       if (extra_dump_files_alloced == 0)
141         extra_dump_files_alloced = 32;
142       else
143         extra_dump_files_alloced *= 2;
144       extra_dump_files = XRESIZEVEC (struct dump_file_info,
145                                      extra_dump_files,
146                                      extra_dump_files_alloced);
147     }
148
149   memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
150   extra_dump_files[count].suffix = suffix;
151   extra_dump_files[count].swtch = swtch;
152   extra_dump_files[count].glob = glob;
153   extra_dump_files[count].pflags = flags;
154   extra_dump_files[count].num = num;
155
156   return count + TDI_end;
157 }
158
159
160 /* Return the dump_file_info for the given phase.  */
161
162 struct dump_file_info *
163 get_dump_file_info (int phase)
164 {
165   if (phase < TDI_end)
166     return &dump_files[phase];
167   else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
168     return NULL;
169   else
170     return extra_dump_files + (phase - TDI_end);
171 }
172
173
174 /* Return the name of the dump file for the given phase.
175    If the dump is not enabled, returns NULL.  */
176
177 char *
178 get_dump_file_name (int phase)
179 {
180   char dump_id[10];
181   struct dump_file_info *dfi;
182
183   if (phase == TDI_none)
184     return NULL;
185
186   dfi = get_dump_file_info (phase);
187   if (dfi->pstate == 0)
188     return NULL;
189
190   /* If available, use the command line dump filename. */
191   if (dfi->pfilename)
192     return xstrdup (dfi->pfilename);
193
194   if (dfi->num < 0)
195     dump_id[0] = '\0';
196   else
197     {
198       char suffix;
199       if (dfi->pflags & TDF_TREE)
200         suffix = 't';
201       else if (dfi->pflags & TDF_IPA)
202         suffix = 'i';
203       else
204         suffix = 'r';
205
206       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
207         dump_id[0] = '\0';
208     }
209
210   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
211 }
212
213 /* For a given DFI, open an alternate dump filename (which could also
214    be a standard stream such as stdout/stderr). If the alternate dump
215    file cannot be opened, return NULL.  */
216
217 static FILE *
218 dump_open_alternate_stream (struct dump_file_info *dfi)
219 {
220   FILE *stream ;
221   if (!dfi->alt_filename)
222     return NULL;
223
224   if (dfi->alt_stream)
225     return dfi->alt_stream;
226
227   stream = strcmp("stderr", dfi->alt_filename) == 0
228     ? stderr
229     : strcmp("stdout", dfi->alt_filename) == 0
230     ?  stdout
231     : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
232
233   if (!stream)
234     error ("could not open dump file %qs: %m", dfi->alt_filename);
235   else
236     dfi->alt_state = 1;
237
238   return stream;
239 }
240
241 /* Print source location on DFILE if enabled.  */
242
243 void
244 dump_loc (int dump_kind, FILE *dfile, source_location loc)
245 {
246   /* Currently vectorization passes print location information.  */
247   if (dump_kind)
248     {
249       if (loc == UNKNOWN_LOCATION)
250         fprintf (dfile, "\n%s:%d: note: ",
251                  DECL_SOURCE_FILE (current_function_decl),
252                  DECL_SOURCE_LINE (current_function_decl));
253      else
254         fprintf (dfile, "\n%d: ", LOCATION_LINE (loc));
255     }
256 }
257
258 /* Dump gimple statement GS with SPC indentation spaces and
259    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
260
261 void
262 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
263 {
264   if (dump_file && (dump_kind & pflags))
265     print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
266
267   if (alt_dump_file && (dump_kind & alt_flags))
268     print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
269 }
270
271 /* Similar to dump_gimple_stmt, except additionally print source location.  */
272
273 void
274 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
275                       gimple gs, int spc)
276 {
277   if (dump_file && (dump_kind & pflags))
278     {
279       dump_loc (dump_kind, dump_file, loc);
280       print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
281     }
282
283   if (alt_dump_file && (dump_kind & alt_flags))
284     {
285       dump_loc (dump_kind, alt_dump_file, loc);
286       print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
287     }
288 }
289
290 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
291    DUMP_KIND is enabled.  */
292
293 void
294 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
295 {
296   if (dump_file && (dump_kind & pflags))
297       print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
298
299   if (alt_dump_file && (dump_kind & alt_flags))
300       print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
301 }
302
303
304 /* Similar to dump_generic_expr, except additionally print the source
305    location.  */
306
307 void
308 dump_generic_expr_loc (int dump_kind, source_location loc,
309                        int extra_dump_flags, tree t)
310 {
311   if (dump_file && (dump_kind & pflags))
312     {
313       dump_loc (dump_kind, dump_file, loc);
314       print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
315     }
316
317   if (alt_dump_file && (dump_kind & alt_flags))
318     {
319       dump_loc (dump_kind, alt_dump_file, loc);
320       print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
321     }
322 }
323
324 /* Output a formatted message using FORMAT on appropriate dump streams.  */
325
326 void
327 dump_printf (int dump_kind, const char *format, ...)
328 {
329   if (dump_file && (dump_kind & pflags))
330     {
331       va_list ap;
332       va_start (ap, format);
333       vfprintf (dump_file, format, ap);
334       va_end (ap);
335     }
336
337   if (alt_dump_file && (dump_kind & alt_flags))
338     {
339       va_list ap;
340       va_start (ap, format);
341       vfprintf (alt_dump_file, format, ap);
342       va_end (ap);
343     }
344 }
345
346 /* Similar to dump_printf, except source location is also printed.  */
347
348 void
349 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
350 {
351   if (dump_file && (dump_kind & pflags))
352     {
353       va_list ap;
354       dump_loc (dump_kind, dump_file, loc);
355       va_start (ap, format);
356       vfprintf (dump_file, format, ap);
357       va_end (ap);
358     }
359
360   if (alt_dump_file && (dump_kind & alt_flags))
361     {
362       va_list ap;
363       dump_loc (dump_kind, alt_dump_file, loc);
364       va_start (ap, format);
365       vfprintf (alt_dump_file, format, ap);
366       va_end (ap);
367     }
368 }
369
370 /* Start a dump for PHASE. Store user-supplied dump flags in
371    *FLAG_PTR.  Return the number of streams opened.  Set globals
372    DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
373    set dump_flags appropriately for both pass dump stream and opt-info
374    stream. */
375
376 int
377 dump_start (int phase, int *flag_ptr)
378 {
379   int count = 0;
380   char *name;
381   struct dump_file_info *dfi;
382   FILE *stream;
383   if (phase == TDI_none || !dump_enabled_p (phase))
384     return 0;
385
386   dfi = get_dump_file_info (phase);
387   name = get_dump_file_name (phase);
388   if (name)
389     {
390       stream = strcmp("stderr", name) == 0
391           ? stderr
392           : strcmp("stdout", name) == 0
393           ?  stdout
394           : fopen (name, dfi->pstate < 0 ? "w" : "a");
395       if (!stream)
396         error ("could not open dump file %qs: %m", name);
397       else
398         {
399           dfi->pstate = 1;
400           count++;
401         }
402       free (name);
403       dfi->pstream = stream;
404       dump_file = dfi->pstream;
405       /* Initialize current dump flags. */
406       pflags = dfi->pflags;
407     }
408
409   stream = dump_open_alternate_stream (dfi);
410   if (stream)
411     {
412       dfi->alt_stream = stream;
413       count++;
414       alt_dump_file = dfi->alt_stream;
415       /* Initialize current opt-info flags. */
416       alt_flags = dfi->alt_flags;
417     }
418
419   if (flag_ptr)
420     *flag_ptr = dfi->pflags;
421
422   return count;
423 }
424
425 /* Finish a tree dump for PHASE and close associated dump streams.  Also
426    reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS.  */
427
428 void
429 dump_finish (int phase)
430 {
431   struct dump_file_info *dfi;
432
433   if (phase < 0)
434     return;
435   dfi = get_dump_file_info (phase);
436   if (dfi->pstream)
437     fclose (dfi->pstream);
438
439   if (dfi->alt_stream && strcmp("stderr", dfi->alt_filename) != 0
440       && strcmp("stdout", dfi->alt_filename) != 0)
441     fclose (dfi->alt_stream);
442
443   dfi->alt_stream = NULL;
444   dfi->pstream = NULL;
445   dump_file = NULL;
446   alt_dump_file = NULL;
447   dump_flags = TDI_none;
448   alt_flags = 0;
449   pflags = 0;
450 }
451
452 /* Begin a tree dump for PHASE. Stores any user supplied flag in
453    *FLAG_PTR and returns a stream to write to. If the dump is not
454    enabled, returns NULL.
455    Multiple calls will reopen and append to the dump file.  */
456
457 FILE *
458 dump_begin (int phase, int *flag_ptr)
459 {
460   char *name;
461   struct dump_file_info *dfi;
462   FILE *stream;
463
464   if (phase == TDI_none || !dump_enabled_p (phase))
465     return NULL;
466
467   name = get_dump_file_name (phase);
468   if (!name)
469     return NULL;
470   dfi = get_dump_file_info (phase);
471
472   stream = strcmp("stderr", name) == 0
473     ? stderr
474     : strcmp("stdout", name) == 0
475     ?  stdout
476     : fopen (name, dfi->pstate < 0 ? "w" : "a");
477
478   if (!stream)
479     error ("could not open dump file %qs: %m", name);
480   else
481     dfi->pstate = 1;
482   free (name);
483
484   if (flag_ptr)
485     *flag_ptr = dfi->pflags;
486
487   /* Initialize current flags */
488   pflags = dfi->pflags;
489   return stream;
490 }
491
492 /* Returns nonzero if dump PHASE is enabled for at least one stream.
493    If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
494    any phase.  */
495
496 int
497 dump_enabled_p (int phase)
498 {
499   if (phase == TDI_tree_all)
500     {
501       size_t i;
502       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
503         if (dump_files[i].pstate || dump_files[i].alt_state)
504           return 1;
505       for (i = 0; i < extra_dump_files_in_use; i++)
506         if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state)
507           return 1;
508       return 0;
509     }
510   else
511     {
512       struct dump_file_info *dfi = get_dump_file_info (phase);
513       return dfi->pstate || dfi->alt_state;
514     }
515 }
516
517 /* Returns nonzero if tree dump PHASE has been initialized.  */
518
519 int
520 dump_initialized_p (int phase)
521 {
522   struct dump_file_info *dfi = get_dump_file_info (phase);
523   return dfi->pstate > 0 || dfi->alt_state > 0;
524 }
525
526 /* Returns the switch name of PHASE.  */
527
528 const char *
529 dump_flag_name (int phase)
530 {
531   struct dump_file_info *dfi = get_dump_file_info (phase);
532   return dfi->swtch;
533 }
534
535 /* Finish a tree dump for PHASE. STREAM is the stream created by
536    dump_begin.  */
537
538 void
539 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
540 {
541   if (stream != stderr && stream != stdout)
542     fclose (stream);
543 }
544
545 /* Enable all tree dumps with FLAGS on FILENAME.  Return number of
546    enabled tree dumps.  */
547
548 static int
549 dump_enable_all (int flags, const char *filename)
550 {
551   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
552   int n = 0;
553   size_t i;
554
555   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
556     {
557       if ((dump_files[i].pflags & ir_dump_type))
558         {
559           const char *old_filename = dump_files[i].pfilename;
560           dump_files[i].pstate = -1;
561           dump_files[i].pflags |= flags;
562           n++;
563           /* Override the existing filename.  */
564           if (filename)
565             {
566               dump_files[i].pfilename = xstrdup (filename);
567               /* Since it is a command-line provided file, which is
568                  common to all the phases, use it in append mode.  */
569               dump_files[i].pstate = 1;
570             }
571           if (old_filename && filename != old_filename)
572             free (CONST_CAST (char *, old_filename));
573         }
574     }
575
576   for (i = 0; i < extra_dump_files_in_use; i++)
577     {
578       if ((extra_dump_files[i].pflags & ir_dump_type))
579         {
580           const char *old_filename = extra_dump_files[i].pfilename;
581           extra_dump_files[i].pstate = -1;
582           extra_dump_files[i].pflags |= flags;
583           n++;
584           /* Override the existing filename.  */
585           if (filename)
586             {
587               extra_dump_files[i].pfilename = xstrdup (filename);
588               /* Since it is a command-line provided file, which is
589                  common to all the phases, use it in append mode.  */
590               extra_dump_files[i].pstate = 1;
591             }
592           if (old_filename && filename != old_filename)
593             free (CONST_CAST (char *, old_filename));
594         }
595     }
596
597   return n;
598 }
599
600 /* Enable opt-info dumps on all IR_DUMP_TYPE passes with FLAGS on
601    FILENAME.  Return the number of enabled dumps.  */
602
603 static int
604 opt_info_enable_all (int ir_dump_type, int flags, const char *filename)
605 {
606   int n = 0;
607   size_t i;
608
609   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
610     {
611       if ((dump_files[i].pflags & ir_dump_type))
612         {
613           const char *old_filename = dump_files[i].alt_filename;
614           /* Since this file is shared among different passes, it
615              should be opened in append mode.  */
616           dump_files[i].alt_state = 1;
617           dump_files[i].alt_flags |= flags;
618           n++;
619           /* Override the existing filename.  */
620           if (filename)
621             dump_files[i].alt_filename = xstrdup (filename);
622           if (old_filename && filename != old_filename)
623             free (CONST_CAST (char *, old_filename));
624         }
625     }
626
627   for (i = 0; i < extra_dump_files_in_use; i++)
628     {
629       if ((extra_dump_files[i].pflags & ir_dump_type))
630         {
631           const char *old_filename = extra_dump_files[i].alt_filename;
632           /* Since this file is shared among different passes, it
633              should be opened in append mode.  */
634           extra_dump_files[i].alt_state = 1;
635           extra_dump_files[i].alt_flags |= flags;
636           n++;
637           /* Override the existing filename.  */
638           if (filename)
639             extra_dump_files[i].alt_filename = xstrdup (filename);
640           if (old_filename && filename != old_filename)
641             free (CONST_CAST (char *, old_filename));
642         }
643     }
644
645   return n;
646 }
647
648 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
649    relevant details in the dump_files array.  */
650
651 static int
652 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
653 {
654   const char *option_value;
655   const char *ptr;
656   int flags;
657
658   if (doglob && !dfi->glob)
659     return 0;
660
661   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
662   if (!option_value)
663     return 0;
664
665   if (*option_value && *option_value != '-' && *option_value != '=')
666     return 0;
667
668   ptr = option_value;
669   flags = 0;
670
671   while (*ptr)
672     {
673       const struct dump_option_value_info *option_ptr;
674       const char *end_ptr;
675       const char *eq_ptr;
676       unsigned length;
677
678       while (*ptr == '-')
679         ptr++;
680       end_ptr = strchr (ptr, '-');
681       eq_ptr = strchr (ptr, '=');
682
683       if (eq_ptr && !end_ptr)
684         end_ptr = eq_ptr;
685
686       if (!end_ptr)
687         end_ptr = ptr + strlen (ptr);
688       length = end_ptr - ptr;
689
690       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
691         if (strlen (option_ptr->name) == length
692             && !memcmp (option_ptr->name, ptr, length))
693           {
694             flags |= option_ptr->value;
695             goto found;
696           }
697
698       if (*ptr == '=')
699         {
700           /* Interpret rest of the argument as a dump filename.  This
701              filename overrides other command line filenames.  */
702           if (dfi->pfilename)
703             free (CONST_CAST (char *, dfi->pfilename));
704           dfi->pfilename = xstrdup (ptr + 1);
705           break;
706         }
707       else
708         warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
709                  length, ptr, dfi->swtch);
710     found:;
711       ptr = end_ptr;
712     }
713
714   dfi->pstate = -1;
715   dfi->pflags |= flags;
716
717   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
718      known dumps.  */
719   if (dfi->suffix == NULL)
720     dump_enable_all (dfi->pflags, dfi->pfilename);
721
722   return 1;
723 }
724
725 int
726 dump_switch_p (const char *arg)
727 {
728   size_t i;
729   int any = 0;
730
731   for (i = TDI_none + 1; i != TDI_end; i++)
732     any |= dump_switch_p_1 (arg, &dump_files[i], false);
733
734   /* Don't glob if we got a hit already */
735   if (!any)
736     for (i = TDI_none + 1; i != TDI_end; i++)
737       any |= dump_switch_p_1 (arg, &dump_files[i], true);
738
739   for (i = 0; i < extra_dump_files_in_use; i++)
740     any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
741
742   if (!any)
743     for (i = 0; i < extra_dump_files_in_use; i++)
744       any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
745
746
747   return any;
748 }
749
750 /* Parse ARG as a -fopt-info switch and store flags and filename.
751    Return non-zero if it is a recognized switch.  */
752
753 static int
754 opt_info_switch_p_1 (const char *arg, int *flags, char **filename)
755 {
756   const char *option_value;
757   const char *ptr;
758
759   option_value = arg;
760   ptr = option_value;
761
762   *filename = NULL;
763   *flags = 0;
764
765   if (!ptr)
766     return 1;
767
768   while (*ptr)
769     {
770       const struct dump_option_value_info *option_ptr;
771       const char *end_ptr;
772       const char *eq_ptr;
773       unsigned length;
774
775       while (*ptr == '-')
776         ptr++;
777       end_ptr = strchr (ptr, '-');
778       eq_ptr = strchr (ptr, '=');
779
780       if (eq_ptr && !end_ptr)
781         end_ptr = eq_ptr;
782
783       if (!end_ptr)
784         end_ptr = ptr + strlen (ptr);
785       length = end_ptr - ptr;
786
787       for (option_ptr = opt_info_options; option_ptr->name; option_ptr++)
788         if (strlen (option_ptr->name) == length
789             && !memcmp (option_ptr->name, ptr, length))
790           {
791             *flags |= option_ptr->value;
792             goto found;
793           }
794
795       if (*ptr == '=')
796         {
797           /* Interpret rest of the argument as a dump filename.  This
798              filename overrides other command line filenames.  */
799           *filename = xstrdup (ptr + 1);
800           break;
801         }
802       else
803         warning (0, "ignoring unknown option %q.*s in %<-fopt-info=%s%>",
804                  length, ptr, arg);
805     found:;
806       ptr = end_ptr;
807     }
808
809   return 1;
810 }
811
812 /* Return non-zero if ARG is a recognized switch for
813    -fopt-info. Return zero otherwise.  */
814
815 int
816 opt_info_switch_p (const char *arg)
817 {
818   int flags;
819   char *filename;
820
821   opt_info_switch_p_1 (arg, &flags, &filename);
822
823   if (!filename)
824     filename = xstrdup ("stderr");
825   if (!flags)
826     flags = MSG_ALL;
827
828   return opt_info_enable_all ((TDF_TREE | TDF_RTL | TDF_IPA), flags, filename);
829 }
830
831 /* Return true if any dumps are enabled for the given MSG_TYPE, false
832    otherwise.  */
833
834 bool
835 dump_kind_p (int msg_type)
836 {
837   if (!current_function_decl)
838     return 0;
839   return ((msg_type & pflags) || (msg_type & alt_flags));
840 }
841
842 /* Print basic block on the dump streams.  */
843
844 void
845 dump_basic_block (int dump_kind, basic_block bb, int indent)
846 {
847   if (dump_file && (dump_kind & pflags))
848     dump_bb (dump_file, bb, indent, TDF_DETAILS);
849   if (alt_dump_file && (dump_kind & alt_flags))
850     dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
851 }
852
853 /* Print information from the combine pass on dump_file.  */
854
855 void
856 print_combine_total_stats (void)
857 {
858   if (dump_file)
859     dump_combine_total_stats (dump_file);
860 }
861
862 /* Enable RTL dump for all the RTL passes.  */
863
864 bool
865 enable_rtl_dump_file (void)
866 {
867   return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
868 }