2015-05-19 Christophe Lyon <christophe.lyon@linaro.org>
[official-gcc.git] / gcc / dumpfile.c
blob743344e5e1533c509f48a772f898c315a1e2b306
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "diagnostic-core.h"
24 #include "dumpfile.h"
25 #include "hash-set.h"
26 #include "machmode.h"
27 #include "vec.h"
28 #include "double-int.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "options.h"
33 #include "wide-int.h"
34 #include "inchash.h"
35 #include "real.h"
36 #include "tree.h"
37 #include "gimple-pretty-print.h"
38 #include "context.h"
40 /* If non-NULL, return one past-the-end of the matching SUBPART of
41 the WHOLE string. */
42 #define skip_leading_substring(whole, part) \
43 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
45 static int pflags; /* current dump_flags */
46 static int alt_flags; /* current opt_info flags */
48 static void dump_loc (int, FILE *, source_location);
49 static FILE *dump_open_alternate_stream (struct dump_file_info *);
51 /* These are currently used for communicating between passes.
52 However, instead of accessing them directly, the passes can use
53 dump_printf () for dumps. */
54 FILE *dump_file = NULL;
55 FILE *alt_dump_file = NULL;
56 const char *dump_file_name;
57 int dump_flags;
59 /* Table of tree dump switches. This must be consistent with the
60 TREE_DUMP_INDEX enumeration in dumpfile.h. */
61 static struct dump_file_info dump_files[TDI_end] =
63 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, false},
64 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
65 0, 0, 0, 0, 0, false},
66 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
67 0, 0, 0, 0, 0, false},
68 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
69 0, 0, 0, 0, 1, false},
70 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
71 0, 0, 0, 0, 2, false},
72 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
73 0, 0, 0, 0, 3, false},
74 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
75 0, 0, 0, 0, 4, false},
76 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
77 0, 0, 0, 0, 5, false},
78 #define FIRST_AUTO_NUMBERED_DUMP 6
80 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
81 0, 0, 0, 0, 0, false},
82 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
83 0, 0, 0, 0, 0, false},
84 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
85 0, 0, 0, 0, 0, false},
88 /* Define a name->number mapping for a dump flag value. */
89 struct dump_option_value_info
91 const char *const name; /* the name of the value */
92 const int value; /* the value of the name */
95 /* Table of dump options. This must be consistent with the TDF_* flags
96 in dumpfile.h and opt_info_options below. */
97 static const struct dump_option_value_info dump_options[] =
99 {"address", TDF_ADDRESS},
100 {"asmname", TDF_ASMNAME},
101 {"slim", TDF_SLIM},
102 {"raw", TDF_RAW},
103 {"graph", TDF_GRAPH},
104 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
105 | MSG_MISSED_OPTIMIZATION
106 | MSG_NOTE)},
107 {"cselib", TDF_CSELIB},
108 {"stats", TDF_STATS},
109 {"blocks", TDF_BLOCKS},
110 {"vops", TDF_VOPS},
111 {"lineno", TDF_LINENO},
112 {"uid", TDF_UID},
113 {"stmtaddr", TDF_STMTADDR},
114 {"memsyms", TDF_MEMSYMS},
115 {"verbose", TDF_VERBOSE},
116 {"eh", TDF_EH},
117 {"alias", TDF_ALIAS},
118 {"nouid", TDF_NOUID},
119 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
120 {"scev", TDF_SCEV},
121 {"optimized", MSG_OPTIMIZED_LOCATIONS},
122 {"missed", MSG_MISSED_OPTIMIZATION},
123 {"note", MSG_NOTE},
124 {"optall", MSG_ALL},
125 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
126 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
127 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
128 {NULL, 0}
131 /* A subset of the dump_options table which is used for -fopt-info
132 types. This must be consistent with the MSG_* flags in dumpfile.h.
134 static const struct dump_option_value_info optinfo_verbosity_options[] =
136 {"optimized", MSG_OPTIMIZED_LOCATIONS},
137 {"missed", MSG_MISSED_OPTIMIZATION},
138 {"note", MSG_NOTE},
139 {"all", MSG_ALL},
140 {NULL, 0}
143 /* Flags used for -fopt-info groups. */
144 static const struct dump_option_value_info optgroup_options[] =
146 {"ipa", OPTGROUP_IPA},
147 {"loop", OPTGROUP_LOOP},
148 {"inline", OPTGROUP_INLINE},
149 {"vec", OPTGROUP_VEC},
150 {"optall", OPTGROUP_ALL},
151 {NULL, 0}
154 gcc::dump_manager::dump_manager ():
155 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
156 m_extra_dump_files (NULL),
157 m_extra_dump_files_in_use (0),
158 m_extra_dump_files_alloced (0)
162 gcc::dump_manager::~dump_manager ()
164 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
166 dump_file_info *dfi = &m_extra_dump_files[i];
167 /* suffix, swtch, glob are statically allocated for the entries
168 in dump_files, and for statistics, but are dynamically allocated
169 for those for passes. */
170 if (dfi->owns_strings)
172 XDELETEVEC (const_cast <char *> (dfi->suffix));
173 XDELETEVEC (const_cast <char *> (dfi->swtch));
174 XDELETEVEC (const_cast <char *> (dfi->glob));
176 /* These, if non-NULL, are always dynamically allocated. */
177 XDELETEVEC (const_cast <char *> (dfi->pfilename));
178 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
180 XDELETEVEC (m_extra_dump_files);
183 unsigned int
184 gcc::dump_manager::
185 dump_register (const char *suffix, const char *swtch, const char *glob,
186 int flags, int optgroup_flags,
187 bool take_ownership)
189 int num = m_next_dump++;
191 size_t count = m_extra_dump_files_in_use++;
193 if (count >= m_extra_dump_files_alloced)
195 if (m_extra_dump_files_alloced == 0)
196 m_extra_dump_files_alloced = 32;
197 else
198 m_extra_dump_files_alloced *= 2;
199 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
200 m_extra_dump_files,
201 m_extra_dump_files_alloced);
204 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
205 m_extra_dump_files[count].suffix = suffix;
206 m_extra_dump_files[count].swtch = swtch;
207 m_extra_dump_files[count].glob = glob;
208 m_extra_dump_files[count].pflags = flags;
209 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
210 m_extra_dump_files[count].num = num;
211 m_extra_dump_files[count].owns_strings = take_ownership;
213 return count + TDI_end;
217 /* Return the dump_file_info for the given phase. */
219 struct dump_file_info *
220 gcc::dump_manager::
221 get_dump_file_info (int phase) const
223 if (phase < TDI_end)
224 return &dump_files[phase];
225 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
226 return NULL;
227 else
228 return m_extra_dump_files + (phase - TDI_end);
231 /* Locate the dump_file_info with swtch equal to SWTCH,
232 or return NULL if no such dump_file_info exists. */
234 struct dump_file_info *
235 gcc::dump_manager::
236 get_dump_file_info_by_switch (const char *swtch) const
238 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
239 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
240 return &m_extra_dump_files[i];
242 /* Not found. */
243 return NULL;
247 /* Return the name of the dump file for the given phase.
248 The caller is responsible for calling free on the returned
249 buffer.
250 If the dump is not enabled, returns NULL. */
252 char *
253 gcc::dump_manager::
254 get_dump_file_name (int phase) const
256 struct dump_file_info *dfi;
258 if (phase == TDI_none)
259 return NULL;
261 dfi = get_dump_file_info (phase);
263 return get_dump_file_name (dfi);
266 /* Return the name of the dump file for the given dump_file_info.
267 The caller is responsible for calling free on the returned
268 buffer.
269 If the dump is not enabled, returns NULL. */
271 char *
272 gcc::dump_manager::
273 get_dump_file_name (struct dump_file_info *dfi) const
275 char dump_id[10];
277 gcc_assert (dfi);
279 if (dfi->pstate == 0)
280 return NULL;
282 /* If available, use the command line dump filename. */
283 if (dfi->pfilename)
284 return xstrdup (dfi->pfilename);
286 if (dfi->num < 0)
287 dump_id[0] = '\0';
288 else
290 char suffix;
291 if (dfi->pflags & TDF_TREE)
292 suffix = 't';
293 else if (dfi->pflags & TDF_IPA)
294 suffix = 'i';
295 else
296 suffix = 'r';
298 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
299 dump_id[0] = '\0';
302 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
305 /* For a given DFI, open an alternate dump filename (which could also
306 be a standard stream such as stdout/stderr). If the alternate dump
307 file cannot be opened, return NULL. */
309 static FILE *
310 dump_open_alternate_stream (struct dump_file_info *dfi)
312 FILE *stream ;
313 if (!dfi->alt_filename)
314 return NULL;
316 if (dfi->alt_stream)
317 return dfi->alt_stream;
319 stream = strcmp ("stderr", dfi->alt_filename) == 0
320 ? stderr
321 : strcmp ("stdout", dfi->alt_filename) == 0
322 ? stdout
323 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
325 if (!stream)
326 error ("could not open dump file %qs: %m", dfi->alt_filename);
327 else
328 dfi->alt_state = 1;
330 return stream;
333 /* Print source location on DFILE if enabled. */
335 void
336 dump_loc (int dump_kind, FILE *dfile, source_location loc)
338 if (dump_kind)
340 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
341 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
342 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
343 else if (current_function_decl)
344 fprintf (dfile, "%s:%d:%d: note: ",
345 DECL_SOURCE_FILE (current_function_decl),
346 DECL_SOURCE_LINE (current_function_decl),
347 DECL_SOURCE_COLUMN (current_function_decl));
351 /* Dump gimple statement GS with SPC indentation spaces and
352 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
354 void
355 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
357 if (dump_file && (dump_kind & pflags))
358 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
360 if (alt_dump_file && (dump_kind & alt_flags))
361 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
364 /* Similar to dump_gimple_stmt, except additionally print source location. */
366 void
367 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
368 gimple gs, int spc)
370 if (dump_file && (dump_kind & pflags))
372 dump_loc (dump_kind, dump_file, loc);
373 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
376 if (alt_dump_file && (dump_kind & alt_flags))
378 dump_loc (dump_kind, alt_dump_file, loc);
379 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
383 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
384 DUMP_KIND is enabled. */
386 void
387 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
389 if (dump_file && (dump_kind & pflags))
390 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
392 if (alt_dump_file && (dump_kind & alt_flags))
393 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
397 /* Similar to dump_generic_expr, except additionally print the source
398 location. */
400 void
401 dump_generic_expr_loc (int dump_kind, source_location loc,
402 int extra_dump_flags, tree t)
404 if (dump_file && (dump_kind & pflags))
406 dump_loc (dump_kind, dump_file, loc);
407 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
410 if (alt_dump_file && (dump_kind & alt_flags))
412 dump_loc (dump_kind, alt_dump_file, loc);
413 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
417 /* Output a formatted message using FORMAT on appropriate dump streams. */
419 void
420 dump_printf (int dump_kind, const char *format, ...)
422 if (dump_file && (dump_kind & pflags))
424 va_list ap;
425 va_start (ap, format);
426 vfprintf (dump_file, format, ap);
427 va_end (ap);
430 if (alt_dump_file && (dump_kind & alt_flags))
432 va_list ap;
433 va_start (ap, format);
434 vfprintf (alt_dump_file, format, ap);
435 va_end (ap);
439 /* Similar to dump_printf, except source location is also printed. */
441 void
442 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
444 if (dump_file && (dump_kind & pflags))
446 va_list ap;
447 dump_loc (dump_kind, dump_file, loc);
448 va_start (ap, format);
449 vfprintf (dump_file, format, ap);
450 va_end (ap);
453 if (alt_dump_file && (dump_kind & alt_flags))
455 va_list ap;
456 dump_loc (dump_kind, alt_dump_file, loc);
457 va_start (ap, format);
458 vfprintf (alt_dump_file, format, ap);
459 va_end (ap);
463 /* Start a dump for PHASE. Store user-supplied dump flags in
464 *FLAG_PTR. Return the number of streams opened. Set globals
465 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
466 set dump_flags appropriately for both pass dump stream and
467 -fopt-info stream. */
470 gcc::dump_manager::
471 dump_start (int phase, int *flag_ptr)
473 int count = 0;
474 char *name;
475 struct dump_file_info *dfi;
476 FILE *stream;
477 if (phase == TDI_none || !dump_phase_enabled_p (phase))
478 return 0;
480 dfi = get_dump_file_info (phase);
481 name = get_dump_file_name (phase);
482 if (name)
484 stream = strcmp ("stderr", name) == 0
485 ? stderr
486 : strcmp ("stdout", name) == 0
487 ? stdout
488 : fopen (name, dfi->pstate < 0 ? "w" : "a");
489 if (!stream)
490 error ("could not open dump file %qs: %m", name);
491 else
493 dfi->pstate = 1;
494 count++;
496 free (name);
497 dfi->pstream = stream;
498 dump_file = dfi->pstream;
499 /* Initialize current dump flags. */
500 pflags = dfi->pflags;
503 stream = dump_open_alternate_stream (dfi);
504 if (stream)
506 dfi->alt_stream = stream;
507 count++;
508 alt_dump_file = dfi->alt_stream;
509 /* Initialize current -fopt-info flags. */
510 alt_flags = dfi->alt_flags;
513 if (flag_ptr)
514 *flag_ptr = dfi->pflags;
516 return count;
519 /* Finish a tree dump for PHASE and close associated dump streams. Also
520 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
522 void
523 gcc::dump_manager::
524 dump_finish (int phase)
526 struct dump_file_info *dfi;
528 if (phase < 0)
529 return;
530 dfi = get_dump_file_info (phase);
531 if (dfi->pstream && (!dfi->pfilename
532 || (strcmp ("stderr", dfi->pfilename) != 0
533 && strcmp ("stdout", dfi->pfilename) != 0)))
534 fclose (dfi->pstream);
536 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
537 && strcmp ("stdout", dfi->alt_filename) != 0)
538 fclose (dfi->alt_stream);
540 dfi->alt_stream = NULL;
541 dfi->pstream = NULL;
542 dump_file = NULL;
543 alt_dump_file = NULL;
544 dump_flags = TDI_none;
545 alt_flags = 0;
546 pflags = 0;
549 /* Begin a tree dump for PHASE. Stores any user supplied flag in
550 *FLAG_PTR and returns a stream to write to. If the dump is not
551 enabled, returns NULL.
552 Multiple calls will reopen and append to the dump file. */
554 FILE *
555 dump_begin (int phase, int *flag_ptr)
557 return g->get_dumps ()->dump_begin (phase, flag_ptr);
560 FILE *
561 gcc::dump_manager::
562 dump_begin (int phase, int *flag_ptr)
564 char *name;
565 struct dump_file_info *dfi;
566 FILE *stream;
568 if (phase == TDI_none || !dump_phase_enabled_p (phase))
569 return NULL;
571 name = get_dump_file_name (phase);
572 if (!name)
573 return NULL;
574 dfi = get_dump_file_info (phase);
576 stream = strcmp ("stderr", name) == 0
577 ? stderr
578 : strcmp ("stdout", name) == 0
579 ? stdout
580 : fopen (name, dfi->pstate < 0 ? "w" : "a");
582 if (!stream)
583 error ("could not open dump file %qs: %m", name);
584 else
585 dfi->pstate = 1;
586 free (name);
588 if (flag_ptr)
589 *flag_ptr = dfi->pflags;
591 /* Initialize current flags */
592 pflags = dfi->pflags;
593 return stream;
596 /* Returns nonzero if dump PHASE is enabled for at least one stream.
597 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
598 any phase. */
601 gcc::dump_manager::
602 dump_phase_enabled_p (int phase) const
604 if (phase == TDI_tree_all)
606 size_t i;
607 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
608 if (dump_files[i].pstate || dump_files[i].alt_state)
609 return 1;
610 for (i = 0; i < m_extra_dump_files_in_use; i++)
611 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
612 return 1;
613 return 0;
615 else
617 struct dump_file_info *dfi = get_dump_file_info (phase);
618 return dfi->pstate || dfi->alt_state;
622 /* Returns nonzero if tree dump PHASE has been initialized. */
625 gcc::dump_manager::
626 dump_initialized_p (int phase) const
628 struct dump_file_info *dfi = get_dump_file_info (phase);
629 return dfi->pstate > 0 || dfi->alt_state > 0;
632 /* Returns the switch name of PHASE. */
634 const char *
635 dump_flag_name (int phase)
637 return g->get_dumps ()->dump_flag_name (phase);
640 const char *
641 gcc::dump_manager::
642 dump_flag_name (int phase) const
644 struct dump_file_info *dfi = get_dump_file_info (phase);
645 return dfi->swtch;
648 /* Finish a tree dump for PHASE. STREAM is the stream created by
649 dump_begin. */
651 void
652 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
654 if (stream != stderr && stream != stdout)
655 fclose (stream);
658 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
659 enabled tree dumps. */
662 gcc::dump_manager::
663 dump_enable_all (int flags, const char *filename)
665 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
666 int n = 0;
667 size_t i;
669 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
671 if ((dump_files[i].pflags & ir_dump_type))
673 const char *old_filename = dump_files[i].pfilename;
674 dump_files[i].pstate = -1;
675 dump_files[i].pflags |= flags;
676 n++;
677 /* Override the existing filename. */
678 if (filename)
680 dump_files[i].pfilename = xstrdup (filename);
681 /* Since it is a command-line provided file, which is
682 common to all the phases, use it in append mode. */
683 dump_files[i].pstate = 1;
685 if (old_filename && filename != old_filename)
686 free (CONST_CAST (char *, old_filename));
690 for (i = 0; i < m_extra_dump_files_in_use; i++)
692 if ((m_extra_dump_files[i].pflags & ir_dump_type))
694 const char *old_filename = m_extra_dump_files[i].pfilename;
695 m_extra_dump_files[i].pstate = -1;
696 m_extra_dump_files[i].pflags |= flags;
697 n++;
698 /* Override the existing filename. */
699 if (filename)
701 m_extra_dump_files[i].pfilename = xstrdup (filename);
702 /* Since it is a command-line provided file, which is
703 common to all the phases, use it in append mode. */
704 m_extra_dump_files[i].pstate = 1;
706 if (old_filename && filename != old_filename)
707 free (CONST_CAST (char *, old_filename));
711 return n;
714 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
715 Enable dumps with FLAGS on FILENAME. Return the number of enabled
716 dumps. */
719 gcc::dump_manager::
720 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
722 int n = 0;
723 size_t i;
725 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
727 if ((dump_files[i].optgroup_flags & optgroup_flags))
729 const char *old_filename = dump_files[i].alt_filename;
730 /* Since this file is shared among different passes, it
731 should be opened in append mode. */
732 dump_files[i].alt_state = 1;
733 dump_files[i].alt_flags |= flags;
734 n++;
735 /* Override the existing filename. */
736 if (filename)
737 dump_files[i].alt_filename = xstrdup (filename);
738 if (old_filename && filename != old_filename)
739 free (CONST_CAST (char *, old_filename));
743 for (i = 0; i < m_extra_dump_files_in_use; i++)
745 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
747 const char *old_filename = m_extra_dump_files[i].alt_filename;
748 /* Since this file is shared among different passes, it
749 should be opened in append mode. */
750 m_extra_dump_files[i].alt_state = 1;
751 m_extra_dump_files[i].alt_flags |= flags;
752 n++;
753 /* Override the existing filename. */
754 if (filename)
755 m_extra_dump_files[i].alt_filename = xstrdup (filename);
756 if (old_filename && filename != old_filename)
757 free (CONST_CAST (char *, old_filename));
761 return n;
764 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
765 relevant details in the dump_files array. */
768 gcc::dump_manager::
769 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
771 const char *option_value;
772 const char *ptr;
773 int flags;
775 if (doglob && !dfi->glob)
776 return 0;
778 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
779 if (!option_value)
780 return 0;
782 if (*option_value && *option_value != '-' && *option_value != '=')
783 return 0;
785 ptr = option_value;
786 flags = 0;
788 while (*ptr)
790 const struct dump_option_value_info *option_ptr;
791 const char *end_ptr;
792 const char *eq_ptr;
793 unsigned length;
795 while (*ptr == '-')
796 ptr++;
797 end_ptr = strchr (ptr, '-');
798 eq_ptr = strchr (ptr, '=');
800 if (eq_ptr && !end_ptr)
801 end_ptr = eq_ptr;
803 if (!end_ptr)
804 end_ptr = ptr + strlen (ptr);
805 length = end_ptr - ptr;
807 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
808 if (strlen (option_ptr->name) == length
809 && !memcmp (option_ptr->name, ptr, length))
811 flags |= option_ptr->value;
812 goto found;
815 if (*ptr == '=')
817 /* Interpret rest of the argument as a dump filename. This
818 filename overrides other command line filenames. */
819 if (dfi->pfilename)
820 free (CONST_CAST (char *, dfi->pfilename));
821 dfi->pfilename = xstrdup (ptr + 1);
822 break;
824 else
825 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
826 length, ptr, dfi->swtch);
827 found:;
828 ptr = end_ptr;
831 dfi->pstate = -1;
832 dfi->pflags |= flags;
834 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
835 known dumps. */
836 if (dfi->suffix == NULL)
837 dump_enable_all (dfi->pflags, dfi->pfilename);
839 return 1;
843 gcc::dump_manager::
844 dump_switch_p (const char *arg)
846 size_t i;
847 int any = 0;
849 for (i = TDI_none + 1; i != TDI_end; i++)
850 any |= dump_switch_p_1 (arg, &dump_files[i], false);
852 /* Don't glob if we got a hit already */
853 if (!any)
854 for (i = TDI_none + 1; i != TDI_end; i++)
855 any |= dump_switch_p_1 (arg, &dump_files[i], true);
857 for (i = 0; i < m_extra_dump_files_in_use; i++)
858 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
860 if (!any)
861 for (i = 0; i < m_extra_dump_files_in_use; i++)
862 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
865 return any;
868 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
869 and filename. Return non-zero if it is a recognized switch. */
871 static int
872 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
873 char **filename)
875 const char *option_value;
876 const char *ptr;
878 option_value = arg;
879 ptr = option_value;
881 *filename = NULL;
882 *flags = 0;
883 *optgroup_flags = 0;
885 if (!ptr)
886 return 1; /* Handle '-fopt-info' without any additional options. */
888 while (*ptr)
890 const struct dump_option_value_info *option_ptr;
891 const char *end_ptr;
892 const char *eq_ptr;
893 unsigned length;
895 while (*ptr == '-')
896 ptr++;
897 end_ptr = strchr (ptr, '-');
898 eq_ptr = strchr (ptr, '=');
900 if (eq_ptr && !end_ptr)
901 end_ptr = eq_ptr;
903 if (!end_ptr)
904 end_ptr = ptr + strlen (ptr);
905 length = end_ptr - ptr;
907 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
908 option_ptr++)
909 if (strlen (option_ptr->name) == length
910 && !memcmp (option_ptr->name, ptr, length))
912 *flags |= option_ptr->value;
913 goto found;
916 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
917 if (strlen (option_ptr->name) == length
918 && !memcmp (option_ptr->name, ptr, length))
920 *optgroup_flags |= option_ptr->value;
921 goto found;
924 if (*ptr == '=')
926 /* Interpret rest of the argument as a dump filename. This
927 filename overrides other command line filenames. */
928 *filename = xstrdup (ptr + 1);
929 break;
931 else
933 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
934 length, ptr, arg);
935 return 0;
937 found:;
938 ptr = end_ptr;
941 return 1;
944 /* Return non-zero if ARG is a recognized switch for
945 -fopt-info. Return zero otherwise. */
948 opt_info_switch_p (const char *arg)
950 int flags;
951 int optgroup_flags;
952 char *filename;
953 static char *file_seen = NULL;
954 gcc::dump_manager *dumps = g->get_dumps ();
956 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
957 return 0;
959 if (!filename)
960 filename = xstrdup ("stderr");
962 /* Bail out if a different filename has been specified. */
963 if (file_seen && strcmp (file_seen, filename))
965 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
966 arg);
967 return 1;
970 file_seen = xstrdup (filename);
971 if (!flags)
972 flags = MSG_OPTIMIZED_LOCATIONS;
973 if (!optgroup_flags)
974 optgroup_flags = OPTGROUP_ALL;
976 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
979 /* Print basic block on the dump streams. */
981 void
982 dump_basic_block (int dump_kind, basic_block bb, int indent)
984 if (dump_file && (dump_kind & pflags))
985 dump_bb (dump_file, bb, indent, TDF_DETAILS);
986 if (alt_dump_file && (dump_kind & alt_flags))
987 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
990 /* Print information from the combine pass on dump_file. */
992 void
993 print_combine_total_stats (void)
995 if (dump_file)
996 dump_combine_total_stats (dump_file);
999 /* Enable RTL dump for all the RTL passes. */
1001 bool
1002 enable_rtl_dump_file (void)
1004 gcc::dump_manager *dumps = g->get_dumps ();
1005 int num_enabled =
1006 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
1007 return num_enabled > 0;