2017-05-11 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / gcc / dumpfile.c
blobd9a84ff661f1a01c125f258992b08b637ab950b6
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2017 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 "options.h"
24 #include "tree.h"
25 #include "gimple-pretty-print.h"
26 #include "diagnostic-core.h"
27 #include "dumpfile.h"
28 #include "context.h"
29 #include "tree-cfg.h"
31 /* If non-NULL, return one past-the-end of the matching SUBPART of
32 the WHOLE string. */
33 #define skip_leading_substring(whole, part) \
34 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
36 static int pflags; /* current dump_flags */
37 static int alt_flags; /* current opt_info flags */
39 static void dump_loc (int, FILE *, source_location);
40 static FILE *dump_open_alternate_stream (struct dump_file_info *);
42 /* These are currently used for communicating between passes.
43 However, instead of accessing them directly, the passes can use
44 dump_printf () for dumps. */
45 FILE *dump_file = NULL;
46 FILE *alt_dump_file = NULL;
47 const char *dump_file_name;
48 int dump_flags;
50 /* Table of tree dump switches. This must be consistent with the
51 TREE_DUMP_INDEX enumeration in dumpfile.h. */
52 static struct dump_file_info dump_files[TDI_end] =
54 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, false, false},
55 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
56 0, 0, 0, 0, 0, false, false},
57 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
58 0, 0, 0, 0, 0, false, false},
59 {".ipa-clones", "ipa-clones", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
60 0, 0, 0, 0, 0, false, false},
61 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_LANG,
62 0, 0, 0, 0, 1, false, false},
63 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_LANG,
64 0, 0, 0, 0, 2, false, false},
65 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
66 0, 0, 0, 0, 3, false, false},
67 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
68 0, 0, 0, 0, 4, false, false},
69 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
70 0, 0, 0, 0, 5, false, false},
71 #define FIRST_AUTO_NUMBERED_DUMP 6
73 {NULL, "lang-all", NULL, NULL, NULL, NULL, NULL, TDF_LANG,
74 0, 0, 0, 0, 0, false, false},
75 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
76 0, 0, 0, 0, 0, false, false},
77 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
78 0, 0, 0, 0, 0, false, false},
79 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
80 0, 0, 0, 0, 0, false, false},
83 /* Define a name->number mapping for a dump flag value. */
84 struct dump_option_value_info
86 const char *const name; /* the name of the value */
87 const int value; /* the value of the name */
90 /* Table of dump options. This must be consistent with the TDF_* flags
91 in dumpfile.h and opt_info_options below. */
92 static const struct dump_option_value_info dump_options[] =
94 {"address", TDF_ADDRESS},
95 {"asmname", TDF_ASMNAME},
96 {"slim", TDF_SLIM},
97 {"raw", TDF_RAW},
98 {"graph", TDF_GRAPH},
99 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
100 | MSG_MISSED_OPTIMIZATION
101 | MSG_NOTE)},
102 {"cselib", TDF_CSELIB},
103 {"stats", TDF_STATS},
104 {"blocks", TDF_BLOCKS},
105 {"vops", TDF_VOPS},
106 {"lineno", TDF_LINENO},
107 {"uid", TDF_UID},
108 {"stmtaddr", TDF_STMTADDR},
109 {"memsyms", TDF_MEMSYMS},
110 {"verbose", TDF_VERBOSE},
111 {"eh", TDF_EH},
112 {"alias", TDF_ALIAS},
113 {"nouid", TDF_NOUID},
114 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
115 {"scev", TDF_SCEV},
116 {"gimple", TDF_GIMPLE},
117 {"optimized", MSG_OPTIMIZED_LOCATIONS},
118 {"missed", MSG_MISSED_OPTIMIZATION},
119 {"note", MSG_NOTE},
120 {"optall", MSG_ALL},
121 {"all", ~(TDF_KIND_MASK | TDF_RAW | TDF_SLIM | TDF_LINENO
122 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
123 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV
124 | TDF_GIMPLE)},
125 {NULL, 0}
128 /* A subset of the dump_options table which is used for -fopt-info
129 types. This must be consistent with the MSG_* flags in dumpfile.h.
131 static const struct dump_option_value_info optinfo_verbosity_options[] =
133 {"optimized", MSG_OPTIMIZED_LOCATIONS},
134 {"missed", MSG_MISSED_OPTIMIZATION},
135 {"note", MSG_NOTE},
136 {"all", MSG_ALL},
137 {NULL, 0}
140 /* Flags used for -fopt-info groups. */
141 static const struct dump_option_value_info optgroup_options[] =
143 {"ipa", OPTGROUP_IPA},
144 {"loop", OPTGROUP_LOOP},
145 {"inline", OPTGROUP_INLINE},
146 {"omp", OPTGROUP_OMP},
147 {"vec", OPTGROUP_VEC},
148 {"optall", OPTGROUP_ALL},
149 {NULL, 0}
152 gcc::dump_manager::dump_manager ():
153 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
154 m_extra_dump_files (NULL),
155 m_extra_dump_files_in_use (0),
156 m_extra_dump_files_alloced (0)
160 gcc::dump_manager::~dump_manager ()
162 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
164 dump_file_info *dfi = &m_extra_dump_files[i];
165 /* suffix, swtch, glob are statically allocated for the entries
166 in dump_files, and for statistics, but are dynamically allocated
167 for those for passes. */
168 if (dfi->owns_strings)
170 XDELETEVEC (const_cast <char *> (dfi->suffix));
171 XDELETEVEC (const_cast <char *> (dfi->swtch));
172 XDELETEVEC (const_cast <char *> (dfi->glob));
174 /* These, if non-NULL, are always dynamically allocated. */
175 XDELETEVEC (const_cast <char *> (dfi->pfilename));
176 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
178 XDELETEVEC (m_extra_dump_files);
181 unsigned int
182 gcc::dump_manager::
183 dump_register (const char *suffix, const char *swtch, const char *glob,
184 int flags, int optgroup_flags,
185 bool take_ownership)
187 int num = m_next_dump++;
189 size_t count = m_extra_dump_files_in_use++;
191 if (count >= m_extra_dump_files_alloced)
193 if (m_extra_dump_files_alloced == 0)
194 m_extra_dump_files_alloced = 32;
195 else
196 m_extra_dump_files_alloced *= 2;
197 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
198 m_extra_dump_files,
199 m_extra_dump_files_alloced);
202 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
203 m_extra_dump_files[count].suffix = suffix;
204 m_extra_dump_files[count].swtch = swtch;
205 m_extra_dump_files[count].glob = glob;
206 m_extra_dump_files[count].pflags = flags;
207 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
208 m_extra_dump_files[count].num = num;
209 m_extra_dump_files[count].owns_strings = take_ownership;
211 return count + TDI_end;
215 /* Return the dump_file_info for the given phase. */
217 struct dump_file_info *
218 gcc::dump_manager::
219 get_dump_file_info (int phase) const
221 if (phase < TDI_end)
222 return &dump_files[phase];
223 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
224 return NULL;
225 else
226 return m_extra_dump_files + (phase - TDI_end);
229 /* Locate the dump_file_info with swtch equal to SWTCH,
230 or return NULL if no such dump_file_info exists. */
232 struct dump_file_info *
233 gcc::dump_manager::
234 get_dump_file_info_by_switch (const char *swtch) const
236 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
237 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
238 return &m_extra_dump_files[i];
240 /* Not found. */
241 return NULL;
245 /* Return the name of the dump file for the given phase.
246 The caller is responsible for calling free on the returned
247 buffer.
248 If the dump is not enabled, returns NULL. */
250 char *
251 gcc::dump_manager::
252 get_dump_file_name (int phase) const
254 struct dump_file_info *dfi;
256 if (phase == TDI_none)
257 return NULL;
259 dfi = get_dump_file_info (phase);
261 return get_dump_file_name (dfi);
264 /* Return the name of the dump file for the given dump_file_info.
265 The caller is responsible for calling free on the returned
266 buffer.
267 If the dump is not enabled, returns NULL. */
269 char *
270 gcc::dump_manager::
271 get_dump_file_name (struct dump_file_info *dfi) const
273 char dump_id[10];
275 gcc_assert (dfi);
277 if (dfi->pstate == 0)
278 return NULL;
280 /* If available, use the command line dump filename. */
281 if (dfi->pfilename)
282 return xstrdup (dfi->pfilename);
284 if (dfi->num < 0)
285 dump_id[0] = '\0';
286 else
288 /* LANG, TREE, RTL, IPA. */
289 char suffix = "ltri"[TDF_KIND (dfi->pflags)];
291 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix)
292 < 0)
293 dump_id[0] = '\0';
296 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
299 /* For a given DFI, open an alternate dump filename (which could also
300 be a standard stream such as stdout/stderr). If the alternate dump
301 file cannot be opened, return NULL. */
303 static FILE *
304 dump_open_alternate_stream (struct dump_file_info *dfi)
306 FILE *stream ;
307 if (!dfi->alt_filename)
308 return NULL;
310 if (dfi->alt_stream)
311 return dfi->alt_stream;
313 stream = strcmp ("stderr", dfi->alt_filename) == 0
314 ? stderr
315 : strcmp ("stdout", dfi->alt_filename) == 0
316 ? stdout
317 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
319 if (!stream)
320 error ("could not open dump file %qs: %m", dfi->alt_filename);
321 else
322 dfi->alt_state = 1;
324 return stream;
327 /* Print source location on DFILE if enabled. */
329 void
330 dump_loc (int dump_kind, FILE *dfile, source_location loc)
332 if (dump_kind)
334 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
335 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
336 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
337 else if (current_function_decl)
338 fprintf (dfile, "%s:%d:%d: note: ",
339 DECL_SOURCE_FILE (current_function_decl),
340 DECL_SOURCE_LINE (current_function_decl),
341 DECL_SOURCE_COLUMN (current_function_decl));
345 /* Dump gimple statement GS with SPC indentation spaces and
346 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
348 void
349 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple *gs, int spc)
351 if (dump_file && (dump_kind & pflags))
352 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
354 if (alt_dump_file && (dump_kind & alt_flags))
355 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
358 /* Similar to dump_gimple_stmt, except additionally print source location. */
360 void
361 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
362 gimple *gs, int spc)
364 if (dump_file && (dump_kind & pflags))
366 dump_loc (dump_kind, dump_file, loc);
367 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
370 if (alt_dump_file && (dump_kind & alt_flags))
372 dump_loc (dump_kind, alt_dump_file, loc);
373 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
377 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
378 DUMP_KIND is enabled. */
380 void
381 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
383 if (dump_file && (dump_kind & pflags))
384 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
386 if (alt_dump_file && (dump_kind & alt_flags))
387 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
391 /* Similar to dump_generic_expr, except additionally print the source
392 location. */
394 void
395 dump_generic_expr_loc (int dump_kind, source_location loc,
396 int extra_dump_flags, tree t)
398 if (dump_file && (dump_kind & pflags))
400 dump_loc (dump_kind, dump_file, loc);
401 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
404 if (alt_dump_file && (dump_kind & alt_flags))
406 dump_loc (dump_kind, alt_dump_file, loc);
407 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
411 /* Output a formatted message using FORMAT on appropriate dump streams. */
413 void
414 dump_printf (int dump_kind, const char *format, ...)
416 if (dump_file && (dump_kind & pflags))
418 va_list ap;
419 va_start (ap, format);
420 vfprintf (dump_file, format, ap);
421 va_end (ap);
424 if (alt_dump_file && (dump_kind & alt_flags))
426 va_list ap;
427 va_start (ap, format);
428 vfprintf (alt_dump_file, format, ap);
429 va_end (ap);
433 /* Similar to dump_printf, except source location is also printed. */
435 void
436 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
438 if (dump_file && (dump_kind & pflags))
440 va_list ap;
441 dump_loc (dump_kind, dump_file, loc);
442 va_start (ap, format);
443 vfprintf (dump_file, format, ap);
444 va_end (ap);
447 if (alt_dump_file && (dump_kind & alt_flags))
449 va_list ap;
450 dump_loc (dump_kind, alt_dump_file, loc);
451 va_start (ap, format);
452 vfprintf (alt_dump_file, format, ap);
453 va_end (ap);
457 /* Start a dump for PHASE. Store user-supplied dump flags in
458 *FLAG_PTR. Return the number of streams opened. Set globals
459 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
460 set dump_flags appropriately for both pass dump stream and
461 -fopt-info stream. */
464 gcc::dump_manager::
465 dump_start (int phase, int *flag_ptr)
467 int count = 0;
468 char *name;
469 struct dump_file_info *dfi;
470 FILE *stream;
471 if (phase == TDI_none || !dump_phase_enabled_p (phase))
472 return 0;
474 dfi = get_dump_file_info (phase);
475 name = get_dump_file_name (phase);
476 if (name)
478 stream = strcmp ("stderr", name) == 0
479 ? stderr
480 : strcmp ("stdout", name) == 0
481 ? stdout
482 : fopen (name, dfi->pstate < 0 ? "w" : "a");
483 if (!stream)
484 error ("could not open dump file %qs: %m", name);
485 else
487 dfi->pstate = 1;
488 count++;
490 free (name);
491 dfi->pstream = stream;
492 dump_file = dfi->pstream;
493 /* Initialize current dump flags. */
494 pflags = TDF_FLAGS (dfi->pflags);
497 stream = dump_open_alternate_stream (dfi);
498 if (stream)
500 dfi->alt_stream = stream;
501 count++;
502 alt_dump_file = dfi->alt_stream;
503 /* Initialize current -fopt-info flags. */
504 alt_flags = TDF_FLAGS (dfi->alt_flags);
507 if (flag_ptr)
508 *flag_ptr = dfi->pflags;
510 return count;
513 /* Finish a tree dump for PHASE and close associated dump streams. Also
514 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
516 void
517 gcc::dump_manager::
518 dump_finish (int phase)
520 struct dump_file_info *dfi;
522 if (phase < 0)
523 return;
524 dfi = get_dump_file_info (phase);
525 if (dfi->pstream && (!dfi->pfilename
526 || (strcmp ("stderr", dfi->pfilename) != 0
527 && strcmp ("stdout", dfi->pfilename) != 0)))
528 fclose (dfi->pstream);
530 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
531 && strcmp ("stdout", dfi->alt_filename) != 0)
532 fclose (dfi->alt_stream);
534 dfi->alt_stream = NULL;
535 dfi->pstream = NULL;
536 dump_file = NULL;
537 alt_dump_file = NULL;
538 dump_flags = TDI_none;
539 alt_flags = 0;
540 pflags = 0;
543 /* Begin a tree dump for PHASE. Stores any user supplied flag in
544 *FLAG_PTR and returns a stream to write to. If the dump is not
545 enabled, returns NULL.
546 Multiple calls will reopen and append to the dump file. */
548 FILE *
549 dump_begin (int phase, int *flag_ptr)
551 return g->get_dumps ()->dump_begin (phase, flag_ptr);
554 FILE *
555 gcc::dump_manager::
556 dump_begin (int phase, int *flag_ptr)
558 char *name;
559 struct dump_file_info *dfi;
560 FILE *stream;
562 if (phase == TDI_none || !dump_phase_enabled_p (phase))
563 return NULL;
565 name = get_dump_file_name (phase);
566 if (!name)
567 return NULL;
568 dfi = get_dump_file_info (phase);
570 stream = strcmp ("stderr", name) == 0
571 ? stderr
572 : strcmp ("stdout", name) == 0
573 ? stdout
574 : fopen (name, dfi->pstate < 0 ? "w" : "a");
576 if (!stream)
577 error ("could not open dump file %qs: %m", name);
578 else
579 dfi->pstate = 1;
580 free (name);
582 if (flag_ptr)
583 *flag_ptr = dfi->pflags;
585 /* Initialize current flags */
586 pflags = dfi->pflags;
587 return stream;
590 /* Returns nonzero if dump PHASE is enabled for at least one stream.
591 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
592 any phase. */
595 gcc::dump_manager::
596 dump_phase_enabled_p (int phase) const
598 if (phase == TDI_tree_all)
600 size_t i;
601 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
602 if (dump_files[i].pstate || dump_files[i].alt_state)
603 return 1;
604 for (i = 0; i < m_extra_dump_files_in_use; i++)
605 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
606 return 1;
607 return 0;
609 else
611 struct dump_file_info *dfi = get_dump_file_info (phase);
612 return dfi->pstate || dfi->alt_state;
616 /* Returns nonzero if tree dump PHASE has been initialized. */
619 gcc::dump_manager::
620 dump_initialized_p (int phase) const
622 struct dump_file_info *dfi = get_dump_file_info (phase);
623 return dfi->pstate > 0 || dfi->alt_state > 0;
626 /* Returns the switch name of PHASE. */
628 const char *
629 dump_flag_name (int phase)
631 return g->get_dumps ()->dump_flag_name (phase);
634 const char *
635 gcc::dump_manager::
636 dump_flag_name (int phase) const
638 struct dump_file_info *dfi = get_dump_file_info (phase);
639 return dfi->swtch;
642 /* Finish a tree dump for PHASE. STREAM is the stream created by
643 dump_begin. */
645 void
646 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
648 if (stream != stderr && stream != stdout)
649 fclose (stream);
652 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
653 enabled tree dumps. */
656 gcc::dump_manager::
657 dump_enable_all (int flags, const char *filename)
659 int ir_dump_type = TDF_KIND (flags);
660 int n = 0;
661 size_t i;
663 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
665 if (TDF_KIND (dump_files[i].pflags) == ir_dump_type)
667 const char *old_filename = dump_files[i].pfilename;
668 dump_files[i].pstate = -1;
669 dump_files[i].pflags |= flags;
670 n++;
671 /* Override the existing filename. */
672 if (filename)
674 dump_files[i].pfilename = xstrdup (filename);
675 /* Since it is a command-line provided file, which is
676 common to all the phases, use it in append mode. */
677 dump_files[i].pstate = 1;
679 if (old_filename && filename != old_filename)
680 free (CONST_CAST (char *, old_filename));
684 for (i = 0; i < m_extra_dump_files_in_use; i++)
686 if (TDF_KIND (m_extra_dump_files[i].pflags) == ir_dump_type)
688 const char *old_filename = m_extra_dump_files[i].pfilename;
689 m_extra_dump_files[i].pstate = -1;
690 m_extra_dump_files[i].pflags |= flags;
691 n++;
692 /* Override the existing filename. */
693 if (filename)
695 m_extra_dump_files[i].pfilename = xstrdup (filename);
696 /* Since it is a command-line provided file, which is
697 common to all the phases, use it in append mode. */
698 m_extra_dump_files[i].pstate = 1;
700 if (old_filename && filename != old_filename)
701 free (CONST_CAST (char *, old_filename));
705 return n;
708 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
709 Enable dumps with FLAGS on FILENAME. Return the number of enabled
710 dumps. */
713 gcc::dump_manager::
714 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
716 int n = 0;
717 size_t i;
719 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
721 if ((dump_files[i].optgroup_flags & optgroup_flags))
723 const char *old_filename = dump_files[i].alt_filename;
724 /* Since this file is shared among different passes, it
725 should be opened in append mode. */
726 dump_files[i].alt_state = 1;
727 dump_files[i].alt_flags |= flags;
728 n++;
729 /* Override the existing filename. */
730 if (filename)
731 dump_files[i].alt_filename = xstrdup (filename);
732 if (old_filename && filename != old_filename)
733 free (CONST_CAST (char *, old_filename));
737 for (i = 0; i < m_extra_dump_files_in_use; i++)
739 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
741 const char *old_filename = m_extra_dump_files[i].alt_filename;
742 /* Since this file is shared among different passes, it
743 should be opened in append mode. */
744 m_extra_dump_files[i].alt_state = 1;
745 m_extra_dump_files[i].alt_flags |= flags;
746 n++;
747 /* Override the existing filename. */
748 if (filename)
749 m_extra_dump_files[i].alt_filename = xstrdup (filename);
750 if (old_filename && filename != old_filename)
751 free (CONST_CAST (char *, old_filename));
755 return n;
758 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
759 relevant details in the dump_files array. */
762 gcc::dump_manager::
763 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
765 const char *option_value;
766 const char *ptr;
767 int flags;
769 if (doglob && !dfi->glob)
770 return 0;
772 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
773 if (!option_value)
774 return 0;
776 if (*option_value && *option_value != '-' && *option_value != '=')
777 return 0;
779 ptr = option_value;
780 flags = 0;
782 while (*ptr)
784 const struct dump_option_value_info *option_ptr;
785 const char *end_ptr;
786 const char *eq_ptr;
787 unsigned length;
789 while (*ptr == '-')
790 ptr++;
791 end_ptr = strchr (ptr, '-');
792 eq_ptr = strchr (ptr, '=');
794 if (eq_ptr && !end_ptr)
795 end_ptr = eq_ptr;
797 if (!end_ptr)
798 end_ptr = ptr + strlen (ptr);
799 length = end_ptr - ptr;
801 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
802 if (strlen (option_ptr->name) == length
803 && !memcmp (option_ptr->name, ptr, length))
805 flags |= option_ptr->value;
806 goto found;
809 if (*ptr == '=')
811 /* Interpret rest of the argument as a dump filename. This
812 filename overrides other command line filenames. */
813 if (dfi->pfilename)
814 free (CONST_CAST (char *, dfi->pfilename));
815 dfi->pfilename = xstrdup (ptr + 1);
816 break;
818 else
819 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
820 length, ptr, dfi->swtch);
821 found:;
822 ptr = end_ptr;
825 dfi->pstate = -1;
826 dfi->pflags |= flags;
828 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
829 known dumps. */
830 if (dfi->suffix == NULL)
831 dump_enable_all (dfi->pflags, dfi->pfilename);
833 return 1;
837 gcc::dump_manager::
838 dump_switch_p (const char *arg)
840 size_t i;
841 int any = 0;
843 for (i = TDI_none + 1; i != TDI_end; i++)
844 any |= dump_switch_p_1 (arg, &dump_files[i], false);
846 /* Don't glob if we got a hit already */
847 if (!any)
848 for (i = TDI_none + 1; i != TDI_end; i++)
849 any |= dump_switch_p_1 (arg, &dump_files[i], true);
851 for (i = 0; i < m_extra_dump_files_in_use; i++)
852 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
854 if (!any)
855 for (i = 0; i < m_extra_dump_files_in_use; i++)
856 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
859 return any;
862 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
863 and filename. Return non-zero if it is a recognized switch. */
865 static int
866 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
867 char **filename)
869 const char *option_value;
870 const char *ptr;
872 option_value = arg;
873 ptr = option_value;
875 *filename = NULL;
876 *flags = 0;
877 *optgroup_flags = 0;
879 if (!ptr)
880 return 1; /* Handle '-fopt-info' without any additional options. */
882 while (*ptr)
884 const struct dump_option_value_info *option_ptr;
885 const char *end_ptr;
886 const char *eq_ptr;
887 unsigned length;
889 while (*ptr == '-')
890 ptr++;
891 end_ptr = strchr (ptr, '-');
892 eq_ptr = strchr (ptr, '=');
894 if (eq_ptr && !end_ptr)
895 end_ptr = eq_ptr;
897 if (!end_ptr)
898 end_ptr = ptr + strlen (ptr);
899 length = end_ptr - ptr;
901 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
902 option_ptr++)
903 if (strlen (option_ptr->name) == length
904 && !memcmp (option_ptr->name, ptr, length))
906 *flags |= option_ptr->value;
907 goto found;
910 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
911 if (strlen (option_ptr->name) == length
912 && !memcmp (option_ptr->name, ptr, length))
914 *optgroup_flags |= option_ptr->value;
915 goto found;
918 if (*ptr == '=')
920 /* Interpret rest of the argument as a dump filename. This
921 filename overrides other command line filenames. */
922 *filename = xstrdup (ptr + 1);
923 break;
925 else
927 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
928 length, ptr, arg);
929 return 0;
931 found:;
932 ptr = end_ptr;
935 return 1;
938 /* Return non-zero if ARG is a recognized switch for
939 -fopt-info. Return zero otherwise. */
942 opt_info_switch_p (const char *arg)
944 int flags;
945 int optgroup_flags;
946 char *filename;
947 static char *file_seen = NULL;
948 gcc::dump_manager *dumps = g->get_dumps ();
950 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
951 return 0;
953 if (!filename)
954 filename = xstrdup ("stderr");
956 /* Bail out if a different filename has been specified. */
957 if (file_seen && strcmp (file_seen, filename))
959 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
960 arg);
961 return 1;
964 file_seen = xstrdup (filename);
965 if (!flags)
966 flags = MSG_OPTIMIZED_LOCATIONS;
967 if (!optgroup_flags)
968 optgroup_flags = OPTGROUP_ALL;
970 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
973 /* Print basic block on the dump streams. */
975 void
976 dump_basic_block (int dump_kind, basic_block bb, int indent)
978 if (dump_file && (dump_kind & pflags))
979 dump_bb (dump_file, bb, indent, TDF_DETAILS);
980 if (alt_dump_file && (dump_kind & alt_flags))
981 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
984 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
986 void
987 dump_function (int phase, tree fn)
989 FILE *stream;
990 int flags;
992 stream = dump_begin (phase, &flags);
993 if (stream)
995 dump_function_to_file (fn, stream, flags);
996 dump_end (phase, stream);
1000 /* Print information from the combine pass on dump_file. */
1002 void
1003 print_combine_total_stats (void)
1005 if (dump_file)
1006 dump_combine_total_stats (dump_file);
1009 /* Enable RTL dump for all the RTL passes. */
1011 bool
1012 enable_rtl_dump_file (void)
1014 gcc::dump_manager *dumps = g->get_dumps ();
1015 int num_enabled =
1016 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
1017 return num_enabled > 0;