re PR c++/68754 (Explicitly defaulted constexpr assignment operator fails to compile)
[official-gcc.git] / gcc / dumpfile.c
blobb8bda3c918319c5449c068c4db82c270a6d1bddc
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 dump_flags_t pflags; /* current dump_flags */
37 static dump_flags_t alt_flags; /* current opt_info flags */
39 static void dump_loc (dump_flags_t, 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 dump_flags_t dump_flags;
50 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
51 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, 0, 0, 0, 0, 0, num, \
52 false, false}
54 /* Table of tree dump switches. This must be consistent with the
55 TREE_DUMP_INDEX enumeration in dumpfile.h. */
56 static struct dump_file_info dump_files[TDI_end] =
58 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
59 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
60 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
61 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
62 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 3),
63 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 4),
64 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 5),
65 #define FIRST_AUTO_NUMBERED_DUMP 3
67 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
68 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
69 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
70 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
73 /* Define a name->number mapping for a dump flag value. */
74 struct dump_option_value_info
76 const char *const name; /* the name of the value */
77 const dump_flags_t value; /* the value of the name */
80 /* Table of dump options. This must be consistent with the TDF_* flags
81 in dumpfile.h and opt_info_options below. */
82 static const struct dump_option_value_info dump_options[] =
84 {"address", TDF_ADDRESS},
85 {"asmname", TDF_ASMNAME},
86 {"slim", TDF_SLIM},
87 {"raw", TDF_RAW},
88 {"graph", TDF_GRAPH},
89 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
90 | MSG_MISSED_OPTIMIZATION
91 | MSG_NOTE)},
92 {"cselib", TDF_CSELIB},
93 {"stats", TDF_STATS},
94 {"blocks", TDF_BLOCKS},
95 {"vops", TDF_VOPS},
96 {"lineno", TDF_LINENO},
97 {"uid", TDF_UID},
98 {"stmtaddr", TDF_STMTADDR},
99 {"memsyms", TDF_MEMSYMS},
100 {"eh", TDF_EH},
101 {"alias", TDF_ALIAS},
102 {"nouid", TDF_NOUID},
103 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
104 {"scev", TDF_SCEV},
105 {"gimple", TDF_GIMPLE},
106 {"folding", TDF_FOLDING},
107 {"optimized", MSG_OPTIMIZED_LOCATIONS},
108 {"missed", MSG_MISSED_OPTIMIZATION},
109 {"note", MSG_NOTE},
110 {"optall", MSG_ALL},
111 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH | TDF_STMTADDR
112 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV
113 | TDF_GIMPLE)},
114 {NULL, 0}
117 /* A subset of the dump_options table which is used for -fopt-info
118 types. This must be consistent with the MSG_* flags in dumpfile.h.
120 static const struct dump_option_value_info optinfo_verbosity_options[] =
122 {"optimized", MSG_OPTIMIZED_LOCATIONS},
123 {"missed", MSG_MISSED_OPTIMIZATION},
124 {"note", MSG_NOTE},
125 {"all", MSG_ALL},
126 {NULL, 0}
129 /* Flags used for -fopt-info groups. */
130 static const struct dump_option_value_info optgroup_options[] =
132 {"ipa", OPTGROUP_IPA},
133 {"loop", OPTGROUP_LOOP},
134 {"inline", OPTGROUP_INLINE},
135 {"omp", OPTGROUP_OMP},
136 {"vec", OPTGROUP_VEC},
137 {"optall", OPTGROUP_ALL},
138 {NULL, 0}
141 gcc::dump_manager::dump_manager ():
142 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
143 m_extra_dump_files (NULL),
144 m_extra_dump_files_in_use (0),
145 m_extra_dump_files_alloced (0)
149 gcc::dump_manager::~dump_manager ()
151 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
153 dump_file_info *dfi = &m_extra_dump_files[i];
154 /* suffix, swtch, glob are statically allocated for the entries
155 in dump_files, and for statistics, but are dynamically allocated
156 for those for passes. */
157 if (dfi->owns_strings)
159 XDELETEVEC (const_cast <char *> (dfi->suffix));
160 XDELETEVEC (const_cast <char *> (dfi->swtch));
161 XDELETEVEC (const_cast <char *> (dfi->glob));
163 /* These, if non-NULL, are always dynamically allocated. */
164 XDELETEVEC (const_cast <char *> (dfi->pfilename));
165 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
167 XDELETEVEC (m_extra_dump_files);
170 unsigned int
171 gcc::dump_manager::
172 dump_register (const char *suffix, const char *swtch, const char *glob,
173 dump_kind dkind, int optgroup_flags, bool take_ownership)
175 int num = m_next_dump++;
177 size_t count = m_extra_dump_files_in_use++;
179 if (count >= m_extra_dump_files_alloced)
181 if (m_extra_dump_files_alloced == 0)
182 m_extra_dump_files_alloced = 32;
183 else
184 m_extra_dump_files_alloced *= 2;
185 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
186 m_extra_dump_files,
187 m_extra_dump_files_alloced);
190 memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
191 m_extra_dump_files[count].suffix = suffix;
192 m_extra_dump_files[count].swtch = swtch;
193 m_extra_dump_files[count].glob = glob;
194 m_extra_dump_files[count].dkind = dkind;
195 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
196 m_extra_dump_files[count].num = num;
197 m_extra_dump_files[count].owns_strings = take_ownership;
199 return count + TDI_end;
203 /* Return the dump_file_info for the given phase. */
205 struct dump_file_info *
206 gcc::dump_manager::
207 get_dump_file_info (int phase) const
209 if (phase < TDI_end)
210 return &dump_files[phase];
211 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
212 return NULL;
213 else
214 return m_extra_dump_files + (phase - TDI_end);
217 /* Locate the dump_file_info with swtch equal to SWTCH,
218 or return NULL if no such dump_file_info exists. */
220 struct dump_file_info *
221 gcc::dump_manager::
222 get_dump_file_info_by_switch (const char *swtch) const
224 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
225 if (0 == strcmp (m_extra_dump_files[i].swtch, swtch))
226 return &m_extra_dump_files[i];
228 /* Not found. */
229 return NULL;
233 /* Return the name of the dump file for the given phase.
234 The caller is responsible for calling free on the returned
235 buffer.
236 If the dump is not enabled, returns NULL. */
238 char *
239 gcc::dump_manager::
240 get_dump_file_name (int phase) const
242 struct dump_file_info *dfi;
244 if (phase == TDI_none)
245 return NULL;
247 dfi = get_dump_file_info (phase);
249 return get_dump_file_name (dfi);
252 /* Return the name of the dump file for the given dump_file_info.
253 The caller is responsible for calling free on the returned
254 buffer.
255 If the dump is not enabled, returns NULL. */
257 char *
258 gcc::dump_manager::
259 get_dump_file_name (struct dump_file_info *dfi) const
261 char dump_id[10];
263 gcc_assert (dfi);
265 if (dfi->pstate == 0)
266 return NULL;
268 /* If available, use the command line dump filename. */
269 if (dfi->pfilename)
270 return xstrdup (dfi->pfilename);
272 if (dfi->num < 0)
273 dump_id[0] = '\0';
274 else
276 /* (null), LANG, TREE, RTL, IPA. */
277 char suffix = " ltri"[dfi->dkind];
279 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
280 dump_id[0] = '\0';
283 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
286 /* For a given DFI, open an alternate dump filename (which could also
287 be a standard stream such as stdout/stderr). If the alternate dump
288 file cannot be opened, return NULL. */
290 static FILE *
291 dump_open_alternate_stream (struct dump_file_info *dfi)
293 FILE *stream ;
294 if (!dfi->alt_filename)
295 return NULL;
297 if (dfi->alt_stream)
298 return dfi->alt_stream;
300 stream = strcmp ("stderr", dfi->alt_filename) == 0
301 ? stderr
302 : strcmp ("stdout", dfi->alt_filename) == 0
303 ? stdout
304 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
306 if (!stream)
307 error ("could not open dump file %qs: %m", dfi->alt_filename);
308 else
309 dfi->alt_state = 1;
311 return stream;
314 /* Print source location on DFILE if enabled. */
316 void
317 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
319 if (dump_kind)
321 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
322 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
323 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
324 else if (current_function_decl)
325 fprintf (dfile, "%s:%d:%d: note: ",
326 DECL_SOURCE_FILE (current_function_decl),
327 DECL_SOURCE_LINE (current_function_decl),
328 DECL_SOURCE_COLUMN (current_function_decl));
332 /* Dump gimple statement GS with SPC indentation spaces and
333 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
335 void
336 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
337 gimple *gs, int spc)
339 if (dump_file && (dump_kind & pflags))
340 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
342 if (alt_dump_file && (dump_kind & alt_flags))
343 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
346 /* Similar to dump_gimple_stmt, except additionally print source location. */
348 void
349 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
350 dump_flags_t extra_dump_flags, gimple *gs, int spc)
352 if (dump_file && (dump_kind & pflags))
354 dump_loc (dump_kind, dump_file, loc);
355 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
358 if (alt_dump_file && (dump_kind & alt_flags))
360 dump_loc (dump_kind, alt_dump_file, loc);
361 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
365 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
366 DUMP_KIND is enabled. */
368 void
369 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
370 tree t)
372 if (dump_file && (dump_kind & pflags))
373 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
375 if (alt_dump_file && (dump_kind & alt_flags))
376 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
380 /* Similar to dump_generic_expr, except additionally print the source
381 location. */
383 void
384 dump_generic_expr_loc (int dump_kind, source_location loc,
385 dump_flags_t extra_dump_flags, tree t)
387 if (dump_file && (dump_kind & pflags))
389 dump_loc (dump_kind, dump_file, loc);
390 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
393 if (alt_dump_file && (dump_kind & alt_flags))
395 dump_loc (dump_kind, alt_dump_file, loc);
396 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
400 /* Output a formatted message using FORMAT on appropriate dump streams. */
402 void
403 dump_printf (dump_flags_t dump_kind, const char *format, ...)
405 if (dump_file && (dump_kind & pflags))
407 va_list ap;
408 va_start (ap, format);
409 vfprintf (dump_file, format, ap);
410 va_end (ap);
413 if (alt_dump_file && (dump_kind & alt_flags))
415 va_list ap;
416 va_start (ap, format);
417 vfprintf (alt_dump_file, format, ap);
418 va_end (ap);
422 /* Similar to dump_printf, except source location is also printed. */
424 void
425 dump_printf_loc (dump_flags_t dump_kind, source_location loc,
426 const char *format, ...)
428 if (dump_file && (dump_kind & pflags))
430 va_list ap;
431 dump_loc (dump_kind, dump_file, loc);
432 va_start (ap, format);
433 vfprintf (dump_file, format, ap);
434 va_end (ap);
437 if (alt_dump_file && (dump_kind & alt_flags))
439 va_list ap;
440 dump_loc (dump_kind, alt_dump_file, loc);
441 va_start (ap, format);
442 vfprintf (alt_dump_file, format, ap);
443 va_end (ap);
447 /* Start a dump for PHASE. Store user-supplied dump flags in
448 *FLAG_PTR. Return the number of streams opened. Set globals
449 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
450 set dump_flags appropriately for both pass dump stream and
451 -fopt-info stream. */
454 gcc::dump_manager::
455 dump_start (int phase, dump_flags_t *flag_ptr)
457 int count = 0;
458 char *name;
459 struct dump_file_info *dfi;
460 FILE *stream;
461 if (phase == TDI_none || !dump_phase_enabled_p (phase))
462 return 0;
464 dfi = get_dump_file_info (phase);
465 name = get_dump_file_name (phase);
466 if (name)
468 stream = strcmp ("stderr", name) == 0
469 ? stderr
470 : strcmp ("stdout", name) == 0
471 ? stdout
472 : fopen (name, dfi->pstate < 0 ? "w" : "a");
473 if (!stream)
474 error ("could not open dump file %qs: %m", name);
475 else
477 dfi->pstate = 1;
478 count++;
480 free (name);
481 dfi->pstream = stream;
482 dump_file = dfi->pstream;
483 /* Initialize current dump flags. */
484 pflags = dfi->pflags;
487 stream = dump_open_alternate_stream (dfi);
488 if (stream)
490 dfi->alt_stream = stream;
491 count++;
492 alt_dump_file = dfi->alt_stream;
493 /* Initialize current -fopt-info flags. */
494 alt_flags = dfi->alt_flags;
497 if (flag_ptr)
498 *flag_ptr = dfi->pflags;
500 return count;
503 /* Finish a tree dump for PHASE and close associated dump streams. Also
504 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
506 void
507 gcc::dump_manager::
508 dump_finish (int phase)
510 struct dump_file_info *dfi;
512 if (phase < 0)
513 return;
514 dfi = get_dump_file_info (phase);
515 if (dfi->pstream && (!dfi->pfilename
516 || (strcmp ("stderr", dfi->pfilename) != 0
517 && strcmp ("stdout", dfi->pfilename) != 0)))
518 fclose (dfi->pstream);
520 if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
521 && strcmp ("stdout", dfi->alt_filename) != 0)
522 fclose (dfi->alt_stream);
524 dfi->alt_stream = NULL;
525 dfi->pstream = NULL;
526 dump_file = NULL;
527 alt_dump_file = NULL;
528 dump_flags = TDI_none;
529 alt_flags = 0;
530 pflags = 0;
533 /* Begin a tree dump for PHASE. Stores any user supplied flag in
534 *FLAG_PTR and returns a stream to write to. If the dump is not
535 enabled, returns NULL.
536 Multiple calls will reopen and append to the dump file. */
538 FILE *
539 dump_begin (int phase, dump_flags_t *flag_ptr)
541 return g->get_dumps ()->dump_begin (phase, flag_ptr);
544 FILE *
545 gcc::dump_manager::
546 dump_begin (int phase, dump_flags_t *flag_ptr)
548 char *name;
549 struct dump_file_info *dfi;
550 FILE *stream;
552 if (phase == TDI_none || !dump_phase_enabled_p (phase))
553 return NULL;
555 name = get_dump_file_name (phase);
556 if (!name)
557 return NULL;
558 dfi = get_dump_file_info (phase);
560 stream = strcmp ("stderr", name) == 0
561 ? stderr
562 : strcmp ("stdout", name) == 0
563 ? stdout
564 : fopen (name, dfi->pstate < 0 ? "w" : "a");
566 if (!stream)
567 error ("could not open dump file %qs: %m", name);
568 else
569 dfi->pstate = 1;
570 free (name);
572 if (flag_ptr)
573 *flag_ptr = dfi->pflags;
575 /* Initialize current flags */
576 pflags = dfi->pflags;
577 return stream;
580 /* Returns nonzero if dump PHASE is enabled for at least one stream.
581 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
582 any phase. */
585 gcc::dump_manager::
586 dump_phase_enabled_p (int phase) const
588 if (phase == TDI_tree_all)
590 size_t i;
591 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
592 if (dump_files[i].pstate || dump_files[i].alt_state)
593 return 1;
594 for (i = 0; i < m_extra_dump_files_in_use; i++)
595 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
596 return 1;
597 return 0;
599 else
601 struct dump_file_info *dfi = get_dump_file_info (phase);
602 return dfi->pstate || dfi->alt_state;
606 /* Returns nonzero if tree dump PHASE has been initialized. */
609 gcc::dump_manager::
610 dump_initialized_p (int phase) const
612 struct dump_file_info *dfi = get_dump_file_info (phase);
613 return dfi->pstate > 0 || dfi->alt_state > 0;
616 /* Returns the switch name of PHASE. */
618 const char *
619 dump_flag_name (int phase)
621 return g->get_dumps ()->dump_flag_name (phase);
624 const char *
625 gcc::dump_manager::
626 dump_flag_name (int phase) const
628 struct dump_file_info *dfi = get_dump_file_info (phase);
629 return dfi->swtch;
632 /* Finish a tree dump for PHASE. STREAM is the stream created by
633 dump_begin. */
635 void
636 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
638 if (stream != stderr && stream != stdout)
639 fclose (stream);
642 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
643 enabled tree dumps. */
646 gcc::dump_manager::
647 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
649 int n = 0;
650 size_t i;
652 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
654 if ((dump_files[i].dkind == dkind))
656 const char *old_filename = dump_files[i].pfilename;
657 dump_files[i].pstate = -1;
658 dump_files[i].pflags |= flags;
659 n++;
660 /* Override the existing filename. */
661 if (filename)
663 dump_files[i].pfilename = xstrdup (filename);
664 /* Since it is a command-line provided file, which is
665 common to all the phases, use it in append mode. */
666 dump_files[i].pstate = 1;
668 if (old_filename && filename != old_filename)
669 free (CONST_CAST (char *, old_filename));
673 for (i = 0; i < m_extra_dump_files_in_use; i++)
675 if ((m_extra_dump_files[i].dkind == dkind))
677 const char *old_filename = m_extra_dump_files[i].pfilename;
678 m_extra_dump_files[i].pstate = -1;
679 m_extra_dump_files[i].pflags |= flags;
680 n++;
681 /* Override the existing filename. */
682 if (filename)
684 m_extra_dump_files[i].pfilename = xstrdup (filename);
685 /* Since it is a command-line provided file, which is
686 common to all the phases, use it in append mode. */
687 m_extra_dump_files[i].pstate = 1;
689 if (old_filename && filename != old_filename)
690 free (CONST_CAST (char *, old_filename));
694 return n;
697 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
698 Enable dumps with FLAGS on FILENAME. Return the number of enabled
699 dumps. */
702 gcc::dump_manager::
703 opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
704 const char *filename)
706 int n = 0;
707 size_t i;
709 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
711 if ((dump_files[i].optgroup_flags & optgroup_flags))
713 const char *old_filename = dump_files[i].alt_filename;
714 /* Since this file is shared among different passes, it
715 should be opened in append mode. */
716 dump_files[i].alt_state = 1;
717 dump_files[i].alt_flags |= flags;
718 n++;
719 /* Override the existing filename. */
720 if (filename)
721 dump_files[i].alt_filename = xstrdup (filename);
722 if (old_filename && filename != old_filename)
723 free (CONST_CAST (char *, old_filename));
727 for (i = 0; i < m_extra_dump_files_in_use; i++)
729 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
731 const char *old_filename = m_extra_dump_files[i].alt_filename;
732 /* Since this file is shared among different passes, it
733 should be opened in append mode. */
734 m_extra_dump_files[i].alt_state = 1;
735 m_extra_dump_files[i].alt_flags |= flags;
736 n++;
737 /* Override the existing filename. */
738 if (filename)
739 m_extra_dump_files[i].alt_filename = xstrdup (filename);
740 if (old_filename && filename != old_filename)
741 free (CONST_CAST (char *, old_filename));
745 return n;
748 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
749 relevant details in the dump_files array. */
752 gcc::dump_manager::
753 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
755 const char *option_value;
756 const char *ptr;
757 dump_flags_t flags;
759 if (doglob && !dfi->glob)
760 return 0;
762 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
763 if (!option_value)
764 return 0;
766 if (*option_value && *option_value != '-' && *option_value != '=')
767 return 0;
769 ptr = option_value;
770 flags = 0;
772 while (*ptr)
774 const struct dump_option_value_info *option_ptr;
775 const char *end_ptr;
776 const char *eq_ptr;
777 unsigned length;
779 while (*ptr == '-')
780 ptr++;
781 end_ptr = strchr (ptr, '-');
782 eq_ptr = strchr (ptr, '=');
784 if (eq_ptr && !end_ptr)
785 end_ptr = eq_ptr;
787 if (!end_ptr)
788 end_ptr = ptr + strlen (ptr);
789 length = end_ptr - ptr;
791 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
792 if (strlen (option_ptr->name) == length
793 && !memcmp (option_ptr->name, ptr, length))
795 flags |= option_ptr->value;
796 goto found;
799 if (*ptr == '=')
801 /* Interpret rest of the argument as a dump filename. This
802 filename overrides other command line filenames. */
803 if (dfi->pfilename)
804 free (CONST_CAST (char *, dfi->pfilename));
805 dfi->pfilename = xstrdup (ptr + 1);
806 break;
808 else
809 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
810 length, ptr, dfi->swtch);
811 found:;
812 ptr = end_ptr;
815 dfi->pstate = -1;
816 dfi->pflags |= flags;
818 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
819 known dumps. */
820 if (dfi->suffix == NULL)
821 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
823 return 1;
827 gcc::dump_manager::
828 dump_switch_p (const char *arg)
830 size_t i;
831 int any = 0;
833 for (i = TDI_none + 1; i != TDI_end; i++)
834 any |= dump_switch_p_1 (arg, &dump_files[i], false);
836 /* Don't glob if we got a hit already */
837 if (!any)
838 for (i = TDI_none + 1; i != TDI_end; i++)
839 any |= dump_switch_p_1 (arg, &dump_files[i], true);
841 for (i = 0; i < m_extra_dump_files_in_use; i++)
842 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
844 if (!any)
845 for (i = 0; i < m_extra_dump_files_in_use; i++)
846 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
849 return any;
852 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
853 and filename. Return non-zero if it is a recognized switch. */
855 static int
856 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
857 char **filename)
859 const char *option_value;
860 const char *ptr;
862 option_value = arg;
863 ptr = option_value;
865 *filename = NULL;
866 *flags = 0;
867 *optgroup_flags = 0;
869 if (!ptr)
870 return 1; /* Handle '-fopt-info' without any additional options. */
872 while (*ptr)
874 const struct dump_option_value_info *option_ptr;
875 const char *end_ptr;
876 const char *eq_ptr;
877 unsigned length;
879 while (*ptr == '-')
880 ptr++;
881 end_ptr = strchr (ptr, '-');
882 eq_ptr = strchr (ptr, '=');
884 if (eq_ptr && !end_ptr)
885 end_ptr = eq_ptr;
887 if (!end_ptr)
888 end_ptr = ptr + strlen (ptr);
889 length = end_ptr - ptr;
891 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
892 option_ptr++)
893 if (strlen (option_ptr->name) == length
894 && !memcmp (option_ptr->name, ptr, length))
896 *flags |= option_ptr->value;
897 goto found;
900 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
901 if (strlen (option_ptr->name) == length
902 && !memcmp (option_ptr->name, ptr, length))
904 *optgroup_flags |= option_ptr->value;
905 goto found;
908 if (*ptr == '=')
910 /* Interpret rest of the argument as a dump filename. This
911 filename overrides other command line filenames. */
912 *filename = xstrdup (ptr + 1);
913 break;
915 else
917 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
918 length, ptr, arg);
919 return 0;
921 found:;
922 ptr = end_ptr;
925 return 1;
928 /* Return non-zero if ARG is a recognized switch for
929 -fopt-info. Return zero otherwise. */
932 opt_info_switch_p (const char *arg)
934 dump_flags_t flags;
935 int optgroup_flags;
936 char *filename;
937 static char *file_seen = NULL;
938 gcc::dump_manager *dumps = g->get_dumps ();
940 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
941 return 0;
943 if (!filename)
944 filename = xstrdup ("stderr");
946 /* Bail out if a different filename has been specified. */
947 if (file_seen && strcmp (file_seen, filename))
949 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
950 arg);
951 return 1;
954 file_seen = xstrdup (filename);
955 if (!flags)
956 flags = MSG_OPTIMIZED_LOCATIONS;
957 if (!optgroup_flags)
958 optgroup_flags = OPTGROUP_ALL;
960 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
963 /* Print basic block on the dump streams. */
965 void
966 dump_basic_block (int dump_kind, basic_block bb, int indent)
968 if (dump_file && (dump_kind & pflags))
969 dump_bb (dump_file, bb, indent, TDF_DETAILS);
970 if (alt_dump_file && (dump_kind & alt_flags))
971 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
974 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
976 void
977 dump_function (int phase, tree fn)
979 FILE *stream;
980 dump_flags_t flags;
982 stream = dump_begin (phase, &flags);
983 if (stream)
985 dump_function_to_file (fn, stream, flags);
986 dump_end (phase, stream);
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 (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1007 NULL);
1008 return num_enabled > 0;