* gimplify.c (nonlocal_vlas): Delete.
[official-gcc.git] / gcc / dumpfile.c
blob2f11284d488479a0c0fc4b5853d276b97b1f6f39
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, TDF_NONE, TDF_NONE, \
54 OPTGROUP_NONE, 0, 0, num, 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 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
68 #define FIRST_AUTO_NUMBERED_DUMP 1
69 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
71 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
72 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
73 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
74 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
77 /* Define a name->number mapping for a dump flag value. */
78 template <typename ValueType>
79 struct kv_pair
81 const char *const name; /* the name of the value */
82 const ValueType value; /* the value of the name */
85 /* Table of dump options. This must be consistent with the TDF_* flags
86 in dumpfile.h and opt_info_options below. */
87 static const kv_pair<dump_flags_t> dump_options[] =
89 {"address", TDF_ADDRESS},
90 {"asmname", TDF_ASMNAME},
91 {"slim", TDF_SLIM},
92 {"raw", TDF_RAW},
93 {"graph", TDF_GRAPH},
94 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
95 | MSG_MISSED_OPTIMIZATION
96 | MSG_NOTE)},
97 {"cselib", TDF_CSELIB},
98 {"stats", TDF_STATS},
99 {"blocks", TDF_BLOCKS},
100 {"vops", TDF_VOPS},
101 {"lineno", TDF_LINENO},
102 {"uid", TDF_UID},
103 {"stmtaddr", TDF_STMTADDR},
104 {"memsyms", TDF_MEMSYMS},
105 {"eh", TDF_EH},
106 {"alias", TDF_ALIAS},
107 {"nouid", TDF_NOUID},
108 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
109 {"scev", TDF_SCEV},
110 {"gimple", TDF_GIMPLE},
111 {"folding", TDF_FOLDING},
112 {"optimized", MSG_OPTIMIZED_LOCATIONS},
113 {"missed", MSG_MISSED_OPTIMIZATION},
114 {"note", MSG_NOTE},
115 {"optall", MSG_ALL},
116 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
117 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
118 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
119 {NULL, TDF_NONE}
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 kv_pair<dump_flags_t> optinfo_verbosity_options[] =
127 {"optimized", MSG_OPTIMIZED_LOCATIONS},
128 {"missed", MSG_MISSED_OPTIMIZATION},
129 {"note", MSG_NOTE},
130 {"all", MSG_ALL},
131 {NULL, TDF_NONE}
134 /* Flags used for -fopt-info groups. */
135 static const kv_pair<optgroup_flags_t> optgroup_options[] =
137 {"ipa", OPTGROUP_IPA},
138 {"loop", OPTGROUP_LOOP},
139 {"inline", OPTGROUP_INLINE},
140 {"omp", OPTGROUP_OMP},
141 {"vec", OPTGROUP_VEC},
142 {"optall", OPTGROUP_ALL},
143 {NULL, OPTGROUP_NONE}
146 gcc::dump_manager::dump_manager ():
147 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
148 m_extra_dump_files (NULL),
149 m_extra_dump_files_in_use (0),
150 m_extra_dump_files_alloced (0)
154 gcc::dump_manager::~dump_manager ()
156 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
158 dump_file_info *dfi = &m_extra_dump_files[i];
159 /* suffix, swtch, glob are statically allocated for the entries
160 in dump_files, and for statistics, but are dynamically allocated
161 for those for passes. */
162 if (dfi->owns_strings)
164 XDELETEVEC (const_cast <char *> (dfi->suffix));
165 XDELETEVEC (const_cast <char *> (dfi->swtch));
166 XDELETEVEC (const_cast <char *> (dfi->glob));
168 /* These, if non-NULL, are always dynamically allocated. */
169 XDELETEVEC (const_cast <char *> (dfi->pfilename));
170 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
172 XDELETEVEC (m_extra_dump_files);
175 unsigned int
176 gcc::dump_manager::
177 dump_register (const char *suffix, const char *swtch, const char *glob,
178 dump_kind dkind, optgroup_flags_t optgroup_flags,
179 bool take_ownership)
181 int num = m_next_dump++;
183 size_t count = m_extra_dump_files_in_use++;
185 if (count >= m_extra_dump_files_alloced)
187 if (m_extra_dump_files_alloced == 0)
188 m_extra_dump_files_alloced = 512;
189 else
190 m_extra_dump_files_alloced *= 2;
191 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
192 m_extra_dump_files,
193 m_extra_dump_files_alloced);
195 /* Construct a new object in the space allocated above. */
196 new (m_extra_dump_files + count) dump_file_info ();
198 else
200 /* Zero out the already constructed object. */
201 m_extra_dump_files[count] = dump_file_info ();
204 m_extra_dump_files[count].suffix = suffix;
205 m_extra_dump_files[count].swtch = swtch;
206 m_extra_dump_files[count].glob = glob;
207 m_extra_dump_files[count].dkind = dkind;
208 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
209 m_extra_dump_files[count].num = num;
210 m_extra_dump_files[count].owns_strings = take_ownership;
212 return count + TDI_end;
216 /* Allow languages and middle-end to register their dumps before the
217 optimization passes. */
219 void
220 gcc::dump_manager::
221 register_dumps ()
223 lang_hooks.register_dumps (this);
224 /* If this assert fails, some FE registered more than
225 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
226 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
227 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
228 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
229 dump_files[TDI_original].num = m_next_dump++;
230 dump_files[TDI_gimple].num = m_next_dump++;
231 dump_files[TDI_nested].num = m_next_dump++;
235 /* Return the dump_file_info for the given phase. */
237 struct dump_file_info *
238 gcc::dump_manager::
239 get_dump_file_info (int phase) const
241 if (phase < TDI_end)
242 return &dump_files[phase];
243 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
244 return NULL;
245 else
246 return m_extra_dump_files + (phase - TDI_end);
249 /* Locate the dump_file_info with swtch equal to SWTCH,
250 or return NULL if no such dump_file_info exists. */
252 struct dump_file_info *
253 gcc::dump_manager::
254 get_dump_file_info_by_switch (const char *swtch) const
256 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
257 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
258 return &m_extra_dump_files[i];
260 /* Not found. */
261 return NULL;
265 /* Return the name of the dump file for the given phase.
266 The caller is responsible for calling free on the returned
267 buffer.
268 If the dump is not enabled, returns NULL. */
270 char *
271 gcc::dump_manager::
272 get_dump_file_name (int phase) const
274 struct dump_file_info *dfi;
276 if (phase == TDI_none)
277 return NULL;
279 dfi = get_dump_file_info (phase);
281 return get_dump_file_name (dfi);
284 /* Return the name of the dump file for the given dump_file_info.
285 The caller is responsible for calling free on the returned
286 buffer.
287 If the dump is not enabled, returns NULL. */
289 char *
290 gcc::dump_manager::
291 get_dump_file_name (struct dump_file_info *dfi) const
293 char dump_id[10];
295 gcc_assert (dfi);
297 if (dfi->pstate == 0)
298 return NULL;
300 /* If available, use the command line dump filename. */
301 if (dfi->pfilename)
302 return xstrdup (dfi->pfilename);
304 if (dfi->num < 0)
305 dump_id[0] = '\0';
306 else
308 /* (null), LANG, TREE, RTL, IPA. */
309 char suffix = " ltri"[dfi->dkind];
311 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
312 dump_id[0] = '\0';
315 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
318 /* Open a dump file called FILENAME. Some filenames are special and
319 refer to the standard streams. TRUNC indicates whether this is the
320 first open (so the file should be truncated, rather than appended).
321 An error message is emitted in the event of failure. */
323 static FILE *
324 dump_open (const char *filename, bool trunc)
326 if (strcmp ("stderr", filename) == 0)
327 return stderr;
329 if (strcmp ("stdout", filename) == 0
330 || strcmp ("-", filename) == 0)
331 return stdout;
333 FILE *stream = fopen (filename, trunc ? "w" : "a");
335 if (!stream)
336 error ("could not open dump file %qs: %m", filename);
337 return stream;
340 /* For a given DFI, open an alternate dump filename (which could also
341 be a standard stream such as stdout/stderr). If the alternate dump
342 file cannot be opened, return NULL. */
344 static FILE *
345 dump_open_alternate_stream (struct dump_file_info *dfi)
347 if (!dfi->alt_filename)
348 return NULL;
350 if (dfi->alt_stream)
351 return dfi->alt_stream;
353 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
355 if (stream)
356 dfi->alt_state = 1;
358 return stream;
361 /* Print source location on DFILE if enabled. */
363 void
364 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
366 if (dump_kind)
368 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
369 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
370 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
371 else if (current_function_decl)
372 fprintf (dfile, "%s:%d:%d: note: ",
373 DECL_SOURCE_FILE (current_function_decl),
374 DECL_SOURCE_LINE (current_function_decl),
375 DECL_SOURCE_COLUMN (current_function_decl));
379 /* Dump gimple statement GS with SPC indentation spaces and
380 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
382 void
383 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
384 gimple *gs, int spc)
386 if (dump_file && (dump_kind & pflags))
387 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
389 if (alt_dump_file && (dump_kind & alt_flags))
390 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
393 /* Similar to dump_gimple_stmt, except additionally print source location. */
395 void
396 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
397 dump_flags_t extra_dump_flags, gimple *gs, int spc)
399 if (dump_file && (dump_kind & pflags))
401 dump_loc (dump_kind, dump_file, loc);
402 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
405 if (alt_dump_file && (dump_kind & alt_flags))
407 dump_loc (dump_kind, alt_dump_file, loc);
408 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
412 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
413 DUMP_KIND is enabled. */
415 void
416 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
417 tree t)
419 if (dump_file && (dump_kind & pflags))
420 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
422 if (alt_dump_file && (dump_kind & alt_flags))
423 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
427 /* Similar to dump_generic_expr, except additionally print the source
428 location. */
430 void
431 dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
432 dump_flags_t extra_dump_flags, tree t)
434 if (dump_file && (dump_kind & pflags))
436 dump_loc (dump_kind, dump_file, loc);
437 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
440 if (alt_dump_file && (dump_kind & alt_flags))
442 dump_loc (dump_kind, alt_dump_file, loc);
443 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
447 /* Output a formatted message using FORMAT on appropriate dump streams. */
449 void
450 dump_printf (dump_flags_t dump_kind, const char *format, ...)
452 if (dump_file && (dump_kind & pflags))
454 va_list ap;
455 va_start (ap, format);
456 vfprintf (dump_file, format, ap);
457 va_end (ap);
460 if (alt_dump_file && (dump_kind & alt_flags))
462 va_list ap;
463 va_start (ap, format);
464 vfprintf (alt_dump_file, format, ap);
465 va_end (ap);
469 /* Similar to dump_printf, except source location is also printed. */
471 void
472 dump_printf_loc (dump_flags_t dump_kind, source_location loc,
473 const char *format, ...)
475 if (dump_file && (dump_kind & pflags))
477 va_list ap;
478 dump_loc (dump_kind, dump_file, loc);
479 va_start (ap, format);
480 vfprintf (dump_file, format, ap);
481 va_end (ap);
484 if (alt_dump_file && (dump_kind & alt_flags))
486 va_list ap;
487 dump_loc (dump_kind, alt_dump_file, loc);
488 va_start (ap, format);
489 vfprintf (alt_dump_file, format, ap);
490 va_end (ap);
494 /* Output VALUE in decimal to appropriate dump streams. */
496 template<unsigned int N, typename C>
497 void
498 dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
500 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
501 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
502 if (dump_file && (dump_kind & pflags))
503 print_dec (value, dump_file, sgn);
505 if (alt_dump_file && (dump_kind & alt_flags))
506 print_dec (value, alt_dump_file, sgn);
509 template void dump_dec (dump_flags_t, const poly_uint16 &);
510 template void dump_dec (dump_flags_t, const poly_int64 &);
511 template void dump_dec (dump_flags_t, const poly_uint64 &);
512 template void dump_dec (dump_flags_t, const poly_offset_int &);
513 template void dump_dec (dump_flags_t, const poly_widest_int &);
515 /* Start a dump for PHASE. Store user-supplied dump flags in
516 *FLAG_PTR. Return the number of streams opened. Set globals
517 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
518 set dump_flags appropriately for both pass dump stream and
519 -fopt-info stream. */
522 gcc::dump_manager::
523 dump_start (int phase, dump_flags_t *flag_ptr)
525 int count = 0;
526 char *name;
527 struct dump_file_info *dfi;
528 FILE *stream;
529 if (phase == TDI_none || !dump_phase_enabled_p (phase))
530 return 0;
532 dfi = get_dump_file_info (phase);
533 name = get_dump_file_name (phase);
534 if (name)
536 stream = dump_open (name, dfi->pstate < 0);
537 if (stream)
539 dfi->pstate = 1;
540 count++;
542 free (name);
543 dfi->pstream = stream;
544 dump_file = dfi->pstream;
545 /* Initialize current dump flags. */
546 pflags = dfi->pflags;
549 stream = dump_open_alternate_stream (dfi);
550 if (stream)
552 dfi->alt_stream = stream;
553 count++;
554 alt_dump_file = dfi->alt_stream;
555 /* Initialize current -fopt-info flags. */
556 alt_flags = dfi->alt_flags;
559 if (flag_ptr)
560 *flag_ptr = dfi->pflags;
562 return count;
565 /* Finish a tree dump for PHASE and close associated dump streams. Also
566 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
568 void
569 gcc::dump_manager::
570 dump_finish (int phase)
572 struct dump_file_info *dfi;
574 if (phase < 0)
575 return;
576 dfi = get_dump_file_info (phase);
577 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
578 fclose (dfi->pstream);
580 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
581 fclose (dfi->alt_stream);
583 dfi->alt_stream = NULL;
584 dfi->pstream = NULL;
585 dump_file = NULL;
586 alt_dump_file = NULL;
587 dump_flags = TDF_NONE;
588 alt_flags = TDF_NONE;
589 pflags = TDF_NONE;
592 /* Begin a tree dump for PHASE. Stores any user supplied flag in
593 *FLAG_PTR and returns a stream to write to. If the dump is not
594 enabled, returns NULL.
595 Multiple calls will reopen and append to the dump file. */
597 FILE *
598 dump_begin (int phase, dump_flags_t *flag_ptr)
600 return g->get_dumps ()->dump_begin (phase, flag_ptr);
603 FILE *
604 gcc::dump_manager::
605 dump_begin (int phase, dump_flags_t *flag_ptr)
607 char *name;
608 struct dump_file_info *dfi;
609 FILE *stream;
611 if (phase == TDI_none || !dump_phase_enabled_p (phase))
612 return NULL;
614 name = get_dump_file_name (phase);
615 if (!name)
616 return NULL;
617 dfi = get_dump_file_info (phase);
619 stream = dump_open (name, dfi->pstate < 0);
620 if (stream)
621 dfi->pstate = 1;
622 free (name);
624 if (flag_ptr)
625 *flag_ptr = dfi->pflags;
627 /* Initialize current flags */
628 pflags = dfi->pflags;
629 return stream;
632 /* Returns nonzero if dump PHASE is enabled for at least one stream.
633 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
634 any phase. */
637 gcc::dump_manager::
638 dump_phase_enabled_p (int phase) const
640 if (phase == TDI_tree_all)
642 size_t i;
643 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
644 if (dump_files[i].pstate || dump_files[i].alt_state)
645 return 1;
646 for (i = 0; i < m_extra_dump_files_in_use; i++)
647 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
648 return 1;
649 return 0;
651 else
653 struct dump_file_info *dfi = get_dump_file_info (phase);
654 return dfi->pstate || dfi->alt_state;
658 /* Returns nonzero if tree dump PHASE has been initialized. */
661 gcc::dump_manager::
662 dump_initialized_p (int phase) const
664 struct dump_file_info *dfi = get_dump_file_info (phase);
665 return dfi->pstate > 0 || dfi->alt_state > 0;
668 /* Returns the switch name of PHASE. */
670 const char *
671 dump_flag_name (int phase)
673 return g->get_dumps ()->dump_flag_name (phase);
676 const char *
677 gcc::dump_manager::
678 dump_flag_name (int phase) const
680 struct dump_file_info *dfi = get_dump_file_info (phase);
681 return dfi->swtch;
684 /* Finish a tree dump for PHASE. STREAM is the stream created by
685 dump_begin. */
687 void
688 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
690 if (stream != stderr && stream != stdout)
691 fclose (stream);
694 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
695 enabled tree dumps. */
698 gcc::dump_manager::
699 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
701 int n = 0;
702 size_t i;
704 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
706 if ((dump_files[i].dkind == dkind))
708 const char *old_filename = dump_files[i].pfilename;
709 dump_files[i].pstate = -1;
710 dump_files[i].pflags |= flags;
711 n++;
712 /* Override the existing filename. */
713 if (filename)
715 dump_files[i].pfilename = xstrdup (filename);
716 /* Since it is a command-line provided file, which is
717 common to all the phases, use it in append mode. */
718 dump_files[i].pstate = 1;
720 if (old_filename && filename != old_filename)
721 free (CONST_CAST (char *, old_filename));
725 for (i = 0; i < m_extra_dump_files_in_use; i++)
727 if ((m_extra_dump_files[i].dkind == dkind))
729 const char *old_filename = m_extra_dump_files[i].pfilename;
730 m_extra_dump_files[i].pstate = -1;
731 m_extra_dump_files[i].pflags |= flags;
732 n++;
733 /* Override the existing filename. */
734 if (filename)
736 m_extra_dump_files[i].pfilename = xstrdup (filename);
737 /* Since it is a command-line provided file, which is
738 common to all the phases, use it in append mode. */
739 m_extra_dump_files[i].pstate = 1;
741 if (old_filename && filename != old_filename)
742 free (CONST_CAST (char *, old_filename));
746 return n;
749 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
750 Enable dumps with FLAGS on FILENAME. Return the number of enabled
751 dumps. */
754 gcc::dump_manager::
755 opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
756 const char *filename)
758 int n = 0;
759 size_t i;
761 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
763 if ((dump_files[i].optgroup_flags & optgroup_flags))
765 const char *old_filename = dump_files[i].alt_filename;
766 /* Since this file is shared among different passes, it
767 should be opened in append mode. */
768 dump_files[i].alt_state = 1;
769 dump_files[i].alt_flags |= flags;
770 n++;
771 /* Override the existing filename. */
772 if (filename)
773 dump_files[i].alt_filename = xstrdup (filename);
774 if (old_filename && filename != old_filename)
775 free (CONST_CAST (char *, old_filename));
779 for (i = 0; i < m_extra_dump_files_in_use; i++)
781 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
783 const char *old_filename = m_extra_dump_files[i].alt_filename;
784 /* Since this file is shared among different passes, it
785 should be opened in append mode. */
786 m_extra_dump_files[i].alt_state = 1;
787 m_extra_dump_files[i].alt_flags |= flags;
788 n++;
789 /* Override the existing filename. */
790 if (filename)
791 m_extra_dump_files[i].alt_filename = xstrdup (filename);
792 if (old_filename && filename != old_filename)
793 free (CONST_CAST (char *, old_filename));
797 return n;
800 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
801 relevant details in the dump_files array. */
804 gcc::dump_manager::
805 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
807 const char *option_value;
808 const char *ptr;
809 dump_flags_t flags;
811 if (doglob && !dfi->glob)
812 return 0;
814 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
815 if (!option_value)
816 return 0;
818 if (*option_value && *option_value != '-' && *option_value != '=')
819 return 0;
821 ptr = option_value;
822 flags = TDF_NONE;
824 while (*ptr)
826 const struct kv_pair<dump_flags_t> *option_ptr;
827 const char *end_ptr;
828 const char *eq_ptr;
829 unsigned length;
831 while (*ptr == '-')
832 ptr++;
833 end_ptr = strchr (ptr, '-');
834 eq_ptr = strchr (ptr, '=');
836 if (eq_ptr && !end_ptr)
837 end_ptr = eq_ptr;
839 if (!end_ptr)
840 end_ptr = ptr + strlen (ptr);
841 length = end_ptr - ptr;
843 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
844 if (strlen (option_ptr->name) == length
845 && !memcmp (option_ptr->name, ptr, length))
847 flags |= option_ptr->value;
848 goto found;
851 if (*ptr == '=')
853 /* Interpret rest of the argument as a dump filename. This
854 filename overrides other command line filenames. */
855 if (dfi->pfilename)
856 free (CONST_CAST (char *, dfi->pfilename));
857 dfi->pfilename = xstrdup (ptr + 1);
858 break;
860 else
861 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
862 length, ptr, dfi->swtch);
863 found:;
864 ptr = end_ptr;
867 dfi->pstate = -1;
868 dfi->pflags |= flags;
870 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
871 known dumps. */
872 if (dfi->suffix == NULL)
873 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
875 return 1;
879 gcc::dump_manager::
880 dump_switch_p (const char *arg)
882 size_t i;
883 int any = 0;
885 for (i = TDI_none + 1; i != TDI_end; i++)
886 any |= dump_switch_p_1 (arg, &dump_files[i], false);
888 /* Don't glob if we got a hit already */
889 if (!any)
890 for (i = TDI_none + 1; i != TDI_end; i++)
891 any |= dump_switch_p_1 (arg, &dump_files[i], true);
893 for (i = 0; i < m_extra_dump_files_in_use; i++)
894 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
896 if (!any)
897 for (i = 0; i < m_extra_dump_files_in_use; i++)
898 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
901 return any;
904 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
905 and filename. Return non-zero if it is a recognized switch. */
907 static int
908 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
909 optgroup_flags_t *optgroup_flags, char **filename)
911 const char *option_value;
912 const char *ptr;
914 option_value = arg;
915 ptr = option_value;
917 *filename = NULL;
918 *flags = TDF_NONE;
919 *optgroup_flags = OPTGROUP_NONE;
921 if (!ptr)
922 return 1; /* Handle '-fopt-info' without any additional options. */
924 while (*ptr)
926 const char *end_ptr;
927 const char *eq_ptr;
928 unsigned length;
930 while (*ptr == '-')
931 ptr++;
932 end_ptr = strchr (ptr, '-');
933 eq_ptr = strchr (ptr, '=');
935 if (eq_ptr && !end_ptr)
936 end_ptr = eq_ptr;
938 if (!end_ptr)
939 end_ptr = ptr + strlen (ptr);
940 length = end_ptr - ptr;
942 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
943 option_ptr->name; option_ptr++)
944 if (strlen (option_ptr->name) == length
945 && !memcmp (option_ptr->name, ptr, length))
947 *flags |= option_ptr->value;
948 goto found;
951 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
952 option_ptr->name; option_ptr++)
953 if (strlen (option_ptr->name) == length
954 && !memcmp (option_ptr->name, ptr, length))
956 *optgroup_flags |= option_ptr->value;
957 goto found;
960 if (*ptr == '=')
962 /* Interpret rest of the argument as a dump filename. This
963 filename overrides other command line filenames. */
964 *filename = xstrdup (ptr + 1);
965 break;
967 else
969 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
970 length, ptr, arg);
971 return 0;
973 found:;
974 ptr = end_ptr;
977 return 1;
980 /* Return non-zero if ARG is a recognized switch for
981 -fopt-info. Return zero otherwise. */
984 opt_info_switch_p (const char *arg)
986 dump_flags_t flags;
987 optgroup_flags_t optgroup_flags;
988 char *filename;
989 static char *file_seen = NULL;
990 gcc::dump_manager *dumps = g->get_dumps ();
992 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
993 return 0;
995 if (!filename)
996 filename = xstrdup ("stderr");
998 /* Bail out if a different filename has been specified. */
999 if (file_seen && strcmp (file_seen, filename))
1001 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1002 arg);
1003 return 1;
1006 file_seen = xstrdup (filename);
1007 if (!flags)
1008 flags = MSG_OPTIMIZED_LOCATIONS;
1009 if (!optgroup_flags)
1010 optgroup_flags = OPTGROUP_ALL;
1012 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
1015 /* Print basic block on the dump streams. */
1017 void
1018 dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
1020 if (dump_file && (dump_kind & pflags))
1021 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1022 if (alt_dump_file && (dump_kind & alt_flags))
1023 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1026 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1028 void
1029 dump_function (int phase, tree fn)
1031 FILE *stream;
1032 dump_flags_t flags;
1034 stream = dump_begin (phase, &flags);
1035 if (stream)
1037 dump_function_to_file (fn, stream, flags);
1038 dump_end (phase, stream);
1042 /* Print information from the combine pass on dump_file. */
1044 void
1045 print_combine_total_stats (void)
1047 if (dump_file)
1048 dump_combine_total_stats (dump_file);
1051 /* Enable RTL dump for all the RTL passes. */
1053 bool
1054 enable_rtl_dump_file (void)
1056 gcc::dump_manager *dumps = g->get_dumps ();
1057 int num_enabled =
1058 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1059 NULL);
1060 return num_enabled > 0;