PR 66861 Fix null pointer crash on mingw.
[official-gcc.git] / gcc / dumpfile.c
blob79dd810c05d1d0f73aa0ae4a62090ed08eb24e4f
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 "alias.h"
26 #include "tree.h"
27 #include "options.h"
28 #include "gimple-pretty-print.h"
29 #include "context.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},
55 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
56 0, 0, 0, 0, 0, false},
57 {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
58 0, 0, 0, 0, 0, false},
59 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
60 0, 0, 0, 0, 1, false},
61 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
62 0, 0, 0, 0, 2, false},
63 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
64 0, 0, 0, 0, 3, false},
65 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
66 0, 0, 0, 0, 4, false},
67 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
68 0, 0, 0, 0, 5, false},
69 #define FIRST_AUTO_NUMBERED_DUMP 6
71 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
72 0, 0, 0, 0, 0, false},
73 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
74 0, 0, 0, 0, 0, false},
75 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
76 0, 0, 0, 0, 0, false},
79 /* Define a name->number mapping for a dump flag value. */
80 struct dump_option_value_info
82 const char *const name; /* the name of the value */
83 const int value; /* the value of the name */
86 /* Table of dump options. This must be consistent with the TDF_* flags
87 in dumpfile.h and opt_info_options below. */
88 static const struct dump_option_value_info dump_options[] =
90 {"address", TDF_ADDRESS},
91 {"asmname", TDF_ASMNAME},
92 {"slim", TDF_SLIM},
93 {"raw", TDF_RAW},
94 {"graph", TDF_GRAPH},
95 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
96 | MSG_MISSED_OPTIMIZATION
97 | MSG_NOTE)},
98 {"cselib", TDF_CSELIB},
99 {"stats", TDF_STATS},
100 {"blocks", TDF_BLOCKS},
101 {"vops", TDF_VOPS},
102 {"lineno", TDF_LINENO},
103 {"uid", TDF_UID},
104 {"stmtaddr", TDF_STMTADDR},
105 {"memsyms", TDF_MEMSYMS},
106 {"verbose", TDF_VERBOSE},
107 {"eh", TDF_EH},
108 {"alias", TDF_ALIAS},
109 {"nouid", TDF_NOUID},
110 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
111 {"scev", TDF_SCEV},
112 {"optimized", MSG_OPTIMIZED_LOCATIONS},
113 {"missed", MSG_MISSED_OPTIMIZATION},
114 {"note", MSG_NOTE},
115 {"optall", MSG_ALL},
116 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
117 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
118 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
119 {NULL, 0}
122 /* A subset of the dump_options table which is used for -fopt-info
123 types. This must be consistent with the MSG_* flags in dumpfile.h.
125 static const struct dump_option_value_info optinfo_verbosity_options[] =
127 {"optimized", MSG_OPTIMIZED_LOCATIONS},
128 {"missed", MSG_MISSED_OPTIMIZATION},
129 {"note", MSG_NOTE},
130 {"all", MSG_ALL},
131 {NULL, 0}
134 /* Flags used for -fopt-info groups. */
135 static const struct dump_option_value_info optgroup_options[] =
137 {"ipa", OPTGROUP_IPA},
138 {"loop", OPTGROUP_LOOP},
139 {"inline", OPTGROUP_INLINE},
140 {"vec", OPTGROUP_VEC},
141 {"optall", OPTGROUP_ALL},
142 {NULL, 0}
145 gcc::dump_manager::dump_manager ():
146 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
147 m_extra_dump_files (NULL),
148 m_extra_dump_files_in_use (0),
149 m_extra_dump_files_alloced (0)
153 gcc::dump_manager::~dump_manager ()
155 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
157 dump_file_info *dfi = &m_extra_dump_files[i];
158 /* suffix, swtch, glob are statically allocated for the entries
159 in dump_files, and for statistics, but are dynamically allocated
160 for those for passes. */
161 if (dfi->owns_strings)
163 XDELETEVEC (const_cast <char *> (dfi->suffix));
164 XDELETEVEC (const_cast <char *> (dfi->swtch));
165 XDELETEVEC (const_cast <char *> (dfi->glob));
167 /* These, if non-NULL, are always dynamically allocated. */
168 XDELETEVEC (const_cast <char *> (dfi->pfilename));
169 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
171 XDELETEVEC (m_extra_dump_files);
174 unsigned int
175 gcc::dump_manager::
176 dump_register (const char *suffix, const char *swtch, const char *glob,
177 int flags, int optgroup_flags,
178 bool take_ownership)
180 int num = m_next_dump++;
182 size_t count = m_extra_dump_files_in_use++;
184 if (count >= m_extra_dump_files_alloced)
186 if (m_extra_dump_files_alloced == 0)
187 m_extra_dump_files_alloced = 32;
188 else
189 m_extra_dump_files_alloced *= 2;
190 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
191 m_extra_dump_files,
192 m_extra_dump_files_alloced);
195 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
196 m_extra_dump_files[count].suffix = suffix;
197 m_extra_dump_files[count].swtch = swtch;
198 m_extra_dump_files[count].glob = glob;
199 m_extra_dump_files[count].pflags = flags;
200 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
201 m_extra_dump_files[count].num = num;
202 m_extra_dump_files[count].owns_strings = take_ownership;
204 return count + TDI_end;
208 /* Return the dump_file_info for the given phase. */
210 struct dump_file_info *
211 gcc::dump_manager::
212 get_dump_file_info (int phase) const
214 if (phase < TDI_end)
215 return &dump_files[phase];
216 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
217 return NULL;
218 else
219 return m_extra_dump_files + (phase - TDI_end);
222 /* Locate the dump_file_info with swtch equal to SWTCH,
223 or return NULL if no such dump_file_info exists. */
225 struct dump_file_info *
226 gcc::dump_manager::
227 get_dump_file_info_by_switch (const char *swtch) const
229 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
230 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
231 return &m_extra_dump_files[i];
233 /* Not found. */
234 return NULL;
238 /* Return the name of the dump file for the given phase.
239 The caller is responsible for calling free on the returned
240 buffer.
241 If the dump is not enabled, returns NULL. */
243 char *
244 gcc::dump_manager::
245 get_dump_file_name (int phase) const
247 struct dump_file_info *dfi;
249 if (phase == TDI_none)
250 return NULL;
252 dfi = get_dump_file_info (phase);
254 return get_dump_file_name (dfi);
257 /* Return the name of the dump file for the given dump_file_info.
258 The caller is responsible for calling free on the returned
259 buffer.
260 If the dump is not enabled, returns NULL. */
262 char *
263 gcc::dump_manager::
264 get_dump_file_name (struct dump_file_info *dfi) const
266 char dump_id[10];
268 gcc_assert (dfi);
270 if (dfi->pstate == 0)
271 return NULL;
273 /* If available, use the command line dump filename. */
274 if (dfi->pfilename)
275 return xstrdup (dfi->pfilename);
277 if (dfi->num < 0)
278 dump_id[0] = '\0';
279 else
281 char suffix;
282 if (dfi->pflags & TDF_TREE)
283 suffix = 't';
284 else if (dfi->pflags & TDF_IPA)
285 suffix = 'i';
286 else
287 suffix = 'r';
289 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
290 dump_id[0] = '\0';
293 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
296 /* For a given DFI, open an alternate dump filename (which could also
297 be a standard stream such as stdout/stderr). If the alternate dump
298 file cannot be opened, return NULL. */
300 static FILE *
301 dump_open_alternate_stream (struct dump_file_info *dfi)
303 FILE *stream ;
304 if (!dfi->alt_filename)
305 return NULL;
307 if (dfi->alt_stream)
308 return dfi->alt_stream;
310 stream = strcmp ("stderr", dfi->alt_filename) == 0
311 ? stderr
312 : strcmp ("stdout", dfi->alt_filename) == 0
313 ? stdout
314 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
316 if (!stream)
317 error ("could not open dump file %qs: %m", dfi->alt_filename);
318 else
319 dfi->alt_state = 1;
321 return stream;
324 /* Print source location on DFILE if enabled. */
326 void
327 dump_loc (int dump_kind, FILE *dfile, source_location loc)
329 if (dump_kind)
331 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
332 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
333 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
334 else if (current_function_decl)
335 fprintf (dfile, "%s:%d:%d: note: ",
336 DECL_SOURCE_FILE (current_function_decl),
337 DECL_SOURCE_LINE (current_function_decl),
338 DECL_SOURCE_COLUMN (current_function_decl));
342 /* Dump gimple statement GS with SPC indentation spaces and
343 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
345 void
346 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc)
348 if (dump_file && (dump_kind & pflags))
349 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
351 if (alt_dump_file && (dump_kind & alt_flags))
352 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
355 /* Similar to dump_gimple_stmt, except additionally print source location. */
357 void
358 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags,
359 gimple gs, int spc)
361 if (dump_file && (dump_kind & pflags))
363 dump_loc (dump_kind, dump_file, loc);
364 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
367 if (alt_dump_file && (dump_kind & alt_flags))
369 dump_loc (dump_kind, alt_dump_file, loc);
370 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
374 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
375 DUMP_KIND is enabled. */
377 void
378 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t)
380 if (dump_file && (dump_kind & pflags))
381 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
383 if (alt_dump_file && (dump_kind & alt_flags))
384 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
388 /* Similar to dump_generic_expr, except additionally print the source
389 location. */
391 void
392 dump_generic_expr_loc (int dump_kind, source_location loc,
393 int extra_dump_flags, tree t)
395 if (dump_file && (dump_kind & pflags))
397 dump_loc (dump_kind, dump_file, loc);
398 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
401 if (alt_dump_file && (dump_kind & alt_flags))
403 dump_loc (dump_kind, alt_dump_file, loc);
404 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
408 /* Output a formatted message using FORMAT on appropriate dump streams. */
410 void
411 dump_printf (int dump_kind, const char *format, ...)
413 if (dump_file && (dump_kind & pflags))
415 va_list ap;
416 va_start (ap, format);
417 vfprintf (dump_file, format, ap);
418 va_end (ap);
421 if (alt_dump_file && (dump_kind & alt_flags))
423 va_list ap;
424 va_start (ap, format);
425 vfprintf (alt_dump_file, format, ap);
426 va_end (ap);
430 /* Similar to dump_printf, except source location is also printed. */
432 void
433 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
435 if (dump_file && (dump_kind & pflags))
437 va_list ap;
438 dump_loc (dump_kind, dump_file, loc);
439 va_start (ap, format);
440 vfprintf (dump_file, format, ap);
441 va_end (ap);
444 if (alt_dump_file && (dump_kind & alt_flags))
446 va_list ap;
447 dump_loc (dump_kind, alt_dump_file, loc);
448 va_start (ap, format);
449 vfprintf (alt_dump_file, format, ap);
450 va_end (ap);
454 /* Start a dump for PHASE. Store user-supplied dump flags in
455 *FLAG_PTR. Return the number of streams opened. Set globals
456 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
457 set dump_flags appropriately for both pass dump stream and
458 -fopt-info stream. */
461 gcc::dump_manager::
462 dump_start (int phase, int *flag_ptr)
464 int count = 0;
465 char *name;
466 struct dump_file_info *dfi;
467 FILE *stream;
468 if (phase == TDI_none || !dump_phase_enabled_p (phase))
469 return 0;
471 dfi = get_dump_file_info (phase);
472 name = get_dump_file_name (phase);
473 if (name)
475 stream = strcmp ("stderr", name) == 0
476 ? stderr
477 : strcmp ("stdout", name) == 0
478 ? stdout
479 : fopen (name, dfi->pstate < 0 ? "w" : "a");
480 if (!stream)
481 error ("could not open dump file %qs: %m", name);
482 else
484 dfi->pstate = 1;
485 count++;
487 free (name);
488 dfi->pstream = stream;
489 dump_file = dfi->pstream;
490 /* Initialize current dump flags. */
491 pflags = dfi->pflags;
494 stream = dump_open_alternate_stream (dfi);
495 if (stream)
497 dfi->alt_stream = stream;
498 count++;
499 alt_dump_file = dfi->alt_stream;
500 /* Initialize current -fopt-info flags. */
501 alt_flags = dfi->alt_flags;
504 if (flag_ptr)
505 *flag_ptr = dfi->pflags;
507 return count;
510 /* Finish a tree dump for PHASE and close associated dump streams. Also
511 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
513 void
514 gcc::dump_manager::
515 dump_finish (int phase)
517 struct dump_file_info *dfi;
519 if (phase < 0)
520 return;
521 dfi = get_dump_file_info (phase);
522 if (dfi->pstream && (!dfi->pfilename
523 || (strcmp ("stderr", dfi->pfilename) != 0
524 && strcmp ("stdout", dfi->pfilename) != 0)))
525 fclose (dfi->pstream);
527 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
528 && strcmp ("stdout", dfi->alt_filename) != 0)
529 fclose (dfi->alt_stream);
531 dfi->alt_stream = NULL;
532 dfi->pstream = NULL;
533 dump_file = NULL;
534 alt_dump_file = NULL;
535 dump_flags = TDI_none;
536 alt_flags = 0;
537 pflags = 0;
540 /* Begin a tree dump for PHASE. Stores any user supplied flag in
541 *FLAG_PTR and returns a stream to write to. If the dump is not
542 enabled, returns NULL.
543 Multiple calls will reopen and append to the dump file. */
545 FILE *
546 dump_begin (int phase, int *flag_ptr)
548 return g->get_dumps ()->dump_begin (phase, flag_ptr);
551 FILE *
552 gcc::dump_manager::
553 dump_begin (int phase, int *flag_ptr)
555 char *name;
556 struct dump_file_info *dfi;
557 FILE *stream;
559 if (phase == TDI_none || !dump_phase_enabled_p (phase))
560 return NULL;
562 name = get_dump_file_name (phase);
563 if (!name)
564 return NULL;
565 dfi = get_dump_file_info (phase);
567 stream = strcmp ("stderr", name) == 0
568 ? stderr
569 : strcmp ("stdout", name) == 0
570 ? stdout
571 : fopen (name, dfi->pstate < 0 ? "w" : "a");
573 if (!stream)
574 error ("could not open dump file %qs: %m", name);
575 else
576 dfi->pstate = 1;
577 free (name);
579 if (flag_ptr)
580 *flag_ptr = dfi->pflags;
582 /* Initialize current flags */
583 pflags = dfi->pflags;
584 return stream;
587 /* Returns nonzero if dump PHASE is enabled for at least one stream.
588 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
589 any phase. */
592 gcc::dump_manager::
593 dump_phase_enabled_p (int phase) const
595 if (phase == TDI_tree_all)
597 size_t i;
598 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
599 if (dump_files[i].pstate || dump_files[i].alt_state)
600 return 1;
601 for (i = 0; i < m_extra_dump_files_in_use; i++)
602 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
603 return 1;
604 return 0;
606 else
608 struct dump_file_info *dfi = get_dump_file_info (phase);
609 return dfi->pstate || dfi->alt_state;
613 /* Returns nonzero if tree dump PHASE has been initialized. */
616 gcc::dump_manager::
617 dump_initialized_p (int phase) const
619 struct dump_file_info *dfi = get_dump_file_info (phase);
620 return dfi->pstate > 0 || dfi->alt_state > 0;
623 /* Returns the switch name of PHASE. */
625 const char *
626 dump_flag_name (int phase)
628 return g->get_dumps ()->dump_flag_name (phase);
631 const char *
632 gcc::dump_manager::
633 dump_flag_name (int phase) const
635 struct dump_file_info *dfi = get_dump_file_info (phase);
636 return dfi->swtch;
639 /* Finish a tree dump for PHASE. STREAM is the stream created by
640 dump_begin. */
642 void
643 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
645 if (stream != stderr && stream != stdout)
646 fclose (stream);
649 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
650 enabled tree dumps. */
653 gcc::dump_manager::
654 dump_enable_all (int flags, const char *filename)
656 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
657 int n = 0;
658 size_t i;
660 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
662 if ((dump_files[i].pflags & ir_dump_type))
664 const char *old_filename = dump_files[i].pfilename;
665 dump_files[i].pstate = -1;
666 dump_files[i].pflags |= flags;
667 n++;
668 /* Override the existing filename. */
669 if (filename)
671 dump_files[i].pfilename = xstrdup (filename);
672 /* Since it is a command-line provided file, which is
673 common to all the phases, use it in append mode. */
674 dump_files[i].pstate = 1;
676 if (old_filename && filename != old_filename)
677 free (CONST_CAST (char *, old_filename));
681 for (i = 0; i < m_extra_dump_files_in_use; i++)
683 if ((m_extra_dump_files[i].pflags & ir_dump_type))
685 const char *old_filename = m_extra_dump_files[i].pfilename;
686 m_extra_dump_files[i].pstate = -1;
687 m_extra_dump_files[i].pflags |= flags;
688 n++;
689 /* Override the existing filename. */
690 if (filename)
692 m_extra_dump_files[i].pfilename = xstrdup (filename);
693 /* Since it is a command-line provided file, which is
694 common to all the phases, use it in append mode. */
695 m_extra_dump_files[i].pstate = 1;
697 if (old_filename && filename != old_filename)
698 free (CONST_CAST (char *, old_filename));
702 return n;
705 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
706 Enable dumps with FLAGS on FILENAME. Return the number of enabled
707 dumps. */
710 gcc::dump_manager::
711 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
713 int n = 0;
714 size_t i;
716 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
718 if ((dump_files[i].optgroup_flags & optgroup_flags))
720 const char *old_filename = dump_files[i].alt_filename;
721 /* Since this file is shared among different passes, it
722 should be opened in append mode. */
723 dump_files[i].alt_state = 1;
724 dump_files[i].alt_flags |= flags;
725 n++;
726 /* Override the existing filename. */
727 if (filename)
728 dump_files[i].alt_filename = xstrdup (filename);
729 if (old_filename && filename != old_filename)
730 free (CONST_CAST (char *, old_filename));
734 for (i = 0; i < m_extra_dump_files_in_use; i++)
736 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
738 const char *old_filename = m_extra_dump_files[i].alt_filename;
739 /* Since this file is shared among different passes, it
740 should be opened in append mode. */
741 m_extra_dump_files[i].alt_state = 1;
742 m_extra_dump_files[i].alt_flags |= flags;
743 n++;
744 /* Override the existing filename. */
745 if (filename)
746 m_extra_dump_files[i].alt_filename = xstrdup (filename);
747 if (old_filename && filename != old_filename)
748 free (CONST_CAST (char *, old_filename));
752 return n;
755 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
756 relevant details in the dump_files array. */
759 gcc::dump_manager::
760 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
762 const char *option_value;
763 const char *ptr;
764 int flags;
766 if (doglob && !dfi->glob)
767 return 0;
769 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
770 if (!option_value)
771 return 0;
773 if (*option_value && *option_value != '-' && *option_value != '=')
774 return 0;
776 ptr = option_value;
777 flags = 0;
779 while (*ptr)
781 const struct dump_option_value_info *option_ptr;
782 const char *end_ptr;
783 const char *eq_ptr;
784 unsigned length;
786 while (*ptr == '-')
787 ptr++;
788 end_ptr = strchr (ptr, '-');
789 eq_ptr = strchr (ptr, '=');
791 if (eq_ptr && !end_ptr)
792 end_ptr = eq_ptr;
794 if (!end_ptr)
795 end_ptr = ptr + strlen (ptr);
796 length = end_ptr - ptr;
798 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
799 if (strlen (option_ptr->name) == length
800 && !memcmp (option_ptr->name, ptr, length))
802 flags |= option_ptr->value;
803 goto found;
806 if (*ptr == '=')
808 /* Interpret rest of the argument as a dump filename. This
809 filename overrides other command line filenames. */
810 if (dfi->pfilename)
811 free (CONST_CAST (char *, dfi->pfilename));
812 dfi->pfilename = xstrdup (ptr + 1);
813 break;
815 else
816 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
817 length, ptr, dfi->swtch);
818 found:;
819 ptr = end_ptr;
822 dfi->pstate = -1;
823 dfi->pflags |= flags;
825 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
826 known dumps. */
827 if (dfi->suffix == NULL)
828 dump_enable_all (dfi->pflags, dfi->pfilename);
830 return 1;
834 gcc::dump_manager::
835 dump_switch_p (const char *arg)
837 size_t i;
838 int any = 0;
840 for (i = TDI_none + 1; i != TDI_end; i++)
841 any |= dump_switch_p_1 (arg, &dump_files[i], false);
843 /* Don't glob if we got a hit already */
844 if (!any)
845 for (i = TDI_none + 1; i != TDI_end; i++)
846 any |= dump_switch_p_1 (arg, &dump_files[i], true);
848 for (i = 0; i < m_extra_dump_files_in_use; i++)
849 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
851 if (!any)
852 for (i = 0; i < m_extra_dump_files_in_use; i++)
853 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
856 return any;
859 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
860 and filename. Return non-zero if it is a recognized switch. */
862 static int
863 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags,
864 char **filename)
866 const char *option_value;
867 const char *ptr;
869 option_value = arg;
870 ptr = option_value;
872 *filename = NULL;
873 *flags = 0;
874 *optgroup_flags = 0;
876 if (!ptr)
877 return 1; /* Handle '-fopt-info' without any additional options. */
879 while (*ptr)
881 const struct dump_option_value_info *option_ptr;
882 const char *end_ptr;
883 const char *eq_ptr;
884 unsigned length;
886 while (*ptr == '-')
887 ptr++;
888 end_ptr = strchr (ptr, '-');
889 eq_ptr = strchr (ptr, '=');
891 if (eq_ptr && !end_ptr)
892 end_ptr = eq_ptr;
894 if (!end_ptr)
895 end_ptr = ptr + strlen (ptr);
896 length = end_ptr - ptr;
898 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
899 option_ptr++)
900 if (strlen (option_ptr->name) == length
901 && !memcmp (option_ptr->name, ptr, length))
903 *flags |= option_ptr->value;
904 goto found;
907 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
908 if (strlen (option_ptr->name) == length
909 && !memcmp (option_ptr->name, ptr, length))
911 *optgroup_flags |= option_ptr->value;
912 goto found;
915 if (*ptr == '=')
917 /* Interpret rest of the argument as a dump filename. This
918 filename overrides other command line filenames. */
919 *filename = xstrdup (ptr + 1);
920 break;
922 else
924 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
925 length, ptr, arg);
926 return 0;
928 found:;
929 ptr = end_ptr;
932 return 1;
935 /* Return non-zero if ARG is a recognized switch for
936 -fopt-info. Return zero otherwise. */
939 opt_info_switch_p (const char *arg)
941 int flags;
942 int optgroup_flags;
943 char *filename;
944 static char *file_seen = NULL;
945 gcc::dump_manager *dumps = g->get_dumps ();
947 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
948 return 0;
950 if (!filename)
951 filename = xstrdup ("stderr");
953 /* Bail out if a different filename has been specified. */
954 if (file_seen && strcmp (file_seen, filename))
956 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
957 arg);
958 return 1;
961 file_seen = xstrdup (filename);
962 if (!flags)
963 flags = MSG_OPTIMIZED_LOCATIONS;
964 if (!optgroup_flags)
965 optgroup_flags = OPTGROUP_ALL;
967 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
970 /* Print basic block on the dump streams. */
972 void
973 dump_basic_block (int dump_kind, basic_block bb, int indent)
975 if (dump_file && (dump_kind & pflags))
976 dump_bb (dump_file, bb, indent, TDF_DETAILS);
977 if (alt_dump_file && (dump_kind & alt_flags))
978 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
981 /* Print information from the combine pass on dump_file. */
983 void
984 print_combine_total_stats (void)
986 if (dump_file)
987 dump_combine_total_stats (dump_file);
990 /* Enable RTL dump for all the RTL passes. */
992 bool
993 enable_rtl_dump_file (void)
995 gcc::dump_manager *dumps = g->get_dumps ();
996 int num_enabled =
997 dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
998 return num_enabled > 0;