dumpfile cleanup
[official-gcc.git] / gcc / dumpfile.c
blob75e2a7d792f57b9dc5a0ffe34c994a0939643b73
1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2018 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 "profile-count.h"
30 #include "tree-cfg.h"
31 #include "langhooks.h"
33 /* If non-NULL, return one past-the-end of the matching SUBPART of
34 the WHOLE string. */
35 #define skip_leading_substring(whole, part) \
36 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
38 static dump_flags_t pflags; /* current dump_flags */
39 static dump_flags_t alt_flags; /* current opt_info flags */
41 static void dump_loc (dump_flags_t, FILE *, source_location);
42 static FILE *dump_open_alternate_stream (struct dump_file_info *);
44 /* These are currently used for communicating between passes.
45 However, instead of accessing them directly, the passes can use
46 dump_printf () for dumps. */
47 FILE *dump_file = NULL;
48 FILE *alt_dump_file = NULL;
49 const char *dump_file_name;
50 dump_flags_t dump_flags;
52 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
53 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, 0, 0, 0, 0, 0, num, \
54 false, false}
56 /* Table of tree dump switches. This must be consistent with the
57 TREE_DUMP_INDEX enumeration in dumpfile.h. */
58 static struct dump_file_info dump_files[TDI_end] =
60 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
61 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
62 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
63 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
64 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
65 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
66 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
67 #define FIRST_AUTO_NUMBERED_DUMP 1
68 #define FIRST_ME_AUTO_NUMBERED_DUMP 3
70 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
71 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
72 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
73 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
76 /* Define a name->number mapping for a dump flag value. */
77 struct dump_option_value_info
79 const char *const name; /* the name of the value */
80 const dump_flags_t value; /* the value of the name */
83 /* Table of dump options. This must be consistent with the TDF_* flags
84 in dumpfile.h and opt_info_options below. */
85 static const struct dump_option_value_info dump_options[] =
87 {"address", TDF_ADDRESS},
88 {"asmname", TDF_ASMNAME},
89 {"slim", TDF_SLIM},
90 {"raw", TDF_RAW},
91 {"graph", TDF_GRAPH},
92 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
93 | MSG_MISSED_OPTIMIZATION
94 | MSG_NOTE)},
95 {"cselib", TDF_CSELIB},
96 {"stats", TDF_STATS},
97 {"blocks", TDF_BLOCKS},
98 {"vops", TDF_VOPS},
99 {"lineno", TDF_LINENO},
100 {"uid", TDF_UID},
101 {"stmtaddr", TDF_STMTADDR},
102 {"memsyms", TDF_MEMSYMS},
103 {"eh", TDF_EH},
104 {"alias", TDF_ALIAS},
105 {"nouid", TDF_NOUID},
106 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
107 {"scev", TDF_SCEV},
108 {"gimple", TDF_GIMPLE},
109 {"folding", TDF_FOLDING},
110 {"optimized", MSG_OPTIMIZED_LOCATIONS},
111 {"missed", MSG_MISSED_OPTIMIZATION},
112 {"note", MSG_NOTE},
113 {"optall", MSG_ALL},
114 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
115 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
116 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
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 {"omp", OPTGROUP_OMP},
139 {"vec", OPTGROUP_VEC},
140 {"optall", OPTGROUP_ALL},
141 {NULL, 0}
144 gcc::dump_manager::dump_manager ():
145 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
146 m_extra_dump_files (NULL),
147 m_extra_dump_files_in_use (0),
148 m_extra_dump_files_alloced (0)
152 gcc::dump_manager::~dump_manager ()
154 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
156 dump_file_info *dfi = &m_extra_dump_files[i];
157 /* suffix, swtch, glob are statically allocated for the entries
158 in dump_files, and for statistics, but are dynamically allocated
159 for those for passes. */
160 if (dfi->owns_strings)
162 XDELETEVEC (const_cast <char *> (dfi->suffix));
163 XDELETEVEC (const_cast <char *> (dfi->swtch));
164 XDELETEVEC (const_cast <char *> (dfi->glob));
166 /* These, if non-NULL, are always dynamically allocated. */
167 XDELETEVEC (const_cast <char *> (dfi->pfilename));
168 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
170 XDELETEVEC (m_extra_dump_files);
173 unsigned int
174 gcc::dump_manager::
175 dump_register (const char *suffix, const char *swtch, const char *glob,
176 dump_kind dkind, int optgroup_flags, 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 = 512;
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);
192 /* Construct a new object in the space allocated above. */
193 new (m_extra_dump_files + count) dump_file_info ();
195 else
197 /* Zero out the already constructed object. */
198 m_extra_dump_files[count] = dump_file_info ();
201 m_extra_dump_files[count].suffix = suffix;
202 m_extra_dump_files[count].swtch = swtch;
203 m_extra_dump_files[count].glob = glob;
204 m_extra_dump_files[count].dkind = dkind;
205 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
206 m_extra_dump_files[count].num = num;
207 m_extra_dump_files[count].owns_strings = take_ownership;
209 return count + TDI_end;
213 /* Allow languages and middle-end to register their dumps before the
214 optimization passes. */
216 void
217 gcc::dump_manager::
218 register_dumps ()
220 lang_hooks.register_dumps (this);
221 /* If this assert fails, some FE registered more than
222 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
223 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
224 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
225 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
226 dump_files[TDI_original].num = m_next_dump++;
227 dump_files[TDI_gimple].num = m_next_dump++;
228 dump_files[TDI_nested].num = m_next_dump++;
232 /* Return the dump_file_info for the given phase. */
234 struct dump_file_info *
235 gcc::dump_manager::
236 get_dump_file_info (int phase) const
238 if (phase < TDI_end)
239 return &dump_files[phase];
240 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
241 return NULL;
242 else
243 return m_extra_dump_files + (phase - TDI_end);
246 /* Locate the dump_file_info with swtch equal to SWTCH,
247 or return NULL if no such dump_file_info exists. */
249 struct dump_file_info *
250 gcc::dump_manager::
251 get_dump_file_info_by_switch (const char *swtch) const
253 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
254 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
255 return &m_extra_dump_files[i];
257 /* Not found. */
258 return NULL;
262 /* Return the name of the dump file for the given phase.
263 The caller is responsible for calling free on the returned
264 buffer.
265 If the dump is not enabled, returns NULL. */
267 char *
268 gcc::dump_manager::
269 get_dump_file_name (int phase) const
271 struct dump_file_info *dfi;
273 if (phase == TDI_none)
274 return NULL;
276 dfi = get_dump_file_info (phase);
278 return get_dump_file_name (dfi);
281 /* Return the name of the dump file for the given dump_file_info.
282 The caller is responsible for calling free on the returned
283 buffer.
284 If the dump is not enabled, returns NULL. */
286 char *
287 gcc::dump_manager::
288 get_dump_file_name (struct dump_file_info *dfi) const
290 char dump_id[10];
292 gcc_assert (dfi);
294 if (dfi->pstate == 0)
295 return NULL;
297 /* If available, use the command line dump filename. */
298 if (dfi->pfilename)
299 return xstrdup (dfi->pfilename);
301 if (dfi->num < 0)
302 dump_id[0] = '\0';
303 else
305 /* (null), LANG, TREE, RTL, IPA. */
306 char suffix = " ltri"[dfi->dkind];
308 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
309 dump_id[0] = '\0';
312 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
315 /* Open a dump file called FILENAME. Some filenames are special and
316 refer to the standard streams. TRUNC indicates whether this is the
317 first open (so the file should be truncated, rather than appended).
318 An error message is emitted in the event of failure. */
320 static FILE *
321 dump_open (const char *filename, bool trunc)
323 if (strcmp ("stderr", filename) == 0)
324 return stderr;
326 if (strcmp ("stdout", filename) == 0)
327 return stdout;
329 FILE *stream = fopen (filename, trunc ? "w" : "a");
331 if (!stream)
332 error ("could not open dump file %qs: %m", filename);
333 return stream;
336 /* For a given DFI, open an alternate dump filename (which could also
337 be a standard stream such as stdout/stderr). If the alternate dump
338 file cannot be opened, return NULL. */
340 static FILE *
341 dump_open_alternate_stream (struct dump_file_info *dfi)
343 if (!dfi->alt_filename)
344 return NULL;
346 if (dfi->alt_stream)
347 return dfi->alt_stream;
349 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
351 if (stream)
352 dfi->alt_state = 1;
354 return stream;
357 /* Print source location on DFILE if enabled. */
359 void
360 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
362 if (dump_kind)
364 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
365 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
366 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
367 else if (current_function_decl)
368 fprintf (dfile, "%s:%d:%d: note: ",
369 DECL_SOURCE_FILE (current_function_decl),
370 DECL_SOURCE_LINE (current_function_decl),
371 DECL_SOURCE_COLUMN (current_function_decl));
375 /* Dump gimple statement GS with SPC indentation spaces and
376 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
378 void
379 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
380 gimple *gs, int spc)
382 if (dump_file && (dump_kind & pflags))
383 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
385 if (alt_dump_file && (dump_kind & alt_flags))
386 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
389 /* Similar to dump_gimple_stmt, except additionally print source location. */
391 void
392 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
393 dump_flags_t extra_dump_flags, gimple *gs, int spc)
395 if (dump_file && (dump_kind & pflags))
397 dump_loc (dump_kind, dump_file, loc);
398 print_gimple_stmt (dump_file, gs, spc, 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_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
408 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
409 DUMP_KIND is enabled. */
411 void
412 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
413 tree t)
415 if (dump_file && (dump_kind & pflags))
416 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
418 if (alt_dump_file && (dump_kind & alt_flags))
419 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
423 /* Similar to dump_generic_expr, except additionally print the source
424 location. */
426 void
427 dump_generic_expr_loc (int dump_kind, source_location loc,
428 dump_flags_t extra_dump_flags, tree t)
430 if (dump_file && (dump_kind & pflags))
432 dump_loc (dump_kind, dump_file, loc);
433 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
436 if (alt_dump_file && (dump_kind & alt_flags))
438 dump_loc (dump_kind, alt_dump_file, loc);
439 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
443 /* Output a formatted message using FORMAT on appropriate dump streams. */
445 void
446 dump_printf (dump_flags_t dump_kind, const char *format, ...)
448 if (dump_file && (dump_kind & pflags))
450 va_list ap;
451 va_start (ap, format);
452 vfprintf (dump_file, format, ap);
453 va_end (ap);
456 if (alt_dump_file && (dump_kind & alt_flags))
458 va_list ap;
459 va_start (ap, format);
460 vfprintf (alt_dump_file, format, ap);
461 va_end (ap);
465 /* Similar to dump_printf, except source location is also printed. */
467 void
468 dump_printf_loc (dump_flags_t dump_kind, source_location loc,
469 const char *format, ...)
471 if (dump_file && (dump_kind & pflags))
473 va_list ap;
474 dump_loc (dump_kind, dump_file, loc);
475 va_start (ap, format);
476 vfprintf (dump_file, format, ap);
477 va_end (ap);
480 if (alt_dump_file && (dump_kind & alt_flags))
482 va_list ap;
483 dump_loc (dump_kind, alt_dump_file, loc);
484 va_start (ap, format);
485 vfprintf (alt_dump_file, format, ap);
486 va_end (ap);
490 /* Output VALUE in decimal to appropriate dump streams. */
492 template<unsigned int N, typename C>
493 void
494 dump_dec (int dump_kind, const poly_int<N, C> &value)
496 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
497 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
498 if (dump_file && (dump_kind & pflags))
499 print_dec (value, dump_file, sgn);
501 if (alt_dump_file && (dump_kind & alt_flags))
502 print_dec (value, alt_dump_file, sgn);
505 template void dump_dec (int, const poly_uint16 &);
506 template void dump_dec (int, const poly_int64 &);
507 template void dump_dec (int, const poly_uint64 &);
508 template void dump_dec (int, const poly_offset_int &);
509 template void dump_dec (int, const poly_widest_int &);
511 /* Start a dump for PHASE. Store user-supplied dump flags in
512 *FLAG_PTR. Return the number of streams opened. Set globals
513 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
514 set dump_flags appropriately for both pass dump stream and
515 -fopt-info stream. */
518 gcc::dump_manager::
519 dump_start (int phase, dump_flags_t *flag_ptr)
521 int count = 0;
522 char *name;
523 struct dump_file_info *dfi;
524 FILE *stream;
525 if (phase == TDI_none || !dump_phase_enabled_p (phase))
526 return 0;
528 dfi = get_dump_file_info (phase);
529 name = get_dump_file_name (phase);
530 if (name)
532 stream = dump_open (name, dfi->pstate < 0);
533 if (stream)
535 dfi->pstate = 1;
536 count++;
538 free (name);
539 dfi->pstream = stream;
540 dump_file = dfi->pstream;
541 /* Initialize current dump flags. */
542 pflags = dfi->pflags;
545 stream = dump_open_alternate_stream (dfi);
546 if (stream)
548 dfi->alt_stream = stream;
549 count++;
550 alt_dump_file = dfi->alt_stream;
551 /* Initialize current -fopt-info flags. */
552 alt_flags = dfi->alt_flags;
555 if (flag_ptr)
556 *flag_ptr = dfi->pflags;
558 return count;
561 /* Finish a tree dump for PHASE and close associated dump streams. Also
562 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
564 void
565 gcc::dump_manager::
566 dump_finish (int phase)
568 struct dump_file_info *dfi;
570 if (phase < 0)
571 return;
572 dfi = get_dump_file_info (phase);
573 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
574 fclose (dfi->pstream);
576 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
577 fclose (dfi->alt_stream);
579 dfi->alt_stream = NULL;
580 dfi->pstream = NULL;
581 dump_file = NULL;
582 alt_dump_file = NULL;
583 dump_flags = TDI_none;
584 alt_flags = 0;
585 pflags = 0;
588 /* Begin a tree dump for PHASE. Stores any user supplied flag in
589 *FLAG_PTR and returns a stream to write to. If the dump is not
590 enabled, returns NULL.
591 Multiple calls will reopen and append to the dump file. */
593 FILE *
594 dump_begin (int phase, dump_flags_t *flag_ptr)
596 return g->get_dumps ()->dump_begin (phase, flag_ptr);
599 FILE *
600 gcc::dump_manager::
601 dump_begin (int phase, dump_flags_t *flag_ptr)
603 char *name;
604 struct dump_file_info *dfi;
605 FILE *stream;
607 if (phase == TDI_none || !dump_phase_enabled_p (phase))
608 return NULL;
610 name = get_dump_file_name (phase);
611 if (!name)
612 return NULL;
613 dfi = get_dump_file_info (phase);
615 stream = dump_open (name, dfi->pstate < 0);
616 if (stream)
617 dfi->pstate = 1;
618 free (name);
620 if (flag_ptr)
621 *flag_ptr = dfi->pflags;
623 /* Initialize current flags */
624 pflags = dfi->pflags;
625 return stream;
628 /* Returns nonzero if dump PHASE is enabled for at least one stream.
629 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
630 any phase. */
633 gcc::dump_manager::
634 dump_phase_enabled_p (int phase) const
636 if (phase == TDI_tree_all)
638 size_t i;
639 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
640 if (dump_files[i].pstate || dump_files[i].alt_state)
641 return 1;
642 for (i = 0; i < m_extra_dump_files_in_use; i++)
643 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
644 return 1;
645 return 0;
647 else
649 struct dump_file_info *dfi = get_dump_file_info (phase);
650 return dfi->pstate || dfi->alt_state;
654 /* Returns nonzero if tree dump PHASE has been initialized. */
657 gcc::dump_manager::
658 dump_initialized_p (int phase) const
660 struct dump_file_info *dfi = get_dump_file_info (phase);
661 return dfi->pstate > 0 || dfi->alt_state > 0;
664 /* Returns the switch name of PHASE. */
666 const char *
667 dump_flag_name (int phase)
669 return g->get_dumps ()->dump_flag_name (phase);
672 const char *
673 gcc::dump_manager::
674 dump_flag_name (int phase) const
676 struct dump_file_info *dfi = get_dump_file_info (phase);
677 return dfi->swtch;
680 /* Finish a tree dump for PHASE. STREAM is the stream created by
681 dump_begin. */
683 void
684 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
686 if (stream != stderr && stream != stdout)
687 fclose (stream);
690 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
691 enabled tree dumps. */
694 gcc::dump_manager::
695 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
697 int n = 0;
698 size_t i;
700 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
702 if ((dump_files[i].dkind == dkind))
704 const char *old_filename = dump_files[i].pfilename;
705 dump_files[i].pstate = -1;
706 dump_files[i].pflags |= flags;
707 n++;
708 /* Override the existing filename. */
709 if (filename)
711 dump_files[i].pfilename = xstrdup (filename);
712 /* Since it is a command-line provided file, which is
713 common to all the phases, use it in append mode. */
714 dump_files[i].pstate = 1;
716 if (old_filename && filename != old_filename)
717 free (CONST_CAST (char *, old_filename));
721 for (i = 0; i < m_extra_dump_files_in_use; i++)
723 if ((m_extra_dump_files[i].dkind == dkind))
725 const char *old_filename = m_extra_dump_files[i].pfilename;
726 m_extra_dump_files[i].pstate = -1;
727 m_extra_dump_files[i].pflags |= flags;
728 n++;
729 /* Override the existing filename. */
730 if (filename)
732 m_extra_dump_files[i].pfilename = xstrdup (filename);
733 /* Since it is a command-line provided file, which is
734 common to all the phases, use it in append mode. */
735 m_extra_dump_files[i].pstate = 1;
737 if (old_filename && filename != old_filename)
738 free (CONST_CAST (char *, old_filename));
742 return n;
745 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
746 Enable dumps with FLAGS on FILENAME. Return the number of enabled
747 dumps. */
750 gcc::dump_manager::
751 opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
752 const char *filename)
754 int n = 0;
755 size_t i;
757 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
759 if ((dump_files[i].optgroup_flags & optgroup_flags))
761 const char *old_filename = dump_files[i].alt_filename;
762 /* Since this file is shared among different passes, it
763 should be opened in append mode. */
764 dump_files[i].alt_state = 1;
765 dump_files[i].alt_flags |= flags;
766 n++;
767 /* Override the existing filename. */
768 if (filename)
769 dump_files[i].alt_filename = xstrdup (filename);
770 if (old_filename && filename != old_filename)
771 free (CONST_CAST (char *, old_filename));
775 for (i = 0; i < m_extra_dump_files_in_use; i++)
777 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
779 const char *old_filename = m_extra_dump_files[i].alt_filename;
780 /* Since this file is shared among different passes, it
781 should be opened in append mode. */
782 m_extra_dump_files[i].alt_state = 1;
783 m_extra_dump_files[i].alt_flags |= flags;
784 n++;
785 /* Override the existing filename. */
786 if (filename)
787 m_extra_dump_files[i].alt_filename = xstrdup (filename);
788 if (old_filename && filename != old_filename)
789 free (CONST_CAST (char *, old_filename));
793 return n;
796 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
797 relevant details in the dump_files array. */
800 gcc::dump_manager::
801 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
803 const char *option_value;
804 const char *ptr;
805 dump_flags_t flags;
807 if (doglob && !dfi->glob)
808 return 0;
810 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
811 if (!option_value)
812 return 0;
814 if (*option_value && *option_value != '-' && *option_value != '=')
815 return 0;
817 ptr = option_value;
818 flags = 0;
820 while (*ptr)
822 const struct dump_option_value_info *option_ptr;
823 const char *end_ptr;
824 const char *eq_ptr;
825 unsigned length;
827 while (*ptr == '-')
828 ptr++;
829 end_ptr = strchr (ptr, '-');
830 eq_ptr = strchr (ptr, '=');
832 if (eq_ptr && !end_ptr)
833 end_ptr = eq_ptr;
835 if (!end_ptr)
836 end_ptr = ptr + strlen (ptr);
837 length = end_ptr - ptr;
839 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
840 if (strlen (option_ptr->name) == length
841 && !memcmp (option_ptr->name, ptr, length))
843 flags |= option_ptr->value;
844 goto found;
847 if (*ptr == '=')
849 /* Interpret rest of the argument as a dump filename. This
850 filename overrides other command line filenames. */
851 if (dfi->pfilename)
852 free (CONST_CAST (char *, dfi->pfilename));
853 dfi->pfilename = xstrdup (ptr + 1);
854 break;
856 else
857 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
858 length, ptr, dfi->swtch);
859 found:;
860 ptr = end_ptr;
863 dfi->pstate = -1;
864 dfi->pflags |= flags;
866 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
867 known dumps. */
868 if (dfi->suffix == NULL)
869 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
871 return 1;
875 gcc::dump_manager::
876 dump_switch_p (const char *arg)
878 size_t i;
879 int any = 0;
881 for (i = TDI_none + 1; i != TDI_end; i++)
882 any |= dump_switch_p_1 (arg, &dump_files[i], false);
884 /* Don't glob if we got a hit already */
885 if (!any)
886 for (i = TDI_none + 1; i != TDI_end; i++)
887 any |= dump_switch_p_1 (arg, &dump_files[i], true);
889 for (i = 0; i < m_extra_dump_files_in_use; i++)
890 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
892 if (!any)
893 for (i = 0; i < m_extra_dump_files_in_use; i++)
894 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
897 return any;
900 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
901 and filename. Return non-zero if it is a recognized switch. */
903 static int
904 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
905 char **filename)
907 const char *option_value;
908 const char *ptr;
910 option_value = arg;
911 ptr = option_value;
913 *filename = NULL;
914 *flags = 0;
915 *optgroup_flags = 0;
917 if (!ptr)
918 return 1; /* Handle '-fopt-info' without any additional options. */
920 while (*ptr)
922 const struct dump_option_value_info *option_ptr;
923 const char *end_ptr;
924 const char *eq_ptr;
925 unsigned length;
927 while (*ptr == '-')
928 ptr++;
929 end_ptr = strchr (ptr, '-');
930 eq_ptr = strchr (ptr, '=');
932 if (eq_ptr && !end_ptr)
933 end_ptr = eq_ptr;
935 if (!end_ptr)
936 end_ptr = ptr + strlen (ptr);
937 length = end_ptr - ptr;
939 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
940 option_ptr++)
941 if (strlen (option_ptr->name) == length
942 && !memcmp (option_ptr->name, ptr, length))
944 *flags |= option_ptr->value;
945 goto found;
948 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
949 if (strlen (option_ptr->name) == length
950 && !memcmp (option_ptr->name, ptr, length))
952 *optgroup_flags |= option_ptr->value;
953 goto found;
956 if (*ptr == '=')
958 /* Interpret rest of the argument as a dump filename. This
959 filename overrides other command line filenames. */
960 *filename = xstrdup (ptr + 1);
961 break;
963 else
965 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
966 length, ptr, arg);
967 return 0;
969 found:;
970 ptr = end_ptr;
973 return 1;
976 /* Return non-zero if ARG is a recognized switch for
977 -fopt-info. Return zero otherwise. */
980 opt_info_switch_p (const char *arg)
982 dump_flags_t flags;
983 int optgroup_flags;
984 char *filename;
985 static char *file_seen = NULL;
986 gcc::dump_manager *dumps = g->get_dumps ();
988 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
989 return 0;
991 if (!filename)
992 filename = xstrdup ("stderr");
994 /* Bail out if a different filename has been specified. */
995 if (file_seen && strcmp (file_seen, filename))
997 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
998 arg);
999 return 1;
1002 file_seen = xstrdup (filename);
1003 if (!flags)
1004 flags = MSG_OPTIMIZED_LOCATIONS;
1005 if (!optgroup_flags)
1006 optgroup_flags = OPTGROUP_ALL;
1008 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
1011 /* Print basic block on the dump streams. */
1013 void
1014 dump_basic_block (int dump_kind, basic_block bb, int indent)
1016 if (dump_file && (dump_kind & pflags))
1017 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1018 if (alt_dump_file && (dump_kind & alt_flags))
1019 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1022 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1024 void
1025 dump_function (int phase, tree fn)
1027 FILE *stream;
1028 dump_flags_t flags;
1030 stream = dump_begin (phase, &flags);
1031 if (stream)
1033 dump_function_to_file (fn, stream, flags);
1034 dump_end (phase, stream);
1038 /* Print information from the combine pass on dump_file. */
1040 void
1041 print_combine_total_stats (void)
1043 if (dump_file)
1044 dump_combine_total_stats (dump_file);
1047 /* Enable RTL dump for all the RTL passes. */
1049 bool
1050 enable_rtl_dump_file (void)
1052 gcc::dump_manager *dumps = g->get_dumps ();
1053 int num_enabled =
1054 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1055 NULL);
1056 return num_enabled > 0;