* lib/ubsan-dg.exp (check_effective_target_fsanitize_undefined):
[official-gcc.git] / gcc / dumpfile.c
blobeb178feae07308ad005f4485fe8aa9dbea19e2cd
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);
220 /* Locate the dump_file_info with swtch equal to SWTCH,
221 or return NULL if no such dump_file_info exists. */
223 struct dump_file_info *
224 gcc::dump_manager::
225 get_dump_file_info_by_switch (const char *swtch) const
227 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
228 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
229 return &m_extra_dump_files[i];
231 /* Not found. */
232 return NULL;
236 /* Return the name of the dump file for the given phase.
237 The caller is responsible for calling free on the returned
238 buffer.
239 If the dump is not enabled, returns NULL. */
241 char *
242 gcc::dump_manager::
243 get_dump_file_name (int phase) const
245 struct dump_file_info *dfi;
247 if (phase == TDI_none)
248 return NULL;
250 dfi = get_dump_file_info (phase);
252 return get_dump_file_name (dfi);
255 /* Return the name of the dump file for the given dump_file_info.
256 The caller is responsible for calling free on the returned
257 buffer.
258 If the dump is not enabled, returns NULL. */
260 char *
261 gcc::dump_manager::
262 get_dump_file_name (struct dump_file_info *dfi) const
264 char dump_id[10];
266 gcc_assert (dfi);
268 if (dfi->pstate == 0)
269 return NULL;
271 /* If available, use the command line dump filename. */
272 if (dfi->pfilename)
273 return xstrdup (dfi->pfilename);
275 if (dfi->num < 0)
276 dump_id[0] = '\0';
277 else
279 char suffix;
280 if (dfi->pflags & TDF_TREE)
281 suffix = 't';
282 else if (dfi->pflags & TDF_IPA)
283 suffix = 'i';
284 else
285 suffix = 'r';
287 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
288 dump_id[0] = '\0';
291 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
294 /* For a given DFI, open an alternate dump filename (which could also
295 be a standard stream such as stdout/stderr). If the alternate dump
296 file cannot be opened, return NULL. */
298 static FILE *
299 dump_open_alternate_stream (struct dump_file_info *dfi)
301 FILE *stream ;
302 if (!dfi->alt_filename)
303 return NULL;
305 if (dfi->alt_stream)
306 return dfi->alt_stream;
308 stream = strcmp ("stderr", dfi->alt_filename) == 0
309 ? stderr
310 : strcmp ("stdout", dfi->alt_filename) == 0
311 ? stdout
312 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
314 if (!stream)
315 error ("could not open dump file %qs: %m", dfi->alt_filename);
316 else
317 dfi->alt_state = 1;
319 return stream;
322 /* Print source location on DFILE if enabled. */
324 void
325 dump_loc (int dump_kind, FILE *dfile, source_location loc)
327 if (dump_kind)
329 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
330 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
331 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
332 else if (current_function_decl)
333 fprintf (dfile, "%s:%d:%d: note: ",
334 DECL_SOURCE_FILE (current_function_decl),
335 DECL_SOURCE_LINE (current_function_decl),
336 DECL_SOURCE_COLUMN (current_function_decl));
340 /* Dump gimple statement GS with SPC indentation spaces and
341 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
343 void
344 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
346 if (dump_file && (dump_kind & pflags))
347 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
349 if (alt_dump_file && (dump_kind & alt_flags))
350 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
353 /* Similar to dump_gimple_stmt, except additionally print source location. */
355 void
356 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
357 gimple gs, int spc)
359 if (dump_file && (dump_kind & pflags))
361 dump_loc (dump_kind, dump_file, loc);
362 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
365 if (alt_dump_file && (dump_kind & alt_flags))
367 dump_loc (dump_kind, alt_dump_file, loc);
368 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
372 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
373 DUMP_KIND is enabled. */
375 void
376 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
378 if (dump_file && (dump_kind & pflags))
379 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
381 if (alt_dump_file && (dump_kind & alt_flags))
382 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
386 /* Similar to dump_generic_expr, except additionally print the source
387 location. */
389 void
390 dump_generic_expr_loc (int dump_kind, source_location loc,
391 int extra_dump_flags, tree t)
393 if (dump_file && (dump_kind & pflags))
395 dump_loc (dump_kind, dump_file, loc);
396 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
399 if (alt_dump_file && (dump_kind & alt_flags))
401 dump_loc (dump_kind, alt_dump_file, loc);
402 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
406 /* Output a formatted message using FORMAT on appropriate dump streams. */
408 void
409 dump_printf (int dump_kind, const char *format, ...)
411 if (dump_file && (dump_kind & pflags))
413 va_list ap;
414 va_start (ap, format);
415 vfprintf (dump_file, format, ap);
416 va_end (ap);
419 if (alt_dump_file && (dump_kind & alt_flags))
421 va_list ap;
422 va_start (ap, format);
423 vfprintf (alt_dump_file, format, ap);
424 va_end (ap);
428 /* Similar to dump_printf, except source location is also printed. */
430 void
431 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
433 if (dump_file && (dump_kind & pflags))
435 va_list ap;
436 dump_loc (dump_kind, dump_file, loc);
437 va_start (ap, format);
438 vfprintf (dump_file, format, ap);
439 va_end (ap);
442 if (alt_dump_file && (dump_kind & alt_flags))
444 va_list ap;
445 dump_loc (dump_kind, alt_dump_file, loc);
446 va_start (ap, format);
447 vfprintf (alt_dump_file, format, ap);
448 va_end (ap);
452 /* Start a dump for PHASE. Store user-supplied dump flags in
453 *FLAG_PTR. Return the number of streams opened. Set globals
454 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
455 set dump_flags appropriately for both pass dump stream and
456 -fopt-info stream. */
459 gcc::dump_manager::
460 dump_start (int phase, int *flag_ptr)
462 int count = 0;
463 char *name;
464 struct dump_file_info *dfi;
465 FILE *stream;
466 if (phase == TDI_none || !dump_phase_enabled_p (phase))
467 return 0;
469 dfi = get_dump_file_info (phase);
470 name = get_dump_file_name (phase);
471 if (name)
473 stream = strcmp ("stderr", name) == 0
474 ? stderr
475 : strcmp ("stdout", name) == 0
476 ? stdout
477 : fopen (name, dfi->pstate < 0 ? "w" : "a");
478 if (!stream)
479 error ("could not open dump file %qs: %m", name);
480 else
482 dfi->pstate = 1;
483 count++;
485 free (name);
486 dfi->pstream = stream;
487 dump_file = dfi->pstream;
488 /* Initialize current dump flags. */
489 pflags = dfi->pflags;
492 stream = dump_open_alternate_stream (dfi);
493 if (stream)
495 dfi->alt_stream = stream;
496 count++;
497 alt_dump_file = dfi->alt_stream;
498 /* Initialize current -fopt-info flags. */
499 alt_flags = dfi->alt_flags;
502 if (flag_ptr)
503 *flag_ptr = dfi->pflags;
505 return count;
508 /* Finish a tree dump for PHASE and close associated dump streams. Also
509 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
511 void
512 gcc::dump_manager::
513 dump_finish (int phase)
515 struct dump_file_info *dfi;
517 if (phase < 0)
518 return;
519 dfi = get_dump_file_info (phase);
520 if (dfi->pstream && (!dfi->pfilename
521 || (strcmp ("stderr", dfi->pfilename) != 0
522 && strcmp ("stdout", dfi->pfilename) != 0)))
523 fclose (dfi->pstream);
525 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
526 && strcmp ("stdout", dfi->alt_filename) != 0)
527 fclose (dfi->alt_stream);
529 dfi->alt_stream = NULL;
530 dfi->pstream = NULL;
531 dump_file = NULL;
532 alt_dump_file = NULL;
533 dump_flags = TDI_none;
534 alt_flags = 0;
535 pflags = 0;
538 /* Begin a tree dump for PHASE. Stores any user supplied flag in
539 *FLAG_PTR and returns a stream to write to. If the dump is not
540 enabled, returns NULL.
541 Multiple calls will reopen and append to the dump file. */
543 FILE *
544 dump_begin (int phase, int *flag_ptr)
546 return g->get_dumps ()->dump_begin (phase, flag_ptr);
549 FILE *
550 gcc::dump_manager::
551 dump_begin (int phase, int *flag_ptr)
553 char *name;
554 struct dump_file_info *dfi;
555 FILE *stream;
557 if (phase == TDI_none || !dump_phase_enabled_p (phase))
558 return NULL;
560 name = get_dump_file_name (phase);
561 if (!name)
562 return NULL;
563 dfi = get_dump_file_info (phase);
565 stream = strcmp ("stderr", name) == 0
566 ? stderr
567 : strcmp ("stdout", name) == 0
568 ? stdout
569 : fopen (name, dfi->pstate < 0 ? "w" : "a");
571 if (!stream)
572 error ("could not open dump file %qs: %m", name);
573 else
574 dfi->pstate = 1;
575 free (name);
577 if (flag_ptr)
578 *flag_ptr = dfi->pflags;
580 /* Initialize current flags */
581 pflags = dfi->pflags;
582 return stream;
585 /* Returns nonzero if dump PHASE is enabled for at least one stream.
586 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
587 any phase. */
590 gcc::dump_manager::
591 dump_phase_enabled_p (int phase) const
593 if (phase == TDI_tree_all)
595 size_t i;
596 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
597 if (dump_files[i].pstate || dump_files[i].alt_state)
598 return 1;
599 for (i = 0; i < m_extra_dump_files_in_use; i++)
600 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
601 return 1;
602 return 0;
604 else
606 struct dump_file_info *dfi = get_dump_file_info (phase);
607 return dfi->pstate || dfi->alt_state;
611 /* Returns nonzero if tree dump PHASE has been initialized. */
614 gcc::dump_manager::
615 dump_initialized_p (int phase) const
617 struct dump_file_info *dfi = get_dump_file_info (phase);
618 return dfi->pstate > 0 || dfi->alt_state > 0;
621 /* Returns the switch name of PHASE. */
623 const char *
624 dump_flag_name (int phase)
626 return g->get_dumps ()->dump_flag_name (phase);
629 const char *
630 gcc::dump_manager::
631 dump_flag_name (int phase) const
633 struct dump_file_info *dfi = get_dump_file_info (phase);
634 return dfi->swtch;
637 /* Finish a tree dump for PHASE. STREAM is the stream created by
638 dump_begin. */
640 void
641 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
643 if (stream != stderr && stream != stdout)
644 fclose (stream);
647 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
648 enabled tree dumps. */
651 gcc::dump_manager::
652 dump_enable_all (int flags, const char *filename)
654 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
655 int n = 0;
656 size_t i;
658 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
660 if ((dump_files[i].pflags & ir_dump_type))
662 const char *old_filename = dump_files[i].pfilename;
663 dump_files[i].pstate = -1;
664 dump_files[i].pflags |= flags;
665 n++;
666 /* Override the existing filename. */
667 if (filename)
669 dump_files[i].pfilename = xstrdup (filename);
670 /* Since it is a command-line provided file, which is
671 common to all the phases, use it in append mode. */
672 dump_files[i].pstate = 1;
674 if (old_filename && filename != old_filename)
675 free (CONST_CAST (char *, old_filename));
679 for (i = 0; i < m_extra_dump_files_in_use; i++)
681 if ((m_extra_dump_files[i].pflags & ir_dump_type))
683 const char *old_filename = m_extra_dump_files[i].pfilename;
684 m_extra_dump_files[i].pstate = -1;
685 m_extra_dump_files[i].pflags |= flags;
686 n++;
687 /* Override the existing filename. */
688 if (filename)
690 m_extra_dump_files[i].pfilename = xstrdup (filename);
691 /* Since it is a command-line provided file, which is
692 common to all the phases, use it in append mode. */
693 m_extra_dump_files[i].pstate = 1;
695 if (old_filename && filename != old_filename)
696 free (CONST_CAST (char *, old_filename));
700 return n;
703 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
704 Enable dumps with FLAGS on FILENAME. Return the number of enabled
705 dumps. */
708 gcc::dump_manager::
709 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
711 int n = 0;
712 size_t i;
714 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
716 if ((dump_files[i].optgroup_flags & optgroup_flags))
718 const char *old_filename = dump_files[i].alt_filename;
719 /* Since this file is shared among different passes, it
720 should be opened in append mode. */
721 dump_files[i].alt_state = 1;
722 dump_files[i].alt_flags |= flags;
723 n++;
724 /* Override the existing filename. */
725 if (filename)
726 dump_files[i].alt_filename = xstrdup (filename);
727 if (old_filename && filename != old_filename)
728 free (CONST_CAST (char *, old_filename));
732 for (i = 0; i < m_extra_dump_files_in_use; i++)
734 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
736 const char *old_filename = m_extra_dump_files[i].alt_filename;
737 /* Since this file is shared among different passes, it
738 should be opened in append mode. */
739 m_extra_dump_files[i].alt_state = 1;
740 m_extra_dump_files[i].alt_flags |= flags;
741 n++;
742 /* Override the existing filename. */
743 if (filename)
744 m_extra_dump_files[i].alt_filename = xstrdup (filename);
745 if (old_filename && filename != old_filename)
746 free (CONST_CAST (char *, old_filename));
750 return n;
753 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
754 relevant details in the dump_files array. */
757 gcc::dump_manager::
758 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
760 const char *option_value;
761 const char *ptr;
762 int flags;
764 if (doglob && !dfi->glob)
765 return 0;
767 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
768 if (!option_value)
769 return 0;
771 if (*option_value && *option_value != '-' && *option_value != '=')
772 return 0;
774 ptr = option_value;
775 flags = 0;
777 while (*ptr)
779 const struct dump_option_value_info *option_ptr;
780 const char *end_ptr;
781 const char *eq_ptr;
782 unsigned length;
784 while (*ptr == '-')
785 ptr++;
786 end_ptr = strchr (ptr, '-');
787 eq_ptr = strchr (ptr, '=');
789 if (eq_ptr && !end_ptr)
790 end_ptr = eq_ptr;
792 if (!end_ptr)
793 end_ptr = ptr + strlen (ptr);
794 length = end_ptr - ptr;
796 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
797 if (strlen (option_ptr->name) == length
798 && !memcmp (option_ptr->name, ptr, length))
800 flags |= option_ptr->value;
801 goto found;
804 if (*ptr == '=')
806 /* Interpret rest of the argument as a dump filename. This
807 filename overrides other command line filenames. */
808 if (dfi->pfilename)
809 free (CONST_CAST (char *, dfi->pfilename));
810 dfi->pfilename = xstrdup (ptr + 1);
811 break;
813 else
814 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
815 length, ptr, dfi->swtch);
816 found:;
817 ptr = end_ptr;
820 dfi->pstate = -1;
821 dfi->pflags |= flags;
823 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
824 known dumps. */
825 if (dfi->suffix == NULL)
826 dump_enable_all (dfi->pflags, dfi->pfilename);
828 return 1;
832 gcc::dump_manager::
833 dump_switch_p (const char *arg)
835 size_t i;
836 int any = 0;
838 for (i = TDI_none + 1; i != TDI_end; i++)
839 any |= dump_switch_p_1 (arg, &dump_files[i], false);
841 /* Don't glob if we got a hit already */
842 if (!any)
843 for (i = TDI_none + 1; i != TDI_end; i++)
844 any |= dump_switch_p_1 (arg, &dump_files[i], true);
846 for (i = 0; i < m_extra_dump_files_in_use; i++)
847 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
849 if (!any)
850 for (i = 0; i < m_extra_dump_files_in_use; i++)
851 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
854 return any;
857 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
858 and filename. Return non-zero if it is a recognized switch. */
860 static int
861 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
862 char **filename)
864 const char *option_value;
865 const char *ptr;
867 option_value = arg;
868 ptr = option_value;
870 *filename = NULL;
871 *flags = 0;
872 *optgroup_flags = 0;
874 if (!ptr)
875 return 1; /* Handle '-fopt-info' without any additional options. */
877 while (*ptr)
879 const struct dump_option_value_info *option_ptr;
880 const char *end_ptr;
881 const char *eq_ptr;
882 unsigned length;
884 while (*ptr == '-')
885 ptr++;
886 end_ptr = strchr (ptr, '-');
887 eq_ptr = strchr (ptr, '=');
889 if (eq_ptr && !end_ptr)
890 end_ptr = eq_ptr;
892 if (!end_ptr)
893 end_ptr = ptr + strlen (ptr);
894 length = end_ptr - ptr;
896 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
897 option_ptr++)
898 if (strlen (option_ptr->name) == length
899 && !memcmp (option_ptr->name, ptr, length))
901 *flags |= option_ptr->value;
902 goto found;
905 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
906 if (strlen (option_ptr->name) == length
907 && !memcmp (option_ptr->name, ptr, length))
909 *optgroup_flags |= option_ptr->value;
910 goto found;
913 if (*ptr == '=')
915 /* Interpret rest of the argument as a dump filename. This
916 filename overrides other command line filenames. */
917 *filename = xstrdup (ptr + 1);
918 break;
920 else
922 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
923 length, ptr, arg);
924 return 0;
926 found:;
927 ptr = end_ptr;
930 return 1;
933 /* Return non-zero if ARG is a recognized switch for
934 -fopt-info. Return zero otherwise. */
937 opt_info_switch_p (const char *arg)
939 int flags;
940 int optgroup_flags;
941 char *filename;
942 static char *file_seen = NULL;
943 gcc::dump_manager *dumps = g->get_dumps ();
945 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
946 return 0;
948 if (!filename)
949 filename = xstrdup ("stderr");
951 /* Bail out if a different filename has been specified. */
952 if (file_seen && strcmp (file_seen, filename))
954 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
955 arg);
956 return 1;
959 file_seen = xstrdup (filename);
960 if (!flags)
961 flags = MSG_OPTIMIZED_LOCATIONS;
962 if (!optgroup_flags)
963 optgroup_flags = OPTGROUP_ALL;
965 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
968 /* Print basic block on the dump streams. */
970 void
971 dump_basic_block (int dump_kind, basic_block bb, int indent)
973 if (dump_file && (dump_kind & pflags))
974 dump_bb (dump_file, bb, indent, TDF_DETAILS);
975 if (alt_dump_file && (dump_kind & alt_flags))
976 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
979 /* Print information from the combine pass on dump_file. */
981 void
982 print_combine_total_stats (void)
984 if (dump_file)
985 dump_combine_total_stats (dump_file);
988 /* Enable RTL dump for all the RTL passes. */
990 bool
991 enable_rtl_dump_file (void)
993 gcc::dump_manager *dumps = g->get_dumps ();
994 int num_enabled =
995 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
996 return num_enabled > 0;