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
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
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/>. */
22 #include "coretypes.h"
25 #include "gimple-pretty-print.h"
26 #include "diagnostic-core.h"
29 #include "profile-count.h"
31 #include "langhooks.h"
33 /* If non-NULL, return one past-the-end of the matching SUBPART of
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
>
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
},
94 {"details", (TDF_DETAILS
| MSG_OPTIMIZED_LOCATIONS
95 | MSG_MISSED_OPTIMIZATION
97 {"cselib", TDF_CSELIB
},
99 {"blocks", TDF_BLOCKS
},
101 {"lineno", TDF_LINENO
},
103 {"stmtaddr", TDF_STMTADDR
},
104 {"memsyms", TDF_MEMSYMS
},
106 {"alias", TDF_ALIAS
},
107 {"nouid", TDF_NOUID
},
108 {"enumerate_locals", TDF_ENUMERATE_LOCALS
},
110 {"gimple", TDF_GIMPLE
},
111 {"folding", TDF_FOLDING
},
112 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
113 {"missed", MSG_MISSED_OPTIMIZATION
},
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
))},
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
},
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
);
177 dump_register (const char *suffix
, const char *swtch
, const char *glob
,
178 dump_kind dkind
, optgroup_flags_t optgroup_flags
,
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;
190 m_extra_dump_files_alloced
*= 2;
191 m_extra_dump_files
= XRESIZEVEC (struct dump_file_info
,
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 ();
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. */
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
*
239 get_dump_file_info (int phase
) const
242 return &dump_files
[phase
];
243 else if ((size_t) (phase
- TDI_end
) >= m_extra_dump_files_in_use
)
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
*
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
];
265 /* Return the name of the dump file for the given phase.
266 The caller is responsible for calling free on the returned
268 If the dump is not enabled, returns NULL. */
272 get_dump_file_name (int phase
) const
274 struct dump_file_info
*dfi
;
276 if (phase
== TDI_none
)
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
287 If the dump is not enabled, returns NULL. */
291 get_dump_file_name (struct dump_file_info
*dfi
) const
297 if (dfi
->pstate
== 0)
300 /* If available, use the command line dump filename. */
302 return xstrdup (dfi
->pfilename
);
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)
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. */
324 dump_open (const char *filename
, bool trunc
)
326 if (strcmp ("stderr", filename
) == 0)
329 if (strcmp ("stdout", filename
) == 0
330 || strcmp ("-", filename
) == 0)
333 FILE *stream
= fopen (filename
, trunc
? "w" : "a");
336 error ("could not open dump file %qs: %m", filename
);
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. */
345 dump_open_alternate_stream (struct dump_file_info
*dfi
)
347 if (!dfi
->alt_filename
)
351 return dfi
->alt_stream
;
353 FILE *stream
= dump_open (dfi
->alt_filename
, dfi
->alt_state
< 0);
361 /* Print source location on DFILE if enabled. */
364 dump_loc (dump_flags_t dump_kind
, FILE *dfile
, source_location loc
)
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. */
383 dump_gimple_stmt (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
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. */
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. */
416 dump_generic_expr (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
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
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. */
450 dump_printf (dump_flags_t dump_kind
, const char *format
, ...)
452 if (dump_file
&& (dump_kind
& pflags
))
455 va_start (ap
, format
);
456 vfprintf (dump_file
, format
, ap
);
460 if (alt_dump_file
&& (dump_kind
& alt_flags
))
463 va_start (ap
, format
);
464 vfprintf (alt_dump_file
, format
, ap
);
469 /* Similar to dump_printf, except source location is also printed. */
472 dump_printf_loc (dump_flags_t dump_kind
, source_location loc
,
473 const char *format
, ...)
475 if (dump_file
&& (dump_kind
& pflags
))
478 dump_loc (dump_kind
, dump_file
, loc
);
479 va_start (ap
, format
);
480 vfprintf (dump_file
, format
, ap
);
484 if (alt_dump_file
&& (dump_kind
& alt_flags
))
487 dump_loc (dump_kind
, alt_dump_file
, loc
);
488 va_start (ap
, format
);
489 vfprintf (alt_dump_file
, format
, ap
);
494 /* Output VALUE in decimal to appropriate dump streams. */
496 template<unsigned int N
, typename C
>
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. */
523 dump_start (int phase
, dump_flags_t
*flag_ptr
)
527 struct dump_file_info
*dfi
;
529 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
532 dfi
= get_dump_file_info (phase
);
533 name
= get_dump_file_name (phase
);
536 stream
= dump_open (name
, dfi
->pstate
< 0);
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
);
552 dfi
->alt_stream
= stream
;
554 alt_dump_file
= dfi
->alt_stream
;
555 /* Initialize current -fopt-info flags. */
556 alt_flags
= dfi
->alt_flags
;
560 *flag_ptr
= dfi
->pflags
;
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. */
570 dump_finish (int phase
)
572 struct dump_file_info
*dfi
;
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
;
586 alt_dump_file
= NULL
;
587 dump_flags
= TDF_NONE
;
588 alt_flags
= 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. */
598 dump_begin (int phase
, dump_flags_t
*flag_ptr
)
600 return g
->get_dumps ()->dump_begin (phase
, flag_ptr
);
605 dump_begin (int phase
, dump_flags_t
*flag_ptr
)
608 struct dump_file_info
*dfi
;
611 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
614 name
= get_dump_file_name (phase
);
617 dfi
= get_dump_file_info (phase
);
619 stream
= dump_open (name
, dfi
->pstate
< 0);
625 *flag_ptr
= dfi
->pflags
;
627 /* Initialize current flags */
628 pflags
= dfi
->pflags
;
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
638 dump_phase_enabled_p (int phase
) const
640 if (phase
== TDI_tree_all
)
643 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
644 if (dump_files
[i
].pstate
|| dump_files
[i
].alt_state
)
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
)
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. */
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. */
671 dump_flag_name (int phase
)
673 return g
->get_dumps ()->dump_flag_name (phase
);
678 dump_flag_name (int phase
) const
680 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
684 /* Finish a tree dump for PHASE. STREAM is the stream created by
688 dump_end (int phase ATTRIBUTE_UNUSED
, FILE *stream
)
690 if (stream
!= stderr
&& stream
!= stdout
)
694 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
695 enabled tree dumps. */
699 dump_enable_all (dump_kind dkind
, dump_flags_t flags
, const char *filename
)
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
;
712 /* Override the existing 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
;
733 /* Override the existing 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
));
749 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
750 Enable dumps with FLAGS on FILENAME. Return the number of enabled
755 opt_info_enable_passes (optgroup_flags_t optgroup_flags
, dump_flags_t flags
,
756 const char *filename
)
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
;
771 /* Override the existing 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
;
789 /* Override the existing 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
));
800 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
801 relevant details in the dump_files array. */
805 dump_switch_p_1 (const char *arg
, struct dump_file_info
*dfi
, bool doglob
)
807 const char *option_value
;
811 if (doglob
&& !dfi
->glob
)
814 option_value
= skip_leading_substring (arg
, doglob
? dfi
->glob
: dfi
->swtch
);
818 if (*option_value
&& *option_value
!= '-' && *option_value
!= '=')
826 const struct kv_pair
<dump_flags_t
> *option_ptr
;
833 end_ptr
= strchr (ptr
, '-');
834 eq_ptr
= strchr (ptr
, '=');
836 if (eq_ptr
&& !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
;
853 /* Interpret rest of the argument as a dump filename. This
854 filename overrides other command line filenames. */
856 free (CONST_CAST (char *, dfi
->pfilename
));
857 dfi
->pfilename
= xstrdup (ptr
+ 1);
861 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
862 length
, ptr
, dfi
->swtch
);
868 dfi
->pflags
|= flags
;
870 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
872 if (dfi
->suffix
== NULL
)
873 dump_enable_all (dfi
->dkind
, dfi
->pflags
, dfi
->pfilename
);
880 dump_switch_p (const char *arg
)
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 */
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);
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);
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. */
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
;
919 *optgroup_flags
= OPTGROUP_NONE
;
922 return 1; /* Handle '-fopt-info' without any additional options. */
932 end_ptr
= strchr (ptr
, '-');
933 eq_ptr
= strchr (ptr
, '=');
935 if (eq_ptr
&& !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
;
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
;
962 /* Interpret rest of the argument as a dump filename. This
963 filename overrides other command line filenames. */
964 *filename
= xstrdup (ptr
+ 1);
969 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
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
)
987 optgroup_flags_t optgroup_flags
;
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
))
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%>",
1006 file_seen
= xstrdup (filename
);
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. */
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. */
1029 dump_function (int phase
, tree fn
)
1034 stream
= dump_begin (phase
, &flags
);
1037 dump_function_to_file (fn
, stream
, flags
);
1038 dump_end (phase
, stream
);
1042 /* Print information from the combine pass on dump_file. */
1045 print_combine_total_stats (void)
1048 dump_combine_total_stats (dump_file
);
1051 /* Enable RTL dump for all the RTL passes. */
1054 enable_rtl_dump_file (void)
1056 gcc::dump_manager
*dumps
= g
->get_dumps ();
1058 dumps
->dump_enable_all (DK_rtl
, dump_flags_t (TDF_DETAILS
) | TDF_BLOCKS
,
1060 return num_enabled
> 0;