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"
32 #include "backend.h" /* for gimple.h. */
33 #include "gimple.h" /* for dump_user_location_t ctor. */
34 #include "rtl.h" /* for dump_user_location_t ctor. */
37 /* If non-NULL, return one past-the-end of the matching SUBPART of
39 #define skip_leading_substring(whole, part) \
40 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
42 static dump_flags_t pflags
; /* current dump_flags */
43 static dump_flags_t alt_flags
; /* current opt_info flags */
45 static void dump_loc (dump_flags_t
, FILE *, source_location
);
46 static FILE *dump_open_alternate_stream (struct dump_file_info
*);
48 /* These are currently used for communicating between passes.
49 However, instead of accessing them directly, the passes can use
50 dump_printf () for dumps. */
51 FILE *dump_file
= NULL
;
52 FILE *alt_dump_file
= NULL
;
53 const char *dump_file_name
;
54 dump_flags_t dump_flags
;
56 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
57 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
58 OPTGROUP_NONE, 0, 0, num, false, false}
60 /* Table of tree dump switches. This must be consistent with the
61 TREE_DUMP_INDEX enumeration in dumpfile.h. */
62 static struct dump_file_info dump_files
[TDI_end
] =
64 DUMP_FILE_INFO (NULL
, NULL
, DK_none
, 0),
65 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa
, 0),
66 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa
, 0),
67 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa
, 0),
68 DUMP_FILE_INFO (".original", "tree-original", DK_tree
, 0),
69 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree
, 0),
70 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree
, 0),
71 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa
, 0),
72 #define FIRST_AUTO_NUMBERED_DUMP 1
73 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
75 DUMP_FILE_INFO (NULL
, "lang-all", DK_lang
, 0),
76 DUMP_FILE_INFO (NULL
, "tree-all", DK_tree
, 0),
77 DUMP_FILE_INFO (NULL
, "rtl-all", DK_rtl
, 0),
78 DUMP_FILE_INFO (NULL
, "ipa-all", DK_ipa
, 0),
81 /* Define a name->number mapping for a dump flag value. */
82 template <typename ValueType
>
85 const char *const name
; /* the name of the value */
86 const ValueType value
; /* the value of the name */
89 /* Table of dump options. This must be consistent with the TDF_* flags
90 in dumpfile.h and opt_info_options below. */
91 static const kv_pair
<dump_flags_t
> dump_options
[] =
93 {"address", TDF_ADDRESS
},
94 {"asmname", TDF_ASMNAME
},
98 {"details", (TDF_DETAILS
| MSG_OPTIMIZED_LOCATIONS
99 | MSG_MISSED_OPTIMIZATION
101 {"cselib", TDF_CSELIB
},
102 {"stats", TDF_STATS
},
103 {"blocks", TDF_BLOCKS
},
105 {"lineno", TDF_LINENO
},
107 {"stmtaddr", TDF_STMTADDR
},
108 {"memsyms", TDF_MEMSYMS
},
110 {"alias", TDF_ALIAS
},
111 {"nouid", TDF_NOUID
},
112 {"enumerate_locals", TDF_ENUMERATE_LOCALS
},
114 {"gimple", TDF_GIMPLE
},
115 {"folding", TDF_FOLDING
},
116 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
117 {"missed", MSG_MISSED_OPTIMIZATION
},
120 {"all", dump_flags_t (~(TDF_RAW
| TDF_SLIM
| TDF_LINENO
| TDF_GRAPH
121 | TDF_STMTADDR
| TDF_RHS_ONLY
| TDF_NOUID
122 | TDF_ENUMERATE_LOCALS
| TDF_SCEV
| TDF_GIMPLE
))},
126 /* A subset of the dump_options table which is used for -fopt-info
127 types. This must be consistent with the MSG_* flags in dumpfile.h.
129 static const kv_pair
<dump_flags_t
> optinfo_verbosity_options
[] =
131 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
132 {"missed", MSG_MISSED_OPTIMIZATION
},
138 /* Flags used for -fopt-info groups. */
139 static const kv_pair
<optgroup_flags_t
> optgroup_options
[] =
141 {"ipa", OPTGROUP_IPA
},
142 {"loop", OPTGROUP_LOOP
},
143 {"inline", OPTGROUP_INLINE
},
144 {"omp", OPTGROUP_OMP
},
145 {"vec", OPTGROUP_VEC
},
146 {"optall", OPTGROUP_ALL
},
147 {NULL
, OPTGROUP_NONE
}
150 gcc::dump_manager::dump_manager ():
151 m_next_dump (FIRST_AUTO_NUMBERED_DUMP
),
152 m_extra_dump_files (NULL
),
153 m_extra_dump_files_in_use (0),
154 m_extra_dump_files_alloced (0)
158 gcc::dump_manager::~dump_manager ()
160 for (size_t i
= 0; i
< m_extra_dump_files_in_use
; i
++)
162 dump_file_info
*dfi
= &m_extra_dump_files
[i
];
163 /* suffix, swtch, glob are statically allocated for the entries
164 in dump_files, and for statistics, but are dynamically allocated
165 for those for passes. */
166 if (dfi
->owns_strings
)
168 XDELETEVEC (const_cast <char *> (dfi
->suffix
));
169 XDELETEVEC (const_cast <char *> (dfi
->swtch
));
170 XDELETEVEC (const_cast <char *> (dfi
->glob
));
172 /* These, if non-NULL, are always dynamically allocated. */
173 XDELETEVEC (const_cast <char *> (dfi
->pfilename
));
174 XDELETEVEC (const_cast <char *> (dfi
->alt_filename
));
176 XDELETEVEC (m_extra_dump_files
);
181 dump_register (const char *suffix
, const char *swtch
, const char *glob
,
182 dump_kind dkind
, optgroup_flags_t optgroup_flags
,
185 int num
= m_next_dump
++;
187 size_t count
= m_extra_dump_files_in_use
++;
189 if (count
>= m_extra_dump_files_alloced
)
191 if (m_extra_dump_files_alloced
== 0)
192 m_extra_dump_files_alloced
= 512;
194 m_extra_dump_files_alloced
*= 2;
195 m_extra_dump_files
= XRESIZEVEC (struct dump_file_info
,
197 m_extra_dump_files_alloced
);
199 /* Construct a new object in the space allocated above. */
200 new (m_extra_dump_files
+ count
) dump_file_info ();
204 /* Zero out the already constructed object. */
205 m_extra_dump_files
[count
] = dump_file_info ();
208 m_extra_dump_files
[count
].suffix
= suffix
;
209 m_extra_dump_files
[count
].swtch
= swtch
;
210 m_extra_dump_files
[count
].glob
= glob
;
211 m_extra_dump_files
[count
].dkind
= dkind
;
212 m_extra_dump_files
[count
].optgroup_flags
= optgroup_flags
;
213 m_extra_dump_files
[count
].num
= num
;
214 m_extra_dump_files
[count
].owns_strings
= take_ownership
;
216 return count
+ TDI_end
;
220 /* Allow languages and middle-end to register their dumps before the
221 optimization passes. */
227 lang_hooks
.register_dumps (this);
228 /* If this assert fails, some FE registered more than
229 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
230 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
231 gcc_assert (m_next_dump
<= FIRST_ME_AUTO_NUMBERED_DUMP
);
232 m_next_dump
= FIRST_ME_AUTO_NUMBERED_DUMP
;
233 dump_files
[TDI_original
].num
= m_next_dump
++;
234 dump_files
[TDI_gimple
].num
= m_next_dump
++;
235 dump_files
[TDI_nested
].num
= m_next_dump
++;
239 /* Return the dump_file_info for the given phase. */
241 struct dump_file_info
*
243 get_dump_file_info (int phase
) const
246 return &dump_files
[phase
];
247 else if ((size_t) (phase
- TDI_end
) >= m_extra_dump_files_in_use
)
250 return m_extra_dump_files
+ (phase
- TDI_end
);
253 /* Locate the dump_file_info with swtch equal to SWTCH,
254 or return NULL if no such dump_file_info exists. */
256 struct dump_file_info
*
258 get_dump_file_info_by_switch (const char *swtch
) const
260 for (unsigned i
= 0; i
< m_extra_dump_files_in_use
; i
++)
261 if (strcmp (m_extra_dump_files
[i
].swtch
, swtch
) == 0)
262 return &m_extra_dump_files
[i
];
269 /* Return the name of the dump file for the given phase.
270 The caller is responsible for calling free on the returned
272 If the dump is not enabled, returns NULL. */
276 get_dump_file_name (int phase
) const
278 struct dump_file_info
*dfi
;
280 if (phase
== TDI_none
)
283 dfi
= get_dump_file_info (phase
);
285 return get_dump_file_name (dfi
);
288 /* Return the name of the dump file for the given dump_file_info.
289 The caller is responsible for calling free on the returned
291 If the dump is not enabled, returns NULL. */
295 get_dump_file_name (struct dump_file_info
*dfi
) const
301 if (dfi
->pstate
== 0)
304 /* If available, use the command line dump filename. */
306 return xstrdup (dfi
->pfilename
);
312 /* (null), LANG, TREE, RTL, IPA. */
313 char suffix
= " ltri"[dfi
->dkind
];
315 if (snprintf (dump_id
, sizeof (dump_id
), ".%03d%c", dfi
->num
, suffix
) < 0)
319 return concat (dump_base_name
, dump_id
, dfi
->suffix
, NULL
);
322 /* Open a dump file called FILENAME. Some filenames are special and
323 refer to the standard streams. TRUNC indicates whether this is the
324 first open (so the file should be truncated, rather than appended).
325 An error message is emitted in the event of failure. */
328 dump_open (const char *filename
, bool trunc
)
330 if (strcmp ("stderr", filename
) == 0)
333 if (strcmp ("stdout", filename
) == 0
334 || strcmp ("-", filename
) == 0)
337 FILE *stream
= fopen (filename
, trunc
? "w" : "a");
340 error ("could not open dump file %qs: %m", filename
);
344 /* For a given DFI, open an alternate dump filename (which could also
345 be a standard stream such as stdout/stderr). If the alternate dump
346 file cannot be opened, return NULL. */
349 dump_open_alternate_stream (struct dump_file_info
*dfi
)
351 if (!dfi
->alt_filename
)
355 return dfi
->alt_stream
;
357 FILE *stream
= dump_open (dfi
->alt_filename
, dfi
->alt_state
< 0);
365 /* Construct a dump_user_location_t from STMT (using its location and
368 dump_user_location_t::dump_user_location_t (gimple
*stmt
)
369 : m_count (), m_loc (UNKNOWN_LOCATION
)
374 m_count
= stmt
->bb
->count
;
375 m_loc
= gimple_location (stmt
);
379 /* Construct a dump_user_location_t from an RTL instruction (using its
380 location and hotness). */
382 dump_user_location_t::dump_user_location_t (rtx_insn
*insn
)
383 : m_count (), m_loc (UNKNOWN_LOCATION
)
387 basic_block bb
= BLOCK_FOR_INSN (insn
);
390 m_loc
= INSN_LOCATION (insn
);
394 /* Construct from a function declaration. This one requires spelling out
395 to avoid accidentally constructing from other kinds of tree. */
398 dump_user_location_t::from_function_decl (tree fndecl
)
402 // FIXME: profile count for function?
403 return dump_user_location_t (profile_count (),
404 DECL_SOURCE_LOCATION (fndecl
));
407 /* Print source location on DFILE if enabled. */
410 dump_loc (dump_flags_t dump_kind
, FILE *dfile
, source_location loc
)
414 if (LOCATION_LOCUS (loc
) > BUILTINS_LOCATION
)
415 fprintf (dfile
, "%s:%d:%d: note: ", LOCATION_FILE (loc
),
416 LOCATION_LINE (loc
), LOCATION_COLUMN (loc
));
417 else if (current_function_decl
)
418 fprintf (dfile
, "%s:%d:%d: note: ",
419 DECL_SOURCE_FILE (current_function_decl
),
420 DECL_SOURCE_LINE (current_function_decl
),
421 DECL_SOURCE_COLUMN (current_function_decl
));
425 /* Dump gimple statement GS with SPC indentation spaces and
426 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
429 dump_gimple_stmt (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
432 if (dump_file
&& (dump_kind
& pflags
))
433 print_gimple_stmt (dump_file
, gs
, spc
, dump_flags
| extra_dump_flags
);
435 if (alt_dump_file
&& (dump_kind
& alt_flags
))
436 print_gimple_stmt (alt_dump_file
, gs
, spc
, dump_flags
| extra_dump_flags
);
439 /* Similar to dump_gimple_stmt, except additionally print source location. */
442 dump_gimple_stmt_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
443 dump_flags_t extra_dump_flags
, gimple
*gs
, int spc
)
445 location_t srcloc
= loc
.get_location_t ();
446 if (dump_file
&& (dump_kind
& pflags
))
448 dump_loc (dump_kind
, dump_file
, srcloc
);
449 print_gimple_stmt (dump_file
, gs
, spc
, dump_flags
| extra_dump_flags
);
452 if (alt_dump_file
&& (dump_kind
& alt_flags
))
454 dump_loc (dump_kind
, alt_dump_file
, srcloc
);
455 print_gimple_stmt (alt_dump_file
, gs
, spc
, dump_flags
| extra_dump_flags
);
459 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
460 DUMP_KIND is enabled. */
463 dump_generic_expr (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
466 if (dump_file
&& (dump_kind
& pflags
))
467 print_generic_expr (dump_file
, t
, dump_flags
| extra_dump_flags
);
469 if (alt_dump_file
&& (dump_kind
& alt_flags
))
470 print_generic_expr (alt_dump_file
, t
, dump_flags
| extra_dump_flags
);
473 /* Output a formatted message using FORMAT on appropriate dump streams. */
476 dump_printf (dump_flags_t dump_kind
, const char *format
, ...)
478 if (dump_file
&& (dump_kind
& pflags
))
481 va_start (ap
, format
);
482 vfprintf (dump_file
, format
, ap
);
486 if (alt_dump_file
&& (dump_kind
& alt_flags
))
489 va_start (ap
, format
);
490 vfprintf (alt_dump_file
, format
, ap
);
495 /* Similar to dump_printf, except source location is also printed. */
498 dump_printf_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
499 const char *format
, ...)
501 location_t srcloc
= loc
.get_location_t ();
502 if (dump_file
&& (dump_kind
& pflags
))
505 dump_loc (dump_kind
, dump_file
, srcloc
);
506 va_start (ap
, format
);
507 vfprintf (dump_file
, format
, ap
);
511 if (alt_dump_file
&& (dump_kind
& alt_flags
))
514 dump_loc (dump_kind
, alt_dump_file
, srcloc
);
515 va_start (ap
, format
);
516 vfprintf (alt_dump_file
, format
, ap
);
521 /* Output VALUE in decimal to appropriate dump streams. */
523 template<unsigned int N
, typename C
>
525 dump_dec (dump_flags_t dump_kind
, const poly_int
<N
, C
> &value
)
527 STATIC_ASSERT (poly_coeff_traits
<C
>::signedness
>= 0);
528 signop sgn
= poly_coeff_traits
<C
>::signedness
? SIGNED
: UNSIGNED
;
529 if (dump_file
&& (dump_kind
& pflags
))
530 print_dec (value
, dump_file
, sgn
);
532 if (alt_dump_file
&& (dump_kind
& alt_flags
))
533 print_dec (value
, alt_dump_file
, sgn
);
536 template void dump_dec (dump_flags_t
, const poly_uint16
&);
537 template void dump_dec (dump_flags_t
, const poly_int64
&);
538 template void dump_dec (dump_flags_t
, const poly_uint64
&);
539 template void dump_dec (dump_flags_t
, const poly_offset_int
&);
540 template void dump_dec (dump_flags_t
, const poly_widest_int
&);
542 /* Start a dump for PHASE. Store user-supplied dump flags in
543 *FLAG_PTR. Return the number of streams opened. Set globals
544 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
545 set dump_flags appropriately for both pass dump stream and
546 -fopt-info stream. */
550 dump_start (int phase
, dump_flags_t
*flag_ptr
)
554 struct dump_file_info
*dfi
;
556 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
559 dfi
= get_dump_file_info (phase
);
560 name
= get_dump_file_name (phase
);
563 stream
= dump_open (name
, dfi
->pstate
< 0);
570 dfi
->pstream
= stream
;
571 dump_file
= dfi
->pstream
;
572 /* Initialize current dump flags. */
573 pflags
= dfi
->pflags
;
576 stream
= dump_open_alternate_stream (dfi
);
579 dfi
->alt_stream
= stream
;
581 alt_dump_file
= dfi
->alt_stream
;
582 /* Initialize current -fopt-info flags. */
583 alt_flags
= dfi
->alt_flags
;
587 *flag_ptr
= dfi
->pflags
;
592 /* Finish a tree dump for PHASE and close associated dump streams. Also
593 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
597 dump_finish (int phase
)
599 struct dump_file_info
*dfi
;
603 dfi
= get_dump_file_info (phase
);
604 if (dfi
->pstream
&& dfi
->pstream
!= stdout
&& dfi
->pstream
!= stderr
)
605 fclose (dfi
->pstream
);
607 if (dfi
->alt_stream
&& dfi
->alt_stream
!= stdout
&& dfi
->alt_stream
!= stderr
)
608 fclose (dfi
->alt_stream
);
610 dfi
->alt_stream
= NULL
;
613 alt_dump_file
= NULL
;
614 dump_flags
= TDF_NONE
;
615 alt_flags
= TDF_NONE
;
619 /* Begin a tree dump for PHASE. Stores any user supplied flag in
620 *FLAG_PTR and returns a stream to write to. If the dump is not
621 enabled, returns NULL.
622 Multiple calls will reopen and append to the dump file. */
625 dump_begin (int phase
, dump_flags_t
*flag_ptr
)
627 return g
->get_dumps ()->dump_begin (phase
, flag_ptr
);
632 dump_begin (int phase
, dump_flags_t
*flag_ptr
)
635 struct dump_file_info
*dfi
;
638 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
641 name
= get_dump_file_name (phase
);
644 dfi
= get_dump_file_info (phase
);
646 stream
= dump_open (name
, dfi
->pstate
< 0);
652 *flag_ptr
= dfi
->pflags
;
654 /* Initialize current flags */
655 pflags
= dfi
->pflags
;
659 /* Returns nonzero if dump PHASE is enabled for at least one stream.
660 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
665 dump_phase_enabled_p (int phase
) const
667 if (phase
== TDI_tree_all
)
670 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
671 if (dump_files
[i
].pstate
|| dump_files
[i
].alt_state
)
673 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
674 if (m_extra_dump_files
[i
].pstate
|| m_extra_dump_files
[i
].alt_state
)
680 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
681 return dfi
->pstate
|| dfi
->alt_state
;
685 /* Returns nonzero if tree dump PHASE has been initialized. */
689 dump_initialized_p (int phase
) const
691 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
692 return dfi
->pstate
> 0 || dfi
->alt_state
> 0;
695 /* Returns the switch name of PHASE. */
698 dump_flag_name (int phase
)
700 return g
->get_dumps ()->dump_flag_name (phase
);
705 dump_flag_name (int phase
) const
707 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
711 /* Finish a tree dump for PHASE. STREAM is the stream created by
715 dump_end (int phase ATTRIBUTE_UNUSED
, FILE *stream
)
717 if (stream
!= stderr
&& stream
!= stdout
)
721 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
722 enabled tree dumps. */
726 dump_enable_all (dump_kind dkind
, dump_flags_t flags
, const char *filename
)
731 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
733 if ((dump_files
[i
].dkind
== dkind
))
735 const char *old_filename
= dump_files
[i
].pfilename
;
736 dump_files
[i
].pstate
= -1;
737 dump_files
[i
].pflags
|= flags
;
739 /* Override the existing filename. */
742 dump_files
[i
].pfilename
= xstrdup (filename
);
743 /* Since it is a command-line provided file, which is
744 common to all the phases, use it in append mode. */
745 dump_files
[i
].pstate
= 1;
747 if (old_filename
&& filename
!= old_filename
)
748 free (CONST_CAST (char *, old_filename
));
752 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
754 if ((m_extra_dump_files
[i
].dkind
== dkind
))
756 const char *old_filename
= m_extra_dump_files
[i
].pfilename
;
757 m_extra_dump_files
[i
].pstate
= -1;
758 m_extra_dump_files
[i
].pflags
|= flags
;
760 /* Override the existing filename. */
763 m_extra_dump_files
[i
].pfilename
= xstrdup (filename
);
764 /* Since it is a command-line provided file, which is
765 common to all the phases, use it in append mode. */
766 m_extra_dump_files
[i
].pstate
= 1;
768 if (old_filename
&& filename
!= old_filename
)
769 free (CONST_CAST (char *, old_filename
));
776 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
777 Enable dumps with FLAGS on FILENAME. Return the number of enabled
782 opt_info_enable_passes (optgroup_flags_t optgroup_flags
, dump_flags_t flags
,
783 const char *filename
)
788 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
790 if ((dump_files
[i
].optgroup_flags
& optgroup_flags
))
792 const char *old_filename
= dump_files
[i
].alt_filename
;
793 /* Since this file is shared among different passes, it
794 should be opened in append mode. */
795 dump_files
[i
].alt_state
= 1;
796 dump_files
[i
].alt_flags
|= flags
;
798 /* Override the existing filename. */
800 dump_files
[i
].alt_filename
= xstrdup (filename
);
801 if (old_filename
&& filename
!= old_filename
)
802 free (CONST_CAST (char *, old_filename
));
806 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
808 if ((m_extra_dump_files
[i
].optgroup_flags
& optgroup_flags
))
810 const char *old_filename
= m_extra_dump_files
[i
].alt_filename
;
811 /* Since this file is shared among different passes, it
812 should be opened in append mode. */
813 m_extra_dump_files
[i
].alt_state
= 1;
814 m_extra_dump_files
[i
].alt_flags
|= flags
;
816 /* Override the existing filename. */
818 m_extra_dump_files
[i
].alt_filename
= xstrdup (filename
);
819 if (old_filename
&& filename
!= old_filename
)
820 free (CONST_CAST (char *, old_filename
));
827 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
828 relevant details in the dump_files array. */
832 dump_switch_p_1 (const char *arg
, struct dump_file_info
*dfi
, bool doglob
)
834 const char *option_value
;
838 if (doglob
&& !dfi
->glob
)
841 option_value
= skip_leading_substring (arg
, doglob
? dfi
->glob
: dfi
->swtch
);
845 if (*option_value
&& *option_value
!= '-' && *option_value
!= '=')
853 const struct kv_pair
<dump_flags_t
> *option_ptr
;
860 end_ptr
= strchr (ptr
, '-');
861 eq_ptr
= strchr (ptr
, '=');
863 if (eq_ptr
&& !end_ptr
)
867 end_ptr
= ptr
+ strlen (ptr
);
868 length
= end_ptr
- ptr
;
870 for (option_ptr
= dump_options
; option_ptr
->name
; option_ptr
++)
871 if (strlen (option_ptr
->name
) == length
872 && !memcmp (option_ptr
->name
, ptr
, length
))
874 flags
|= option_ptr
->value
;
880 /* Interpret rest of the argument as a dump filename. This
881 filename overrides other command line filenames. */
883 free (CONST_CAST (char *, dfi
->pfilename
));
884 dfi
->pfilename
= xstrdup (ptr
+ 1);
888 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
889 length
, ptr
, dfi
->swtch
);
895 dfi
->pflags
|= flags
;
897 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
899 if (dfi
->suffix
== NULL
)
900 dump_enable_all (dfi
->dkind
, dfi
->pflags
, dfi
->pfilename
);
907 dump_switch_p (const char *arg
)
912 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
913 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], false);
915 /* Don't glob if we got a hit already */
917 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
918 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], true);
920 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
921 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], false);
924 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
925 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], true);
931 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
932 and filename. Return non-zero if it is a recognized switch. */
935 opt_info_switch_p_1 (const char *arg
, dump_flags_t
*flags
,
936 optgroup_flags_t
*optgroup_flags
, char **filename
)
938 const char *option_value
;
946 *optgroup_flags
= OPTGROUP_NONE
;
949 return 1; /* Handle '-fopt-info' without any additional options. */
959 end_ptr
= strchr (ptr
, '-');
960 eq_ptr
= strchr (ptr
, '=');
962 if (eq_ptr
&& !end_ptr
)
966 end_ptr
= ptr
+ strlen (ptr
);
967 length
= end_ptr
- ptr
;
969 for (const kv_pair
<dump_flags_t
> *option_ptr
= optinfo_verbosity_options
;
970 option_ptr
->name
; option_ptr
++)
971 if (strlen (option_ptr
->name
) == length
972 && !memcmp (option_ptr
->name
, ptr
, length
))
974 *flags
|= option_ptr
->value
;
978 for (const kv_pair
<optgroup_flags_t
> *option_ptr
= optgroup_options
;
979 option_ptr
->name
; option_ptr
++)
980 if (strlen (option_ptr
->name
) == length
981 && !memcmp (option_ptr
->name
, ptr
, length
))
983 *optgroup_flags
|= option_ptr
->value
;
989 /* Interpret rest of the argument as a dump filename. This
990 filename overrides other command line filenames. */
991 *filename
= xstrdup (ptr
+ 1);
996 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1007 /* Return non-zero if ARG is a recognized switch for
1008 -fopt-info. Return zero otherwise. */
1011 opt_info_switch_p (const char *arg
)
1014 optgroup_flags_t optgroup_flags
;
1016 static char *file_seen
= NULL
;
1017 gcc::dump_manager
*dumps
= g
->get_dumps ();
1019 if (!opt_info_switch_p_1 (arg
, &flags
, &optgroup_flags
, &filename
))
1023 filename
= xstrdup ("stderr");
1025 /* Bail out if a different filename has been specified. */
1026 if (file_seen
&& strcmp (file_seen
, filename
))
1028 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1033 file_seen
= xstrdup (filename
);
1035 flags
= MSG_OPTIMIZED_LOCATIONS
;
1036 if (!optgroup_flags
)
1037 optgroup_flags
= OPTGROUP_ALL
;
1039 return dumps
->opt_info_enable_passes (optgroup_flags
, flags
, filename
);
1042 /* Print basic block on the dump streams. */
1045 dump_basic_block (dump_flags_t dump_kind
, basic_block bb
, int indent
)
1047 if (dump_file
&& (dump_kind
& pflags
))
1048 dump_bb (dump_file
, bb
, indent
, TDF_DETAILS
);
1049 if (alt_dump_file
&& (dump_kind
& alt_flags
))
1050 dump_bb (alt_dump_file
, bb
, indent
, TDF_DETAILS
);
1053 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1056 dump_function (int phase
, tree fn
)
1061 stream
= dump_begin (phase
, &flags
);
1064 dump_function_to_file (fn
, stream
, flags
);
1065 dump_end (phase
, stream
);
1069 /* Print information from the combine pass on dump_file. */
1072 print_combine_total_stats (void)
1075 dump_combine_total_stats (dump_file
);
1078 /* Enable RTL dump for all the RTL passes. */
1081 enable_rtl_dump_file (void)
1083 gcc::dump_manager
*dumps
= g
->get_dumps ();
1085 dumps
->dump_enable_all (DK_rtl
, dump_flags_t (TDF_DETAILS
) | TDF_BLOCKS
,
1087 return num_enabled
> 0;
1092 namespace selftest
{
1094 /* Verify that the dump_location_t constructors capture the source location
1095 at which they were called (provided that the build compiler is sufficiently
1099 test_impl_location ()
1101 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
1104 dump_location_t loc
;
1105 const int expected_line
= __LINE__
- 1;
1106 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1107 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1110 /* Constructing from a gimple. */
1112 dump_location_t
loc ((gimple
*)NULL
);
1113 const int expected_line
= __LINE__
- 1;
1114 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1115 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1118 /* Constructing from an rtx_insn. */
1120 dump_location_t
loc ((rtx_insn
*)NULL
);
1121 const int expected_line
= __LINE__
- 1;
1122 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1123 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1128 /* Run all of the selftests within this file. */
1133 test_impl_location ();
1136 } // namespace selftest
1138 #endif /* CHECKING_P */