* gcc.dg/store-motion-fgcse-sm.c (dg-final): Cleanup
[official-gcc.git] / gcc / dumpfile.c
blobc2cd89b59aaf6fdaddad5db7fba036add1af0e02
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, false},
53 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
54 0, 0, 0, 0, 0, false},
55 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
56 0, 0, 0, 0, 0, false},
57 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
58 0, 0, 0, 0, 1, false},
59 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
60 0, 0, 0, 0, 2, false},
61 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
62 0, 0, 0, 0, 3, false},
63 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
64 0, 0, 0, 0, 4, false},
65 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
66 0, 0, 0, 0, 5, false},
67 #define FIRST_AUTO_NUMBERED_DUMP 6
69 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
70 0, 0, 0, 0, 0, false},
71 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
72 0, 0, 0, 0, 0, false},
73 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
74 0, 0, 0, 0, 0, false},
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 {"optimized", MSG_OPTIMIZED_LOCATIONS},
111 {"missed", MSG_MISSED_OPTIMIZATION},
112 {"note", MSG_NOTE},
113 {"optall", MSG_ALL},
114 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
115 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
116 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
117 {NULL, 0}
120 /* A subset of the dump_options table which is used for -fopt-info
121 types. This must be consistent with the MSG_* flags in dumpfile.h.
123 static const struct dump_option_value_info optinfo_verbosity_options[] =
125 {"optimized", MSG_OPTIMIZED_LOCATIONS},
126 {"missed", MSG_MISSED_OPTIMIZATION},
127 {"note", MSG_NOTE},
128 {"all", MSG_ALL},
129 {NULL, 0}
132 /* Flags used for -fopt-info groups. */
133 static const struct dump_option_value_info optgroup_options[] =
135 {"ipa", OPTGROUP_IPA},
136 {"loop", OPTGROUP_LOOP},
137 {"inline", OPTGROUP_INLINE},
138 {"vec", OPTGROUP_VEC},
139 {"optall", OPTGROUP_ALL},
140 {NULL, 0}
143 gcc::dump_manager::dump_manager ():
144 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
145 m_extra_dump_files (NULL),
146 m_extra_dump_files_in_use (0),
147 m_extra_dump_files_alloced (0)
151 gcc::dump_manager::~dump_manager ()
153 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
155 dump_file_info *dfi = &m_extra_dump_files[i];
156 /* suffix, swtch, glob are statically allocated for the entries
157 in dump_files, and for statistics, but are dynamically allocated
158 for those for passes. */
159 if (dfi->owns_strings)
161 XDELETEVEC (const_cast <char *> (dfi->suffix));
162 XDELETEVEC (const_cast <char *> (dfi->swtch));
163 XDELETEVEC (const_cast <char *> (dfi->glob));
165 /* These, if non-NULL, are always dynamically allocated. */
166 XDELETEVEC (const_cast <char *> (dfi->pfilename));
167 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
169 XDELETEVEC (m_extra_dump_files);
172 unsigned int
173 gcc::dump_manager::
174 dump_register (const char *suffix, const char *swtch, const char *glob,
175 int flags, int optgroup_flags,
176 bool take_ownership)
178 int num = m_next_dump++;
180 size_t count = m_extra_dump_files_in_use++;
182 if (count >= m_extra_dump_files_alloced)
184 if (m_extra_dump_files_alloced == 0)
185 m_extra_dump_files_alloced = 32;
186 else
187 m_extra_dump_files_alloced *= 2;
188 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
189 m_extra_dump_files,
190 m_extra_dump_files_alloced);
193 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
194 m_extra_dump_files[count].suffix = suffix;
195 m_extra_dump_files[count].swtch = swtch;
196 m_extra_dump_files[count].glob = glob;
197 m_extra_dump_files[count].pflags = flags;
198 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
199 m_extra_dump_files[count].num = num;
200 m_extra_dump_files[count].owns_strings = take_ownership;
202 return count + TDI_end;
206 /* Return the dump_file_info for the given phase. */
208 struct dump_file_info *
209 gcc::dump_manager::
210 get_dump_file_info (int phase) const
212 if (phase < TDI_end)
213 return &dump_files[phase];
214 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
215 return NULL;
216 else
217 return m_extra_dump_files + (phase - TDI_end);
221 /* Return the name of the dump file for the given phase.
222 If the dump is not enabled, returns NULL. */
224 char *
225 gcc::dump_manager::
226 get_dump_file_name (int phase) const
228 char dump_id[10];
229 struct dump_file_info *dfi;
231 if (phase == TDI_none)
232 return NULL;
234 dfi = get_dump_file_info (phase);
235 if (dfi->pstate == 0)
236 return NULL;
238 /* If available, use the command line dump filename. */
239 if (dfi->pfilename)
240 return xstrdup (dfi->pfilename);
242 if (dfi->num < 0)
243 dump_id[0] = '\0';
244 else
246 char suffix;
247 if (dfi->pflags & TDF_TREE)
248 suffix = 't';
249 else if (dfi->pflags & TDF_IPA)
250 suffix = 'i';
251 else
252 suffix = 'r';
254 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
255 dump_id[0] = '\0';
258 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
261 /* For a given DFI, open an alternate dump filename (which could also
262 be a standard stream such as stdout/stderr). If the alternate dump
263 file cannot be opened, return NULL. */
265 static FILE *
266 dump_open_alternate_stream (struct dump_file_info *dfi)
268 FILE *stream ;
269 if (!dfi->alt_filename)
270 return NULL;
272 if (dfi->alt_stream)
273 return dfi->alt_stream;
275 stream = strcmp ("stderr", dfi->alt_filename) == 0
276 ? stderr
277 : strcmp ("stdout", dfi->alt_filename) == 0
278 ? stdout
279 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
281 if (!stream)
282 error ("could not open dump file %qs: %m", dfi->alt_filename);
283 else
284 dfi->alt_state = 1;
286 return stream;
289 /* Print source location on DFILE if enabled. */
291 void
292 dump_loc (int dump_kind, FILE *dfile, source_location loc)
294 if (dump_kind)
296 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
297 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
298 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
299 else if (current_function_decl)
300 fprintf (dfile, "%s:%d:%d: note: ",
301 DECL_SOURCE_FILE (current_function_decl),
302 DECL_SOURCE_LINE (current_function_decl),
303 DECL_SOURCE_COLUMN (current_function_decl));
307 /* Dump gimple statement GS with SPC indentation spaces and
308 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
310 void
311 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
313 if (dump_file && (dump_kind & pflags))
314 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
316 if (alt_dump_file && (dump_kind & alt_flags))
317 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
320 /* Similar to dump_gimple_stmt, except additionally print source location. */
322 void
323 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
324 gimple gs, int spc)
326 if (dump_file && (dump_kind & pflags))
328 dump_loc (dump_kind, dump_file, loc);
329 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
332 if (alt_dump_file && (dump_kind & alt_flags))
334 dump_loc (dump_kind, alt_dump_file, loc);
335 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
339 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
340 DUMP_KIND is enabled. */
342 void
343 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
345 if (dump_file && (dump_kind & pflags))
346 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
348 if (alt_dump_file && (dump_kind & alt_flags))
349 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
353 /* Similar to dump_generic_expr, except additionally print the source
354 location. */
356 void
357 dump_generic_expr_loc (int dump_kind, source_location loc,
358 int extra_dump_flags, tree t)
360 if (dump_file && (dump_kind & pflags))
362 dump_loc (dump_kind, dump_file, loc);
363 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
366 if (alt_dump_file && (dump_kind & alt_flags))
368 dump_loc (dump_kind, alt_dump_file, loc);
369 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
373 /* Output a formatted message using FORMAT on appropriate dump streams. */
375 void
376 dump_printf (int dump_kind, const char *format, ...)
378 if (dump_file && (dump_kind & pflags))
380 va_list ap;
381 va_start (ap, format);
382 vfprintf (dump_file, format, ap);
383 va_end (ap);
386 if (alt_dump_file && (dump_kind & alt_flags))
388 va_list ap;
389 va_start (ap, format);
390 vfprintf (alt_dump_file, format, ap);
391 va_end (ap);
395 /* Similar to dump_printf, except source location is also printed. */
397 void
398 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
400 if (dump_file && (dump_kind & pflags))
402 va_list ap;
403 dump_loc (dump_kind, dump_file, loc);
404 va_start (ap, format);
405 vfprintf (dump_file, format, ap);
406 va_end (ap);
409 if (alt_dump_file && (dump_kind & alt_flags))
411 va_list ap;
412 dump_loc (dump_kind, alt_dump_file, loc);
413 va_start (ap, format);
414 vfprintf (alt_dump_file, format, ap);
415 va_end (ap);
419 /* Start a dump for PHASE. Store user-supplied dump flags in
420 *FLAG_PTR. Return the number of streams opened. Set globals
421 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
422 set dump_flags appropriately for both pass dump stream and
423 -fopt-info stream. */
426 gcc::dump_manager::
427 dump_start (int phase, int *flag_ptr)
429 int count = 0;
430 char *name;
431 struct dump_file_info *dfi;
432 FILE *stream;
433 if (phase == TDI_none || !dump_phase_enabled_p (phase))
434 return 0;
436 dfi = get_dump_file_info (phase);
437 name = get_dump_file_name (phase);
438 if (name)
440 stream = strcmp ("stderr", name) == 0
441 ? stderr
442 : strcmp ("stdout", name) == 0
443 ? stdout
444 : fopen (name, dfi->pstate < 0 ? "w" : "a");
445 if (!stream)
446 error ("could not open dump file %qs: %m", name);
447 else
449 dfi->pstate = 1;
450 count++;
452 free (name);
453 dfi->pstream = stream;
454 dump_file = dfi->pstream;
455 /* Initialize current dump flags. */
456 pflags = dfi->pflags;
459 stream = dump_open_alternate_stream (dfi);
460 if (stream)
462 dfi->alt_stream = stream;
463 count++;
464 alt_dump_file = dfi->alt_stream;
465 /* Initialize current -fopt-info flags. */
466 alt_flags = dfi->alt_flags;
469 if (flag_ptr)
470 *flag_ptr = dfi->pflags;
472 return count;
475 /* Finish a tree dump for PHASE and close associated dump streams. Also
476 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
478 void
479 gcc::dump_manager::
480 dump_finish (int phase)
482 struct dump_file_info *dfi;
484 if (phase < 0)
485 return;
486 dfi = get_dump_file_info (phase);
487 if (dfi->pstream && (!dfi->pfilename
488 || (strcmp ("stderr", dfi->pfilename) != 0
489 && strcmp ("stdout", dfi->pfilename) != 0)))
490 fclose (dfi->pstream);
492 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
493 && strcmp ("stdout", dfi->alt_filename) != 0)
494 fclose (dfi->alt_stream);
496 dfi->alt_stream = NULL;
497 dfi->pstream = NULL;
498 dump_file = NULL;
499 alt_dump_file = NULL;
500 dump_flags = TDI_none;
501 alt_flags = 0;
502 pflags = 0;
505 /* Begin a tree dump for PHASE. Stores any user supplied flag in
506 *FLAG_PTR and returns a stream to write to. If the dump is not
507 enabled, returns NULL.
508 Multiple calls will reopen and append to the dump file. */
510 FILE *
511 dump_begin (int phase, int *flag_ptr)
513 return g->get_dumps ()->dump_begin (phase, flag_ptr);
516 FILE *
517 gcc::dump_manager::
518 dump_begin (int phase, int *flag_ptr)
520 char *name;
521 struct dump_file_info *dfi;
522 FILE *stream;
524 if (phase == TDI_none || !dump_phase_enabled_p (phase))
525 return NULL;
527 name = get_dump_file_name (phase);
528 if (!name)
529 return NULL;
530 dfi = get_dump_file_info (phase);
532 stream = strcmp ("stderr", name) == 0
533 ? stderr
534 : strcmp ("stdout", name) == 0
535 ? stdout
536 : fopen (name, dfi->pstate < 0 ? "w" : "a");
538 if (!stream)
539 error ("could not open dump file %qs: %m", name);
540 else
541 dfi->pstate = 1;
542 free (name);
544 if (flag_ptr)
545 *flag_ptr = dfi->pflags;
547 /* Initialize current flags */
548 pflags = dfi->pflags;
549 return stream;
552 /* Returns nonzero if dump PHASE is enabled for at least one stream.
553 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
554 any phase. */
557 gcc::dump_manager::
558 dump_phase_enabled_p (int phase) const
560 if (phase == TDI_tree_all)
562 size_t i;
563 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
564 if (dump_files[i].pstate || dump_files[i].alt_state)
565 return 1;
566 for (i = 0; i < m_extra_dump_files_in_use; i++)
567 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
568 return 1;
569 return 0;
571 else
573 struct dump_file_info *dfi = get_dump_file_info (phase);
574 return dfi->pstate || dfi->alt_state;
578 /* Returns nonzero if tree dump PHASE has been initialized. */
581 gcc::dump_manager::
582 dump_initialized_p (int phase) const
584 struct dump_file_info *dfi = get_dump_file_info (phase);
585 return dfi->pstate > 0 || dfi->alt_state > 0;
588 /* Returns the switch name of PHASE. */
590 const char *
591 dump_flag_name (int phase)
593 return g->get_dumps ()->dump_flag_name (phase);
596 const char *
597 gcc::dump_manager::
598 dump_flag_name (int phase) const
600 struct dump_file_info *dfi = get_dump_file_info (phase);
601 return dfi->swtch;
604 /* Finish a tree dump for PHASE. STREAM is the stream created by
605 dump_begin. */
607 void
608 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
610 if (stream != stderr && stream != stdout)
611 fclose (stream);
614 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
615 enabled tree dumps. */
618 gcc::dump_manager::
619 dump_enable_all (int flags, const char *filename)
621 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
622 int n = 0;
623 size_t i;
625 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
627 if ((dump_files[i].pflags & ir_dump_type))
629 const char *old_filename = dump_files[i].pfilename;
630 dump_files[i].pstate = -1;
631 dump_files[i].pflags |= flags;
632 n++;
633 /* Override the existing filename. */
634 if (filename)
636 dump_files[i].pfilename = xstrdup (filename);
637 /* Since it is a command-line provided file, which is
638 common to all the phases, use it in append mode. */
639 dump_files[i].pstate = 1;
641 if (old_filename && filename != old_filename)
642 free (CONST_CAST (char *, old_filename));
646 for (i = 0; i < m_extra_dump_files_in_use; i++)
648 if ((m_extra_dump_files[i].pflags & ir_dump_type))
650 const char *old_filename = m_extra_dump_files[i].pfilename;
651 m_extra_dump_files[i].pstate = -1;
652 m_extra_dump_files[i].pflags |= flags;
653 n++;
654 /* Override the existing filename. */
655 if (filename)
657 m_extra_dump_files[i].pfilename = xstrdup (filename);
658 /* Since it is a command-line provided file, which is
659 common to all the phases, use it in append mode. */
660 m_extra_dump_files[i].pstate = 1;
662 if (old_filename && filename != old_filename)
663 free (CONST_CAST (char *, old_filename));
667 return n;
670 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
671 Enable dumps with FLAGS on FILENAME. Return the number of enabled
672 dumps. */
675 gcc::dump_manager::
676 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
678 int n = 0;
679 size_t i;
681 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
683 if ((dump_files[i].optgroup_flags & optgroup_flags))
685 const char *old_filename = dump_files[i].alt_filename;
686 /* Since this file is shared among different passes, it
687 should be opened in append mode. */
688 dump_files[i].alt_state = 1;
689 dump_files[i].alt_flags |= flags;
690 n++;
691 /* Override the existing filename. */
692 if (filename)
693 dump_files[i].alt_filename = xstrdup (filename);
694 if (old_filename && filename != old_filename)
695 free (CONST_CAST (char *, old_filename));
699 for (i = 0; i < m_extra_dump_files_in_use; i++)
701 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
703 const char *old_filename = m_extra_dump_files[i].alt_filename;
704 /* Since this file is shared among different passes, it
705 should be opened in append mode. */
706 m_extra_dump_files[i].alt_state = 1;
707 m_extra_dump_files[i].alt_flags |= flags;
708 n++;
709 /* Override the existing filename. */
710 if (filename)
711 m_extra_dump_files[i].alt_filename = xstrdup (filename);
712 if (old_filename && filename != old_filename)
713 free (CONST_CAST (char *, old_filename));
717 return n;
720 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
721 relevant details in the dump_files array. */
724 gcc::dump_manager::
725 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
727 const char *option_value;
728 const char *ptr;
729 int flags;
731 if (doglob && !dfi->glob)
732 return 0;
734 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
735 if (!option_value)
736 return 0;
738 if (*option_value && *option_value != '-' && *option_value != '=')
739 return 0;
741 ptr = option_value;
742 flags = 0;
744 while (*ptr)
746 const struct dump_option_value_info *option_ptr;
747 const char *end_ptr;
748 const char *eq_ptr;
749 unsigned length;
751 while (*ptr == '-')
752 ptr++;
753 end_ptr = strchr (ptr, '-');
754 eq_ptr = strchr (ptr, '=');
756 if (eq_ptr && !end_ptr)
757 end_ptr = eq_ptr;
759 if (!end_ptr)
760 end_ptr = ptr + strlen (ptr);
761 length = end_ptr - ptr;
763 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
764 if (strlen (option_ptr->name) == length
765 && !memcmp (option_ptr->name, ptr, length))
767 flags |= option_ptr->value;
768 goto found;
771 if (*ptr == '=')
773 /* Interpret rest of the argument as a dump filename. This
774 filename overrides other command line filenames. */
775 if (dfi->pfilename)
776 free (CONST_CAST (char *, dfi->pfilename));
777 dfi->pfilename = xstrdup (ptr + 1);
778 break;
780 else
781 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
782 length, ptr, dfi->swtch);
783 found:;
784 ptr = end_ptr;
787 dfi->pstate = -1;
788 dfi->pflags |= flags;
790 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
791 known dumps. */
792 if (dfi->suffix == NULL)
793 dump_enable_all (dfi->pflags, dfi->pfilename);
795 return 1;
799 gcc::dump_manager::
800 dump_switch_p (const char *arg)
802 size_t i;
803 int any = 0;
805 for (i = TDI_none + 1; i != TDI_end; i++)
806 any |= dump_switch_p_1 (arg, &dump_files[i], false);
808 /* Don't glob if we got a hit already */
809 if (!any)
810 for (i = TDI_none + 1; i != TDI_end; i++)
811 any |= dump_switch_p_1 (arg, &dump_files[i], true);
813 for (i = 0; i < m_extra_dump_files_in_use; i++)
814 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
816 if (!any)
817 for (i = 0; i < m_extra_dump_files_in_use; i++)
818 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
821 return any;
824 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
825 and filename. Return non-zero if it is a recognized switch. */
827 static int
828 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
829 char **filename)
831 const char *option_value;
832 const char *ptr;
834 option_value = arg;
835 ptr = option_value;
837 *filename = NULL;
838 *flags = 0;
839 *optgroup_flags = 0;
841 if (!ptr)
842 return 1; /* Handle '-fopt-info' without any additional options. */
844 while (*ptr)
846 const struct dump_option_value_info *option_ptr;
847 const char *end_ptr;
848 const char *eq_ptr;
849 unsigned length;
851 while (*ptr == '-')
852 ptr++;
853 end_ptr = strchr (ptr, '-');
854 eq_ptr = strchr (ptr, '=');
856 if (eq_ptr && !end_ptr)
857 end_ptr = eq_ptr;
859 if (!end_ptr)
860 end_ptr = ptr + strlen (ptr);
861 length = end_ptr - ptr;
863 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
864 option_ptr++)
865 if (strlen (option_ptr->name) == length
866 && !memcmp (option_ptr->name, ptr, length))
868 *flags |= option_ptr->value;
869 goto found;
872 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
873 if (strlen (option_ptr->name) == length
874 && !memcmp (option_ptr->name, ptr, length))
876 *optgroup_flags |= option_ptr->value;
877 goto found;
880 if (*ptr == '=')
882 /* Interpret rest of the argument as a dump filename. This
883 filename overrides other command line filenames. */
884 *filename = xstrdup (ptr + 1);
885 break;
887 else
889 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
890 length, ptr, arg);
891 return 0;
893 found:;
894 ptr = end_ptr;
897 return 1;
900 /* Return non-zero if ARG is a recognized switch for
901 -fopt-info. Return zero otherwise. */
904 opt_info_switch_p (const char *arg)
906 int flags;
907 int optgroup_flags;
908 char *filename;
909 static char *file_seen = NULL;
910 gcc::dump_manager *dumps = g->get_dumps ();
912 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
913 return 0;
915 if (!filename)
916 filename = xstrdup ("stderr");
918 /* Bail out if a different filename has been specified. */
919 if (file_seen && strcmp (file_seen, filename))
921 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
922 arg);
923 return 1;
926 file_seen = xstrdup (filename);
927 if (!flags)
928 flags = MSG_OPTIMIZED_LOCATIONS;
929 if (!optgroup_flags)
930 optgroup_flags = OPTGROUP_ALL;
932 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
935 /* Print basic block on the dump streams. */
937 void
938 dump_basic_block (int dump_kind, basic_block bb, int indent)
940 if (dump_file && (dump_kind & pflags))
941 dump_bb (dump_file, bb, indent, TDF_DETAILS);
942 if (alt_dump_file && (dump_kind & alt_flags))
943 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
946 /* Print information from the combine pass on dump_file. */
948 void
949 print_combine_total_stats (void)
951 if (dump_file)
952 dump_combine_total_stats (dump_file);
955 /* Enable RTL dump for all the RTL passes. */
957 bool
958 enable_rtl_dump_file (void)
960 gcc::dump_manager *dumps = g->get_dumps ();
961 int num_enabled =
962 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
963 return num_enabled > 0;