PR tree-optimization/85822
[official-gcc.git] / gcc / dumpfile.c
blob0f16d4f044f30e46710fc385ff70c905312f4bda
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 || strcmp ("-", filename) == 0)
328 return stdout;
330 FILE *stream = fopen (filename, trunc ? "w" : "a");
332 if (!stream)
333 error ("could not open dump file %qs: %m", filename);
334 return stream;
337 /* For a given DFI, open an alternate dump filename (which could also
338 be a standard stream such as stdout/stderr). If the alternate dump
339 file cannot be opened, return NULL. */
341 static FILE *
342 dump_open_alternate_stream (struct dump_file_info *dfi)
344 if (!dfi->alt_filename)
345 return NULL;
347 if (dfi->alt_stream)
348 return dfi->alt_stream;
350 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
352 if (stream)
353 dfi->alt_state = 1;
355 return stream;
358 /* Print source location on DFILE if enabled. */
360 void
361 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
363 if (dump_kind)
365 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
366 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
367 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
368 else if (current_function_decl)
369 fprintf (dfile, "%s:%d:%d: note: ",
370 DECL_SOURCE_FILE (current_function_decl),
371 DECL_SOURCE_LINE (current_function_decl),
372 DECL_SOURCE_COLUMN (current_function_decl));
376 /* Dump gimple statement GS with SPC indentation spaces and
377 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
379 void
380 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
381 gimple *gs, int spc)
383 if (dump_file && (dump_kind & pflags))
384 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
386 if (alt_dump_file && (dump_kind & alt_flags))
387 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
390 /* Similar to dump_gimple_stmt, except additionally print source location. */
392 void
393 dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
394 dump_flags_t extra_dump_flags, gimple *gs, int spc)
396 if (dump_file && (dump_kind & pflags))
398 dump_loc (dump_kind, dump_file, loc);
399 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
402 if (alt_dump_file && (dump_kind & alt_flags))
404 dump_loc (dump_kind, alt_dump_file, loc);
405 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
409 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
410 DUMP_KIND is enabled. */
412 void
413 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
414 tree t)
416 if (dump_file && (dump_kind & pflags))
417 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
419 if (alt_dump_file && (dump_kind & alt_flags))
420 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
424 /* Similar to dump_generic_expr, except additionally print the source
425 location. */
427 void
428 dump_generic_expr_loc (int dump_kind, source_location loc,
429 dump_flags_t extra_dump_flags, tree t)
431 if (dump_file && (dump_kind & pflags))
433 dump_loc (dump_kind, dump_file, loc);
434 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
437 if (alt_dump_file && (dump_kind & alt_flags))
439 dump_loc (dump_kind, alt_dump_file, loc);
440 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
444 /* Output a formatted message using FORMAT on appropriate dump streams. */
446 void
447 dump_printf (dump_flags_t dump_kind, const char *format, ...)
449 if (dump_file && (dump_kind & pflags))
451 va_list ap;
452 va_start (ap, format);
453 vfprintf (dump_file, format, ap);
454 va_end (ap);
457 if (alt_dump_file && (dump_kind & alt_flags))
459 va_list ap;
460 va_start (ap, format);
461 vfprintf (alt_dump_file, format, ap);
462 va_end (ap);
466 /* Similar to dump_printf, except source location is also printed. */
468 void
469 dump_printf_loc (dump_flags_t dump_kind, source_location loc,
470 const char *format, ...)
472 if (dump_file && (dump_kind & pflags))
474 va_list ap;
475 dump_loc (dump_kind, dump_file, loc);
476 va_start (ap, format);
477 vfprintf (dump_file, format, ap);
478 va_end (ap);
481 if (alt_dump_file && (dump_kind & alt_flags))
483 va_list ap;
484 dump_loc (dump_kind, alt_dump_file, loc);
485 va_start (ap, format);
486 vfprintf (alt_dump_file, format, ap);
487 va_end (ap);
491 /* Output VALUE in decimal to appropriate dump streams. */
493 template<unsigned int N, typename C>
494 void
495 dump_dec (int dump_kind, const poly_int<N, C> &value)
497 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
498 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
499 if (dump_file && (dump_kind & pflags))
500 print_dec (value, dump_file, sgn);
502 if (alt_dump_file && (dump_kind & alt_flags))
503 print_dec (value, alt_dump_file, sgn);
506 template void dump_dec (int, const poly_uint16 &);
507 template void dump_dec (int, const poly_int64 &);
508 template void dump_dec (int, const poly_uint64 &);
509 template void dump_dec (int, const poly_offset_int &);
510 template void dump_dec (int, const poly_widest_int &);
512 /* Start a dump for PHASE. Store user-supplied dump flags in
513 *FLAG_PTR. Return the number of streams opened. Set globals
514 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
515 set dump_flags appropriately for both pass dump stream and
516 -fopt-info stream. */
519 gcc::dump_manager::
520 dump_start (int phase, dump_flags_t *flag_ptr)
522 int count = 0;
523 char *name;
524 struct dump_file_info *dfi;
525 FILE *stream;
526 if (phase == TDI_none || !dump_phase_enabled_p (phase))
527 return 0;
529 dfi = get_dump_file_info (phase);
530 name = get_dump_file_name (phase);
531 if (name)
533 stream = dump_open (name, dfi->pstate < 0);
534 if (stream)
536 dfi->pstate = 1;
537 count++;
539 free (name);
540 dfi->pstream = stream;
541 dump_file = dfi->pstream;
542 /* Initialize current dump flags. */
543 pflags = dfi->pflags;
546 stream = dump_open_alternate_stream (dfi);
547 if (stream)
549 dfi->alt_stream = stream;
550 count++;
551 alt_dump_file = dfi->alt_stream;
552 /* Initialize current -fopt-info flags. */
553 alt_flags = dfi->alt_flags;
556 if (flag_ptr)
557 *flag_ptr = dfi->pflags;
559 return count;
562 /* Finish a tree dump for PHASE and close associated dump streams. Also
563 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
565 void
566 gcc::dump_manager::
567 dump_finish (int phase)
569 struct dump_file_info *dfi;
571 if (phase < 0)
572 return;
573 dfi = get_dump_file_info (phase);
574 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
575 fclose (dfi->pstream);
577 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
578 fclose (dfi->alt_stream);
580 dfi->alt_stream = NULL;
581 dfi->pstream = NULL;
582 dump_file = NULL;
583 alt_dump_file = NULL;
584 dump_flags = TDI_none;
585 alt_flags = 0;
586 pflags = 0;
589 /* Begin a tree dump for PHASE. Stores any user supplied flag in
590 *FLAG_PTR and returns a stream to write to. If the dump is not
591 enabled, returns NULL.
592 Multiple calls will reopen and append to the dump file. */
594 FILE *
595 dump_begin (int phase, dump_flags_t *flag_ptr)
597 return g->get_dumps ()->dump_begin (phase, flag_ptr);
600 FILE *
601 gcc::dump_manager::
602 dump_begin (int phase, dump_flags_t *flag_ptr)
604 char *name;
605 struct dump_file_info *dfi;
606 FILE *stream;
608 if (phase == TDI_none || !dump_phase_enabled_p (phase))
609 return NULL;
611 name = get_dump_file_name (phase);
612 if (!name)
613 return NULL;
614 dfi = get_dump_file_info (phase);
616 stream = dump_open (name, dfi->pstate < 0);
617 if (stream)
618 dfi->pstate = 1;
619 free (name);
621 if (flag_ptr)
622 *flag_ptr = dfi->pflags;
624 /* Initialize current flags */
625 pflags = dfi->pflags;
626 return stream;
629 /* Returns nonzero if dump PHASE is enabled for at least one stream.
630 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
631 any phase. */
634 gcc::dump_manager::
635 dump_phase_enabled_p (int phase) const
637 if (phase == TDI_tree_all)
639 size_t i;
640 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
641 if (dump_files[i].pstate || dump_files[i].alt_state)
642 return 1;
643 for (i = 0; i < m_extra_dump_files_in_use; i++)
644 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
645 return 1;
646 return 0;
648 else
650 struct dump_file_info *dfi = get_dump_file_info (phase);
651 return dfi->pstate || dfi->alt_state;
655 /* Returns nonzero if tree dump PHASE has been initialized. */
658 gcc::dump_manager::
659 dump_initialized_p (int phase) const
661 struct dump_file_info *dfi = get_dump_file_info (phase);
662 return dfi->pstate > 0 || dfi->alt_state > 0;
665 /* Returns the switch name of PHASE. */
667 const char *
668 dump_flag_name (int phase)
670 return g->get_dumps ()->dump_flag_name (phase);
673 const char *
674 gcc::dump_manager::
675 dump_flag_name (int phase) const
677 struct dump_file_info *dfi = get_dump_file_info (phase);
678 return dfi->swtch;
681 /* Finish a tree dump for PHASE. STREAM is the stream created by
682 dump_begin. */
684 void
685 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
687 if (stream != stderr && stream != stdout)
688 fclose (stream);
691 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
692 enabled tree dumps. */
695 gcc::dump_manager::
696 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
698 int n = 0;
699 size_t i;
701 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
703 if ((dump_files[i].dkind == dkind))
705 const char *old_filename = dump_files[i].pfilename;
706 dump_files[i].pstate = -1;
707 dump_files[i].pflags |= flags;
708 n++;
709 /* Override the existing filename. */
710 if (filename)
712 dump_files[i].pfilename = xstrdup (filename);
713 /* Since it is a command-line provided file, which is
714 common to all the phases, use it in append mode. */
715 dump_files[i].pstate = 1;
717 if (old_filename && filename != old_filename)
718 free (CONST_CAST (char *, old_filename));
722 for (i = 0; i < m_extra_dump_files_in_use; i++)
724 if ((m_extra_dump_files[i].dkind == dkind))
726 const char *old_filename = m_extra_dump_files[i].pfilename;
727 m_extra_dump_files[i].pstate = -1;
728 m_extra_dump_files[i].pflags |= flags;
729 n++;
730 /* Override the existing filename. */
731 if (filename)
733 m_extra_dump_files[i].pfilename = xstrdup (filename);
734 /* Since it is a command-line provided file, which is
735 common to all the phases, use it in append mode. */
736 m_extra_dump_files[i].pstate = 1;
738 if (old_filename && filename != old_filename)
739 free (CONST_CAST (char *, old_filename));
743 return n;
746 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
747 Enable dumps with FLAGS on FILENAME. Return the number of enabled
748 dumps. */
751 gcc::dump_manager::
752 opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
753 const char *filename)
755 int n = 0;
756 size_t i;
758 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
760 if ((dump_files[i].optgroup_flags & optgroup_flags))
762 const char *old_filename = dump_files[i].alt_filename;
763 /* Since this file is shared among different passes, it
764 should be opened in append mode. */
765 dump_files[i].alt_state = 1;
766 dump_files[i].alt_flags |= flags;
767 n++;
768 /* Override the existing filename. */
769 if (filename)
770 dump_files[i].alt_filename = xstrdup (filename);
771 if (old_filename && filename != old_filename)
772 free (CONST_CAST (char *, old_filename));
776 for (i = 0; i < m_extra_dump_files_in_use; i++)
778 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
780 const char *old_filename = m_extra_dump_files[i].alt_filename;
781 /* Since this file is shared among different passes, it
782 should be opened in append mode. */
783 m_extra_dump_files[i].alt_state = 1;
784 m_extra_dump_files[i].alt_flags |= flags;
785 n++;
786 /* Override the existing filename. */
787 if (filename)
788 m_extra_dump_files[i].alt_filename = xstrdup (filename);
789 if (old_filename && filename != old_filename)
790 free (CONST_CAST (char *, old_filename));
794 return n;
797 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
798 relevant details in the dump_files array. */
801 gcc::dump_manager::
802 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
804 const char *option_value;
805 const char *ptr;
806 dump_flags_t flags;
808 if (doglob && !dfi->glob)
809 return 0;
811 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
812 if (!option_value)
813 return 0;
815 if (*option_value && *option_value != '-' && *option_value != '=')
816 return 0;
818 ptr = option_value;
819 flags = 0;
821 while (*ptr)
823 const struct dump_option_value_info *option_ptr;
824 const char *end_ptr;
825 const char *eq_ptr;
826 unsigned length;
828 while (*ptr == '-')
829 ptr++;
830 end_ptr = strchr (ptr, '-');
831 eq_ptr = strchr (ptr, '=');
833 if (eq_ptr && !end_ptr)
834 end_ptr = eq_ptr;
836 if (!end_ptr)
837 end_ptr = ptr + strlen (ptr);
838 length = end_ptr - ptr;
840 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
841 if (strlen (option_ptr->name) == length
842 && !memcmp (option_ptr->name, ptr, length))
844 flags |= option_ptr->value;
845 goto found;
848 if (*ptr == '=')
850 /* Interpret rest of the argument as a dump filename. This
851 filename overrides other command line filenames. */
852 if (dfi->pfilename)
853 free (CONST_CAST (char *, dfi->pfilename));
854 dfi->pfilename = xstrdup (ptr + 1);
855 break;
857 else
858 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
859 length, ptr, dfi->swtch);
860 found:;
861 ptr = end_ptr;
864 dfi->pstate = -1;
865 dfi->pflags |= flags;
867 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
868 known dumps. */
869 if (dfi->suffix == NULL)
870 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
872 return 1;
876 gcc::dump_manager::
877 dump_switch_p (const char *arg)
879 size_t i;
880 int any = 0;
882 for (i = TDI_none + 1; i != TDI_end; i++)
883 any |= dump_switch_p_1 (arg, &dump_files[i], false);
885 /* Don't glob if we got a hit already */
886 if (!any)
887 for (i = TDI_none + 1; i != TDI_end; i++)
888 any |= dump_switch_p_1 (arg, &dump_files[i], true);
890 for (i = 0; i < m_extra_dump_files_in_use; i++)
891 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
893 if (!any)
894 for (i = 0; i < m_extra_dump_files_in_use; i++)
895 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
898 return any;
901 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
902 and filename. Return non-zero if it is a recognized switch. */
904 static int
905 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
906 char **filename)
908 const char *option_value;
909 const char *ptr;
911 option_value = arg;
912 ptr = option_value;
914 *filename = NULL;
915 *flags = 0;
916 *optgroup_flags = 0;
918 if (!ptr)
919 return 1; /* Handle '-fopt-info' without any additional options. */
921 while (*ptr)
923 const struct dump_option_value_info *option_ptr;
924 const char *end_ptr;
925 const char *eq_ptr;
926 unsigned length;
928 while (*ptr == '-')
929 ptr++;
930 end_ptr = strchr (ptr, '-');
931 eq_ptr = strchr (ptr, '=');
933 if (eq_ptr && !end_ptr)
934 end_ptr = eq_ptr;
936 if (!end_ptr)
937 end_ptr = ptr + strlen (ptr);
938 length = end_ptr - ptr;
940 for (option_ptr = optinfo_verbosity_options; option_ptr->name;
941 option_ptr++)
942 if (strlen (option_ptr->name) == length
943 && !memcmp (option_ptr->name, ptr, length))
945 *flags |= option_ptr->value;
946 goto found;
949 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
950 if (strlen (option_ptr->name) == length
951 && !memcmp (option_ptr->name, ptr, length))
953 *optgroup_flags |= option_ptr->value;
954 goto found;
957 if (*ptr == '=')
959 /* Interpret rest of the argument as a dump filename. This
960 filename overrides other command line filenames. */
961 *filename = xstrdup (ptr + 1);
962 break;
964 else
966 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
967 length, ptr, arg);
968 return 0;
970 found:;
971 ptr = end_ptr;
974 return 1;
977 /* Return non-zero if ARG is a recognized switch for
978 -fopt-info. Return zero otherwise. */
981 opt_info_switch_p (const char *arg)
983 dump_flags_t flags;
984 int optgroup_flags;
985 char *filename;
986 static char *file_seen = NULL;
987 gcc::dump_manager *dumps = g->get_dumps ();
989 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
990 return 0;
992 if (!filename)
993 filename = xstrdup ("stderr");
995 /* Bail out if a different filename has been specified. */
996 if (file_seen && strcmp (file_seen, filename))
998 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
999 arg);
1000 return 1;
1003 file_seen = xstrdup (filename);
1004 if (!flags)
1005 flags = MSG_OPTIMIZED_LOCATIONS;
1006 if (!optgroup_flags)
1007 optgroup_flags = OPTGROUP_ALL;
1009 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
1012 /* Print basic block on the dump streams. */
1014 void
1015 dump_basic_block (int dump_kind, basic_block bb, int indent)
1017 if (dump_file && (dump_kind & pflags))
1018 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1019 if (alt_dump_file && (dump_kind & alt_flags))
1020 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1023 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1025 void
1026 dump_function (int phase, tree fn)
1028 FILE *stream;
1029 dump_flags_t flags;
1031 stream = dump_begin (phase, &flags);
1032 if (stream)
1034 dump_function_to_file (fn, stream, flags);
1035 dump_end (phase, stream);
1039 /* Print information from the combine pass on dump_file. */
1041 void
1042 print_combine_total_stats (void)
1044 if (dump_file)
1045 dump_combine_total_stats (dump_file);
1048 /* Enable RTL dump for all the RTL passes. */
1050 bool
1051 enable_rtl_dump_file (void)
1053 gcc::dump_manager *dumps = g->get_dumps ();
1054 int num_enabled =
1055 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1056 NULL);
1057 return num_enabled > 0;