1 /* Dump infrastructure for optimizations and intermediate representation.
2 Copyright (C) 2012-2020 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 #include "dump-context.h"
39 #include "tree-pass.h" /* for "current_pass". */
40 #include "optinfo-emit-json.h"
41 #include "stringpool.h" /* for get_identifier. */
42 #include "spellcheck.h"
44 /* If non-NULL, return one past-the-end of the matching SUBPART of
46 #define skip_leading_substring(whole, part) \
47 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
49 static dump_flags_t pflags
; /* current dump_flags */
51 static void dump_loc (dump_flags_t
, FILE *, location_t
);
53 /* Current -fopt-info output stream, if any, and flags. */
54 static FILE *alt_dump_file
= NULL
;
55 static dump_flags_t alt_flags
;
57 static FILE *dump_open_alternate_stream (struct dump_file_info
*);
59 /* These are currently used for communicating between passes.
60 However, instead of accessing them directly, the passes can use
61 dump_printf () for dumps. */
62 FILE *dump_file
= NULL
;
63 const char *dump_file_name
;
64 dump_flags_t dump_flags
;
65 bool dumps_are_enabled
= false;
68 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
72 set_dump_file (FILE *new_dump_file
)
74 dumpfile_ensure_any_optinfo_are_flushed ();
75 dump_file
= new_dump_file
;
76 dump_context::get ().refresh_dumps_are_enabled ();
79 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
83 set_alt_dump_file (FILE *new_alt_dump_file
)
85 dumpfile_ensure_any_optinfo_are_flushed ();
86 alt_dump_file
= new_alt_dump_file
;
87 dump_context::get ().refresh_dumps_are_enabled ();
90 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
91 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
92 OPTGROUP_NONE, 0, 0, num, false, false}
94 /* Table of tree dump switches. This must be consistent with the
95 TREE_DUMP_INDEX enumeration in dumpfile.h. */
96 static struct dump_file_info dump_files
[TDI_end
] =
98 DUMP_FILE_INFO (NULL
, NULL
, DK_none
, 0),
99 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa
, 0),
100 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa
, 0),
101 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa
, 0),
102 DUMP_FILE_INFO (".original", "tree-original", DK_tree
, 0),
103 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree
, 0),
104 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree
, 0),
105 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa
, 0),
106 #define FIRST_AUTO_NUMBERED_DUMP 1
107 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
109 DUMP_FILE_INFO (NULL
, "lang-all", DK_lang
, 0),
110 DUMP_FILE_INFO (NULL
, "tree-all", DK_tree
, 0),
111 DUMP_FILE_INFO (NULL
, "rtl-all", DK_rtl
, 0),
112 DUMP_FILE_INFO (NULL
, "ipa-all", DK_ipa
, 0),
115 /* Table of dump options. This must be consistent with the TDF_* flags
116 in dumpfile.h and opt_info_options below. */
117 static const kv_pair
<dump_flags_t
> dump_options
[] =
120 {"address", TDF_ADDRESS
},
121 {"asmname", TDF_ASMNAME
},
124 {"graph", TDF_GRAPH
},
125 {"details", (TDF_DETAILS
| MSG_OPTIMIZED_LOCATIONS
126 | MSG_MISSED_OPTIMIZATION
128 {"cselib", TDF_CSELIB
},
129 {"stats", TDF_STATS
},
130 {"blocks", TDF_BLOCKS
},
132 {"lineno", TDF_LINENO
},
134 {"stmtaddr", TDF_STMTADDR
},
135 {"memsyms", TDF_MEMSYMS
},
137 {"alias", TDF_ALIAS
},
138 {"nouid", TDF_NOUID
},
139 {"enumerate_locals", TDF_ENUMERATE_LOCALS
},
141 {"gimple", TDF_GIMPLE
},
142 {"folding", TDF_FOLDING
},
143 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
144 {"missed", MSG_MISSED_OPTIMIZATION
},
146 {"optall", MSG_ALL_KINDS
},
147 {"all", dump_flags_t (TDF_ALL_VALUES
148 & ~(TDF_RAW
| TDF_SLIM
| TDF_LINENO
| TDF_GRAPH
149 | TDF_STMTADDR
| TDF_RHS_ONLY
| TDF_NOUID
150 | TDF_ENUMERATE_LOCALS
| TDF_SCEV
| TDF_GIMPLE
))},
154 /* A subset of the dump_options table which is used for -fopt-info
155 types. This must be consistent with the MSG_* flags in dumpfile.h.
157 static const kv_pair
<dump_flags_t
> optinfo_verbosity_options
[] =
159 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
160 {"missed", MSG_MISSED_OPTIMIZATION
},
162 {"all", MSG_ALL_KINDS
},
163 {"internals", MSG_PRIORITY_INTERNALS
},
167 /* Flags used for -fopt-info groups. */
168 const kv_pair
<optgroup_flags_t
> optgroup_options
[] =
170 {"ipa", OPTGROUP_IPA
},
171 {"loop", OPTGROUP_LOOP
},
172 {"inline", OPTGROUP_INLINE
},
173 {"omp", OPTGROUP_OMP
},
174 {"vec", OPTGROUP_VEC
},
175 {"optall", OPTGROUP_ALL
},
176 {NULL
, OPTGROUP_NONE
}
179 gcc::dump_manager::dump_manager ():
180 m_next_dump (FIRST_AUTO_NUMBERED_DUMP
),
181 m_extra_dump_files (NULL
),
182 m_extra_dump_files_in_use (0),
183 m_extra_dump_files_alloced (0),
184 m_optgroup_flags (OPTGROUP_NONE
),
185 m_optinfo_flags (TDF_NONE
),
186 m_optinfo_filename (NULL
)
190 gcc::dump_manager::~dump_manager ()
192 free (m_optinfo_filename
);
193 for (size_t i
= 0; i
< m_extra_dump_files_in_use
; i
++)
195 dump_file_info
*dfi
= &m_extra_dump_files
[i
];
196 /* suffix, swtch, glob are statically allocated for the entries
197 in dump_files, and for statistics, but are dynamically allocated
198 for those for passes. */
199 if (dfi
->owns_strings
)
201 XDELETEVEC (const_cast <char *> (dfi
->suffix
));
202 XDELETEVEC (const_cast <char *> (dfi
->swtch
));
203 XDELETEVEC (const_cast <char *> (dfi
->glob
));
205 /* These, if non-NULL, are always dynamically allocated. */
206 XDELETEVEC (const_cast <char *> (dfi
->pfilename
));
207 XDELETEVEC (const_cast <char *> (dfi
->alt_filename
));
209 XDELETEVEC (m_extra_dump_files
);
214 dump_register (const char *suffix
, const char *swtch
, const char *glob
,
215 dump_kind dkind
, optgroup_flags_t optgroup_flags
,
218 int num
= m_next_dump
++;
220 size_t count
= m_extra_dump_files_in_use
++;
222 if (count
>= m_extra_dump_files_alloced
)
224 if (m_extra_dump_files_alloced
== 0)
225 m_extra_dump_files_alloced
= 512;
227 m_extra_dump_files_alloced
*= 2;
228 m_extra_dump_files
= XRESIZEVEC (struct dump_file_info
,
230 m_extra_dump_files_alloced
);
232 /* Construct a new object in the space allocated above. */
233 new (m_extra_dump_files
+ count
) dump_file_info ();
237 /* Zero out the already constructed object. */
238 m_extra_dump_files
[count
] = dump_file_info ();
241 m_extra_dump_files
[count
].suffix
= suffix
;
242 m_extra_dump_files
[count
].swtch
= swtch
;
243 m_extra_dump_files
[count
].glob
= glob
;
244 m_extra_dump_files
[count
].dkind
= dkind
;
245 m_extra_dump_files
[count
].optgroup_flags
= optgroup_flags
;
246 m_extra_dump_files
[count
].num
= num
;
247 m_extra_dump_files
[count
].owns_strings
= take_ownership
;
249 return count
+ TDI_end
;
253 /* Allow languages and middle-end to register their dumps before the
254 optimization passes. */
260 lang_hooks
.register_dumps (this);
261 /* If this assert fails, some FE registered more than
262 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
263 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
264 gcc_assert (m_next_dump
<= FIRST_ME_AUTO_NUMBERED_DUMP
);
265 m_next_dump
= FIRST_ME_AUTO_NUMBERED_DUMP
;
266 dump_files
[TDI_original
].num
= m_next_dump
++;
267 dump_files
[TDI_gimple
].num
= m_next_dump
++;
268 dump_files
[TDI_nested
].num
= m_next_dump
++;
272 /* Return the dump_file_info for the given phase. */
274 struct dump_file_info
*
276 get_dump_file_info (int phase
) const
279 return &dump_files
[phase
];
280 else if ((size_t) (phase
- TDI_end
) >= m_extra_dump_files_in_use
)
283 return m_extra_dump_files
+ (phase
- TDI_end
);
286 /* Locate the dump_file_info with swtch equal to SWTCH,
287 or return NULL if no such dump_file_info exists. */
289 struct dump_file_info
*
291 get_dump_file_info_by_switch (const char *swtch
) const
293 for (unsigned i
= 0; i
< m_extra_dump_files_in_use
; i
++)
294 if (strcmp (m_extra_dump_files
[i
].swtch
, swtch
) == 0)
295 return &m_extra_dump_files
[i
];
302 /* Return the name of the dump file for the given phase.
303 The caller is responsible for calling free on the returned
305 If the dump is not enabled, returns NULL. */
309 get_dump_file_name (int phase
, int part
) const
311 struct dump_file_info
*dfi
;
313 if (phase
== TDI_none
)
316 dfi
= get_dump_file_info (phase
);
318 return get_dump_file_name (dfi
, part
);
321 /* Return the name of the dump file for the given dump_file_info.
322 The caller is responsible for calling free on the returned
324 If the dump is not enabled, returns NULL. */
328 get_dump_file_name (struct dump_file_info
*dfi
, int part
) const
334 if (dfi
->pstate
== 0)
337 /* If available, use the command line dump filename. */
339 return xstrdup (dfi
->pfilename
);
345 /* (null), LANG, TREE, RTL, IPA. */
346 char suffix
= " ltri"[dfi
->dkind
];
348 if (snprintf (dump_id
, sizeof (dump_id
), ".%03d%c", dfi
->num
, suffix
) < 0)
355 snprintf (part_id
, sizeof (part_id
), ".%i", part
);
356 return concat (dump_base_name
, dump_id
, part_id
, dfi
->suffix
, NULL
);
359 return concat (dump_base_name
, dump_id
, dfi
->suffix
, NULL
);
362 /* Open a dump file called FILENAME. Some filenames are special and
363 refer to the standard streams. TRUNC indicates whether this is the
364 first open (so the file should be truncated, rather than appended).
365 An error message is emitted in the event of failure. */
368 dump_open (const char *filename
, bool trunc
)
370 if (strcmp ("stderr", filename
) == 0)
373 if (strcmp ("stdout", filename
) == 0
374 || strcmp ("-", filename
) == 0)
377 FILE *stream
= fopen (filename
, trunc
? "w" : "a");
380 error ("could not open dump file %qs: %m", filename
);
384 /* For a given DFI, open an alternate dump filename (which could also
385 be a standard stream such as stdout/stderr). If the alternate dump
386 file cannot be opened, return NULL. */
389 dump_open_alternate_stream (struct dump_file_info
*dfi
)
391 if (!dfi
->alt_filename
)
395 return dfi
->alt_stream
;
397 FILE *stream
= dump_open (dfi
->alt_filename
, dfi
->alt_state
< 0);
405 /* Construct a dump_user_location_t from STMT (using its location and
408 dump_user_location_t::dump_user_location_t (const gimple
*stmt
)
409 : m_count (), m_loc (UNKNOWN_LOCATION
)
414 m_count
= stmt
->bb
->count
;
415 m_loc
= gimple_location (stmt
);
419 /* Construct a dump_user_location_t from an RTL instruction (using its
420 location and hotness). */
422 dump_user_location_t::dump_user_location_t (const rtx_insn
*insn
)
423 : m_count (), m_loc (UNKNOWN_LOCATION
)
427 basic_block bb
= BLOCK_FOR_INSN (insn
);
430 m_loc
= INSN_LOCATION (insn
);
434 /* Construct from a function declaration. This one requires spelling out
435 to avoid accidentally constructing from other kinds of tree. */
438 dump_user_location_t::from_function_decl (tree fndecl
)
442 // FIXME: profile count for function?
443 return dump_user_location_t (profile_count (),
444 DECL_SOURCE_LOCATION (fndecl
));
447 /* Extract the MSG_* component from DUMP_KIND and return a string for use
448 as a prefix to dump messages.
449 These match the strings in optinfo_verbosity_options and thus the
450 "OPTIONS" within "-fopt-info-OPTIONS". */
453 kind_as_string (dump_flags_t dump_kind
)
455 switch (dump_kind
& MSG_ALL_KINDS
)
459 case MSG_OPTIMIZED_LOCATIONS
:
461 case MSG_MISSED_OPTIMIZATION
:
468 /* Print source location on DFILE if enabled. */
471 dump_loc (dump_flags_t dump_kind
, FILE *dfile
, location_t loc
)
475 if (LOCATION_LOCUS (loc
) > BUILTINS_LOCATION
)
476 fprintf (dfile
, "%s:%d:%d: ", LOCATION_FILE (loc
),
477 LOCATION_LINE (loc
), LOCATION_COLUMN (loc
));
478 else if (current_function_decl
)
479 fprintf (dfile
, "%s:%d:%d: ",
480 DECL_SOURCE_FILE (current_function_decl
),
481 DECL_SOURCE_LINE (current_function_decl
),
482 DECL_SOURCE_COLUMN (current_function_decl
));
483 fprintf (dfile
, "%s: ", kind_as_string (dump_kind
));
484 /* Indentation based on scope depth. */
485 fprintf (dfile
, "%*s", get_dump_scope_depth (), "");
489 /* Print source location to PP if enabled. */
492 dump_loc (dump_flags_t dump_kind
, pretty_printer
*pp
, location_t loc
)
496 if (LOCATION_LOCUS (loc
) > BUILTINS_LOCATION
)
497 pp_printf (pp
, "%s:%d:%d: ", LOCATION_FILE (loc
),
498 LOCATION_LINE (loc
), LOCATION_COLUMN (loc
));
499 else if (current_function_decl
)
500 pp_printf (pp
, "%s:%d:%d: ",
501 DECL_SOURCE_FILE (current_function_decl
),
502 DECL_SOURCE_LINE (current_function_decl
),
503 DECL_SOURCE_COLUMN (current_function_decl
));
504 pp_printf (pp
, "%s: ", kind_as_string (dump_kind
));
505 /* Indentation based on scope depth. */
506 for (unsigned i
= 0; i
< get_dump_scope_depth (); i
++)
507 pp_character (pp
, ' ');
511 /* Implementation of dump_context member functions. */
513 /* dump_context's dtor. */
515 dump_context::~dump_context ()
521 dump_context::set_json_writer (optrecord_json_writer
*writer
)
523 delete m_json_writer
;
524 m_json_writer
= writer
;
527 /* Perform cleanup activity for -fsave-optimization-record.
528 Currently, the file is written out here in one go, before cleaning
532 dump_context::finish_any_json_writer ()
537 m_json_writer
->write ();
538 delete m_json_writer
;
539 m_json_writer
= NULL
;
542 /* Update the "dumps_are_enabled" global; to be called whenever dump_file
543 or alt_dump_file change, or when changing dump_context in selftests. */
546 dump_context::refresh_dumps_are_enabled ()
548 dumps_are_enabled
= (dump_file
|| alt_dump_file
|| optinfo_enabled_p ()
552 /* Determine if a message of kind DUMP_KIND and at the current scope depth
555 Only show messages that match FILTER both on their kind *and*
559 dump_context::apply_dump_filter_p (dump_flags_t dump_kind
,
560 dump_flags_t filter
) const
562 /* Few messages, if any, have an explicit MSG_PRIORITY.
563 If DUMP_KIND does, we'll use it.
564 Otherwise, generate an implicit priority value for the message based
565 on the current scope depth.
566 Messages at the top-level scope are MSG_PRIORITY_USER_FACING,
567 whereas those in nested scopes are MSG_PRIORITY_INTERNALS. */
568 if (!(dump_kind
& MSG_ALL_PRIORITIES
))
570 dump_flags_t implicit_priority
572 ? MSG_PRIORITY_INTERNALS
573 : MSG_PRIORITY_USER_FACING
);
574 dump_kind
|= implicit_priority
;
577 return (dump_kind
& (filter
& MSG_ALL_KINDS
)
578 && dump_kind
& (filter
& MSG_ALL_PRIORITIES
));
581 /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
582 If optinfos are enabled, begin a new optinfo. */
585 dump_context::dump_loc (const dump_metadata_t
&metadata
,
586 const dump_user_location_t
&loc
)
590 dump_loc_immediate (metadata
.get_dump_flags (), loc
);
592 if (optinfo_enabled_p ())
593 begin_next_optinfo (metadata
, loc
);
596 /* As dump_loc above, but without starting a new optinfo. */
599 dump_context::dump_loc_immediate (dump_flags_t dump_kind
,
600 const dump_user_location_t
&loc
)
602 location_t srcloc
= loc
.get_location_t ();
604 if (dump_file
&& apply_dump_filter_p (dump_kind
, pflags
))
605 ::dump_loc (dump_kind
, dump_file
, srcloc
);
607 if (alt_dump_file
&& apply_dump_filter_p (dump_kind
, alt_flags
))
608 ::dump_loc (dump_kind
, alt_dump_file
, srcloc
);
610 /* Support for temp_dump_context in selftests. */
611 if (m_test_pp
&& apply_dump_filter_p (dump_kind
, m_test_pp_flags
))
612 ::dump_loc (dump_kind
, m_test_pp
, srcloc
);
615 /* Make an item for the given dump call, equivalent to print_gimple_stmt. */
617 static optinfo_item
*
618 make_item_for_dump_gimple_stmt (gimple
*stmt
, int spc
, dump_flags_t dump_flags
)
621 pp_needs_newline (&pp
) = true;
622 pp_gimple_stmt_1 (&pp
, stmt
, spc
, dump_flags
);
626 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE
, gimple_location (stmt
),
627 xstrdup (pp_formatted_text (&pp
)));
631 /* Dump gimple statement GS with SPC indentation spaces and
632 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
635 dump_context::dump_gimple_stmt (const dump_metadata_t
&metadata
,
636 dump_flags_t extra_dump_flags
,
640 = make_item_for_dump_gimple_stmt (gs
, spc
, dump_flags
| extra_dump_flags
);
641 emit_item (item
, metadata
.get_dump_flags ());
643 if (optinfo_enabled_p ())
645 optinfo
&info
= ensure_pending_optinfo (metadata
);
646 info
.add_item (item
);
652 /* Similar to dump_gimple_stmt, except additionally print source location. */
655 dump_context::dump_gimple_stmt_loc (const dump_metadata_t
&metadata
,
656 const dump_user_location_t
&loc
,
657 dump_flags_t extra_dump_flags
,
660 dump_loc (metadata
, loc
);
661 dump_gimple_stmt (metadata
, extra_dump_flags
, gs
, spc
);
664 /* Make an item for the given dump call, equivalent to print_gimple_expr. */
666 static optinfo_item
*
667 make_item_for_dump_gimple_expr (gimple
*stmt
, int spc
, dump_flags_t dump_flags
)
669 dump_flags
|= TDF_RHS_ONLY
;
671 pp_needs_newline (&pp
) = true;
672 pp_gimple_stmt_1 (&pp
, stmt
, spc
, dump_flags
);
675 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE
, gimple_location (stmt
),
676 xstrdup (pp_formatted_text (&pp
)));
680 /* Dump gimple statement GS with SPC indentation spaces and
681 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
682 Do not terminate with a newline or semicolon. */
685 dump_context::dump_gimple_expr (const dump_metadata_t
&metadata
,
686 dump_flags_t extra_dump_flags
,
690 = make_item_for_dump_gimple_expr (gs
, spc
, dump_flags
| extra_dump_flags
);
691 emit_item (item
, metadata
.get_dump_flags ());
693 if (optinfo_enabled_p ())
695 optinfo
&info
= ensure_pending_optinfo (metadata
);
696 info
.add_item (item
);
702 /* Similar to dump_gimple_expr, except additionally print source location. */
705 dump_context::dump_gimple_expr_loc (const dump_metadata_t
&metadata
,
706 const dump_user_location_t
&loc
,
707 dump_flags_t extra_dump_flags
,
711 dump_loc (metadata
, loc
);
712 dump_gimple_expr (metadata
, extra_dump_flags
, gs
, spc
);
715 /* Make an item for the given dump call, equivalent to print_generic_expr. */
717 static optinfo_item
*
718 make_item_for_dump_generic_expr (tree node
, dump_flags_t dump_flags
)
721 pp_needs_newline (&pp
) = true;
722 pp_translate_identifiers (&pp
) = false;
723 dump_generic_node (&pp
, node
, 0, dump_flags
, false);
725 location_t loc
= UNKNOWN_LOCATION
;
726 if (EXPR_HAS_LOCATION (node
))
727 loc
= EXPR_LOCATION (node
);
730 = new optinfo_item (OPTINFO_ITEM_KIND_TREE
, loc
,
731 xstrdup (pp_formatted_text (&pp
)));
735 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
736 DUMP_KIND is enabled. */
739 dump_context::dump_generic_expr (const dump_metadata_t
&metadata
,
740 dump_flags_t extra_dump_flags
,
744 = make_item_for_dump_generic_expr (t
, dump_flags
| extra_dump_flags
);
745 emit_item (item
, metadata
.get_dump_flags ());
747 if (optinfo_enabled_p ())
749 optinfo
&info
= ensure_pending_optinfo (metadata
);
750 info
.add_item (item
);
757 /* Similar to dump_generic_expr, except additionally print the source
761 dump_context::dump_generic_expr_loc (const dump_metadata_t
&metadata
,
762 const dump_user_location_t
&loc
,
763 dump_flags_t extra_dump_flags
,
766 dump_loc (metadata
, loc
);
767 dump_generic_expr (metadata
, extra_dump_flags
, t
);
770 /* Make an item for the given dump call. */
772 static optinfo_item
*
773 make_item_for_dump_symtab_node (symtab_node
*node
)
775 location_t loc
= DECL_SOURCE_LOCATION (node
->decl
);
777 = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE
, loc
,
778 xstrdup (node
->dump_name ()));
782 /* dump_pretty_printer's ctor. */
784 dump_pretty_printer::dump_pretty_printer (dump_context
*context
,
785 dump_flags_t dump_kind
)
786 : pretty_printer (), m_context (context
), m_dump_kind (dump_kind
),
789 pp_format_decoder (this) = format_decoder_cb
;
792 /* Phase 3 of formatting; compare with pp_output_formatted_text.
794 Emit optinfo_item instances for the various formatted chunks from phases
795 1 and 2 (i.e. pp_format).
797 Some chunks may already have had their items built (during decode_format).
798 These chunks have been stashed into m_stashed_items; we emit them here.
800 For all other purely textual chunks, they are printed into
801 buffer->formatted_obstack, and then emitted as a textual optinfo_item.
802 This consolidates multiple adjacent text chunks into a single text
806 dump_pretty_printer::emit_items (optinfo
*dest
)
808 output_buffer
*buffer
= pp_buffer (this);
809 struct chunk_info
*chunk_array
= buffer
->cur_chunk_array
;
810 const char **args
= chunk_array
->args
;
812 gcc_assert (buffer
->obstack
== &buffer
->formatted_obstack
);
813 gcc_assert (buffer
->line_length
== 0);
815 unsigned stashed_item_idx
= 0;
816 for (unsigned chunk
= 0; args
[chunk
]; chunk
++)
818 if (stashed_item_idx
< m_stashed_items
.length ()
819 && args
[chunk
] == *m_stashed_items
[stashed_item_idx
].buffer_ptr
)
821 emit_any_pending_textual_chunks (dest
);
822 /* This chunk has a stashed item: use it. */
823 emit_item (m_stashed_items
[stashed_item_idx
++].item
, dest
);
826 /* This chunk is purely textual. Print it (to
827 buffer->formatted_obstack), so that we can consolidate adjacent
828 chunks into one textual optinfo_item. */
829 pp_string (this, args
[chunk
]);
832 emit_any_pending_textual_chunks (dest
);
834 /* Ensure that we consumed all of stashed_items. */
835 gcc_assert (stashed_item_idx
== m_stashed_items
.length ());
837 /* Deallocate the chunk structure and everything after it (i.e. the
838 associated series of formatted strings). */
839 buffer
->cur_chunk_array
= chunk_array
->prev
;
840 obstack_free (&buffer
->chunk_obstack
, chunk_array
);
843 /* Subroutine of dump_pretty_printer::emit_items
844 for consolidating multiple adjacent pure-text chunks into single
845 optinfo_items (in phase 3). */
848 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo
*dest
)
850 gcc_assert (buffer
->obstack
== &buffer
->formatted_obstack
);
852 /* Don't emit an item if the pending text is empty. */
853 if (output_buffer_last_position_in_text (buffer
) == NULL
)
856 char *formatted_text
= xstrdup (pp_formatted_text (this));
858 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
860 emit_item (item
, dest
);
862 /* Clear the pending text by unwinding formatted_text back to the start
863 of the buffer (without deallocating). */
864 obstack_free (&buffer
->formatted_obstack
,
865 buffer
->formatted_obstack
.object_base
);
868 /* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
869 to DEST; otherwise delete ITEM. */
872 dump_pretty_printer::emit_item (optinfo_item
*item
, optinfo
*dest
)
874 m_context
->emit_item (item
, m_dump_kind
);
876 dest
->add_item (item
);
881 /* Record that ITEM (generated in phase 2 of formatting) is to be used for
882 the chunk at BUFFER_PTR in phase 3 (by emit_items). */
885 dump_pretty_printer::stash_item (const char **buffer_ptr
, optinfo_item
*item
)
887 gcc_assert (buffer_ptr
);
890 m_stashed_items
.safe_push (stashed_item (buffer_ptr
, item
));
893 /* pp_format_decoder callback for dump_pretty_printer, and thus for
894 dump_printf and dump_printf_loc.
896 A wrapper around decode_format, for type-safety. */
899 dump_pretty_printer::format_decoder_cb (pretty_printer
*pp
, text_info
*text
,
900 const char *spec
, int /*precision*/,
901 bool /*wide*/, bool /*set_locus*/,
902 bool /*verbose*/, bool */
*quoted*/
,
903 const char **buffer_ptr
)
905 dump_pretty_printer
*opp
= static_cast <dump_pretty_printer
*> (pp
);
906 return opp
->decode_format (text
, spec
, buffer_ptr
);
909 /* Format decoder for dump_pretty_printer, and thus for dump_printf and
912 Supported format codes (in addition to the standard pretty_printer ones)
916 Equivalent to: dump_symtab_node (MSG_*, node)
918 Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
920 Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
922 Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
924 TODO: add a format code that can handle (symtab_node*) *and* both
925 subclasses (presumably means teaching -Wformat about non-virtual
928 These format codes build optinfo_item instances, thus capturing metadata
929 about the arguments being dumped, as well as the textual output. */
932 dump_pretty_printer::decode_format (text_info
*text
, const char *spec
,
933 const char **buffer_ptr
)
935 /* Various format codes that imply making an optinfo_item and stashed it
936 for later use (to capture metadata, rather than plain text). */
941 cgraph_node
*node
= va_arg (*text
->args_ptr
, cgraph_node
*);
943 /* Make an item for the node, and stash it. */
944 optinfo_item
*item
= make_item_for_dump_symtab_node (node
);
945 stash_item (buffer_ptr
, item
);
951 gimple
*stmt
= va_arg (*text
->args_ptr
, gimple
*);
953 /* Make an item for the stmt, and stash it. */
954 optinfo_item
*item
= make_item_for_dump_gimple_expr (stmt
, 0, TDF_SLIM
);
955 stash_item (buffer_ptr
, item
);
961 gimple
*stmt
= va_arg (*text
->args_ptr
, gimple
*);
963 /* Make an item for the stmt, and stash it. */
964 optinfo_item
*item
= make_item_for_dump_gimple_stmt (stmt
, 0, TDF_SLIM
);
965 stash_item (buffer_ptr
, item
);
971 tree t
= va_arg (*text
->args_ptr
, tree
);
973 /* Make an item for the tree, and stash it. */
974 optinfo_item
*item
= make_item_for_dump_generic_expr (t
, TDF_SLIM
);
975 stash_item (buffer_ptr
, item
);
984 /* Output a formatted message using FORMAT on appropriate dump streams. */
987 dump_context::dump_printf_va (const dump_metadata_t
&metadata
, const char *format
,
990 dump_pretty_printer
pp (this, metadata
.get_dump_flags ());
995 text
.format_spec
= format
;
997 /* Phases 1 and 2, using pp_format. */
998 pp_format (&pp
, &text
);
1001 if (optinfo_enabled_p ())
1003 optinfo
&info
= ensure_pending_optinfo (metadata
);
1004 pp
.emit_items (&info
);
1007 pp
.emit_items (NULL
);
1010 /* Similar to dump_printf, except source location is also printed, and
1011 dump location captured. */
1014 dump_context::dump_printf_loc_va (const dump_metadata_t
&metadata
,
1015 const dump_user_location_t
&loc
,
1016 const char *format
, va_list *ap
)
1018 dump_loc (metadata
, loc
);
1019 dump_printf_va (metadata
, format
, ap
);
1022 /* Make an item for the given dump call, equivalent to print_dec. */
1024 template<unsigned int N
, typename C
>
1025 static optinfo_item
*
1026 make_item_for_dump_dec (const poly_int
<N
, C
> &value
)
1028 STATIC_ASSERT (poly_coeff_traits
<C
>::signedness
>= 0);
1029 signop sgn
= poly_coeff_traits
<C
>::signedness
? SIGNED
: UNSIGNED
;
1033 if (value
.is_constant ())
1034 pp_wide_int (&pp
, value
.coeffs
[0], sgn
);
1037 pp_character (&pp
, '[');
1038 for (unsigned int i
= 0; i
< N
; ++i
)
1040 pp_wide_int (&pp
, value
.coeffs
[i
], sgn
);
1041 pp_character (&pp
, i
== N
- 1 ? ']' : ',');
1046 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
1047 xstrdup (pp_formatted_text (&pp
)));
1051 /* Output VALUE in decimal to appropriate dump streams. */
1053 template<unsigned int N
, typename C
>
1055 dump_context::dump_dec (const dump_metadata_t
&metadata
, const poly_int
<N
, C
> &value
)
1057 optinfo_item
*item
= make_item_for_dump_dec (value
);
1058 emit_item (item
, metadata
.get_dump_flags ());
1060 if (optinfo_enabled_p ())
1062 optinfo
&info
= ensure_pending_optinfo (metadata
);
1063 info
.add_item (item
);
1069 /* Output the name of NODE on appropriate dump streams. */
1072 dump_context::dump_symtab_node (const dump_metadata_t
&metadata
, symtab_node
*node
)
1074 optinfo_item
*item
= make_item_for_dump_symtab_node (node
);
1075 emit_item (item
, metadata
.get_dump_flags ());
1077 if (optinfo_enabled_p ())
1079 optinfo
&info
= ensure_pending_optinfo (metadata
);
1080 info
.add_item (item
);
1086 /* Get the current dump scope-nesting depth.
1087 For use by -fopt-info (for showing nesting via indentation). */
1090 dump_context::get_scope_depth () const
1092 return m_scope_depth
;
1095 /* Push a nested dump scope.
1096 Increment the scope depth.
1097 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1098 destination, if any.
1099 Emit a "scope" optinfo if optinfos are enabled. */
1102 dump_context::begin_scope (const char *name
,
1103 const dump_user_location_t
&user_location
,
1104 const dump_impl_location_t
&impl_location
)
1108 location_t src_loc
= user_location
.get_location_t ();
1110 if (dump_file
&& apply_dump_filter_p (MSG_NOTE
, pflags
))
1111 ::dump_loc (MSG_NOTE
, dump_file
, src_loc
);
1113 if (alt_dump_file
&& apply_dump_filter_p (MSG_NOTE
, alt_flags
))
1114 ::dump_loc (MSG_NOTE
, alt_dump_file
, src_loc
);
1116 /* Support for temp_dump_context in selftests. */
1117 if (m_test_pp
&& apply_dump_filter_p (MSG_NOTE
, m_test_pp_flags
))
1118 ::dump_loc (MSG_NOTE
, m_test_pp
, src_loc
);
1121 pp_printf (&pp
, "=== %s ===\n", name
);
1123 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
1124 xstrdup (pp_formatted_text (&pp
)));
1125 emit_item (item
, MSG_NOTE
);
1127 if (optinfo_enabled_p ())
1130 = begin_next_optinfo (dump_metadata_t (MSG_NOTE
, impl_location
),
1132 info
.m_kind
= OPTINFO_KIND_SCOPE
;
1133 info
.add_item (item
);
1140 /* Pop a nested dump scope. */
1143 dump_context::end_scope ()
1149 m_json_writer
->pop_scope ();
1152 /* Should optinfo instances be created?
1153 All creation of optinfos should be guarded by this predicate.
1154 Return true if any optinfo destinations are active. */
1157 dump_context::optinfo_enabled_p () const
1159 return (optimization_records_enabled_p ());
1162 /* Return the optinfo currently being accumulated, creating one if
1166 dump_context::ensure_pending_optinfo (const dump_metadata_t
&metadata
)
1169 return begin_next_optinfo (metadata
, dump_user_location_t ());
1173 /* Start a new optinfo and return it, ending any optinfo that was already
1177 dump_context::begin_next_optinfo (const dump_metadata_t
&metadata
,
1178 const dump_user_location_t
&user_loc
)
1181 gcc_assert (m_pending
== NULL
);
1182 dump_location_t
loc (user_loc
, metadata
.get_impl_location ());
1183 m_pending
= new optinfo (loc
, OPTINFO_KIND_NOTE
, current_pass
);
1184 m_pending
->handle_dump_file_kind (metadata
.get_dump_flags ());
1188 /* End any optinfo that has been accumulated within this context; emitting
1189 it to any destinations as appropriate, such as optimization records. */
1192 dump_context::end_any_optinfo ()
1195 emit_optinfo (m_pending
);
1200 /* Emit the optinfo to all of the "non-immediate" destinations
1201 (emission to "immediate" destinations is done by
1202 dump_context::emit_item). */
1205 dump_context::emit_optinfo (const optinfo
*info
)
1207 /* -fsave-optimization-record. */
1209 m_json_writer
->add_record (info
);
1212 /* Emit ITEM to all item destinations (those that don't require
1213 consolidation into optinfo instances). */
1216 dump_context::emit_item (optinfo_item
*item
, dump_flags_t dump_kind
)
1218 if (dump_file
&& apply_dump_filter_p (dump_kind
, pflags
))
1219 fprintf (dump_file
, "%s", item
->get_text ());
1221 if (alt_dump_file
&& apply_dump_filter_p (dump_kind
, alt_flags
))
1222 fprintf (alt_dump_file
, "%s", item
->get_text ());
1224 /* Support for temp_dump_context in selftests. */
1225 if (m_test_pp
&& apply_dump_filter_p (dump_kind
, m_test_pp_flags
))
1226 pp_string (m_test_pp
, item
->get_text ());
1229 /* The current singleton dump_context, and its default. */
1231 dump_context
*dump_context::s_current
= &dump_context::s_default
;
1232 dump_context
dump_context::s_default
;
1234 /* Implementation of dump_* API calls, calling into dump_context
1235 member functions. */
1237 /* Calls to the dump_* functions do non-trivial work, so they ought
1239 if (dump_enabled_p ())
1240 Assert that they are guarded, and, if assertions are disabled,
1241 bail out if the calls weren't properly guarded. */
1243 #define VERIFY_DUMP_ENABLED_P \
1245 gcc_assert (dump_enabled_p ()); \
1246 if (!dump_enabled_p ()) \
1250 /* Dump gimple statement GS with SPC indentation spaces and
1251 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
1254 dump_gimple_stmt (const dump_metadata_t
&metadata
, dump_flags_t extra_dump_flags
,
1255 gimple
*gs
, int spc
)
1257 VERIFY_DUMP_ENABLED_P
;
1258 dump_context::get ().dump_gimple_stmt (metadata
, extra_dump_flags
, gs
, spc
);
1261 /* Similar to dump_gimple_stmt, except additionally print source location. */
1264 dump_gimple_stmt_loc (const dump_metadata_t
&metadata
,
1265 const dump_user_location_t
&loc
,
1266 dump_flags_t extra_dump_flags
, gimple
*gs
, int spc
)
1268 VERIFY_DUMP_ENABLED_P
;
1269 dump_context::get ().dump_gimple_stmt_loc (metadata
, loc
, extra_dump_flags
,
1273 /* Dump gimple statement GS with SPC indentation spaces and
1274 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
1275 Do not terminate with a newline or semicolon. */
1278 dump_gimple_expr (const dump_metadata_t
&metadata
,
1279 dump_flags_t extra_dump_flags
,
1280 gimple
*gs
, int spc
)
1282 VERIFY_DUMP_ENABLED_P
;
1283 dump_context::get ().dump_gimple_expr (metadata
, extra_dump_flags
, gs
, spc
);
1286 /* Similar to dump_gimple_expr, except additionally print source location. */
1289 dump_gimple_expr_loc (const dump_metadata_t
&metadata
,
1290 const dump_user_location_t
&loc
,
1291 dump_flags_t extra_dump_flags
, gimple
*gs
, int spc
)
1293 VERIFY_DUMP_ENABLED_P
;
1294 dump_context::get ().dump_gimple_expr_loc (metadata
, loc
, extra_dump_flags
,
1298 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
1299 DUMP_KIND is enabled. */
1302 dump_generic_expr (const dump_metadata_t
&metadata
, dump_flags_t extra_dump_flags
,
1305 VERIFY_DUMP_ENABLED_P
;
1306 dump_context::get ().dump_generic_expr (metadata
, extra_dump_flags
, t
);
1309 /* Similar to dump_generic_expr, except additionally print the source
1313 dump_generic_expr_loc (const dump_metadata_t
&metadata
,
1314 const dump_user_location_t
&loc
,
1315 dump_flags_t extra_dump_flags
, tree t
)
1317 VERIFY_DUMP_ENABLED_P
;
1318 dump_context::get ().dump_generic_expr_loc (metadata
, loc
, extra_dump_flags
,
1322 /* Output a formatted message using FORMAT on appropriate dump streams. */
1325 dump_printf (const dump_metadata_t
&metadata
, const char *format
, ...)
1327 VERIFY_DUMP_ENABLED_P
;
1329 va_start (ap
, format
);
1330 dump_context::get ().dump_printf_va (metadata
, format
, &ap
);
1334 /* Similar to dump_printf, except source location is also printed, and
1335 dump location captured. */
1338 dump_printf_loc (const dump_metadata_t
&metadata
,
1339 const dump_user_location_t
&loc
,
1340 const char *format
, ...)
1342 VERIFY_DUMP_ENABLED_P
;
1344 va_start (ap
, format
);
1345 dump_context::get ().dump_printf_loc_va (metadata
, loc
, format
, &ap
);
1349 /* Output VALUE in decimal to appropriate dump streams. */
1351 template<unsigned int N
, typename C
>
1353 dump_dec (const dump_metadata_t
&metadata
, const poly_int
<N
, C
> &value
)
1355 VERIFY_DUMP_ENABLED_P
;
1356 dump_context::get ().dump_dec (metadata
, value
);
1359 template void dump_dec (const dump_metadata_t
&metadata
, const poly_uint16
&);
1360 template void dump_dec (const dump_metadata_t
&metadata
, const poly_int64
&);
1361 template void dump_dec (const dump_metadata_t
&metadata
, const poly_uint64
&);
1362 template void dump_dec (const dump_metadata_t
&metadata
, const poly_offset_int
&);
1363 template void dump_dec (const dump_metadata_t
&metadata
, const poly_widest_int
&);
1366 dump_dec (dump_flags_t dump_kind
, const poly_wide_int
&value
, signop sgn
)
1368 VERIFY_DUMP_ENABLED_P
;
1370 && dump_context::get ().apply_dump_filter_p (dump_kind
, pflags
))
1371 print_dec (value
, dump_file
, sgn
);
1374 && dump_context::get ().apply_dump_filter_p (dump_kind
, alt_flags
))
1375 print_dec (value
, alt_dump_file
, sgn
);
1378 /* Output VALUE in hexadecimal to appropriate dump streams. */
1381 dump_hex (dump_flags_t dump_kind
, const poly_wide_int
&value
)
1383 VERIFY_DUMP_ENABLED_P
;
1385 && dump_context::get ().apply_dump_filter_p (dump_kind
, pflags
))
1386 print_hex (value
, dump_file
);
1389 && dump_context::get ().apply_dump_filter_p (dump_kind
, alt_flags
))
1390 print_hex (value
, alt_dump_file
);
1393 /* Emit and delete the currently pending optinfo, if there is one,
1394 without the caller needing to know about class dump_context. */
1397 dumpfile_ensure_any_optinfo_are_flushed ()
1399 dump_context::get().end_any_optinfo ();
1402 /* Output the name of NODE on appropriate dump streams. */
1405 dump_symtab_node (const dump_metadata_t
&metadata
, symtab_node
*node
)
1407 VERIFY_DUMP_ENABLED_P
;
1408 dump_context::get ().dump_symtab_node (metadata
, node
);
1411 /* Get the current dump scope-nesting depth.
1412 For use by -fopt-info (for showing nesting via indentation). */
1415 get_dump_scope_depth ()
1417 return dump_context::get ().get_scope_depth ();
1420 /* Push a nested dump scope.
1421 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1422 destination, if any.
1423 Emit a "scope" opinfo if optinfos are enabled.
1424 Increment the scope depth. */
1427 dump_begin_scope (const char *name
,
1428 const dump_user_location_t
&user_location
,
1429 const dump_impl_location_t
&impl_location
)
1431 dump_context::get ().begin_scope (name
, user_location
, impl_location
);
1434 /* Pop a nested dump scope. */
1439 dump_context::get ().end_scope ();
1442 /* Start a dump for PHASE. Store user-supplied dump flags in
1443 *FLAG_PTR. Return the number of streams opened. Set globals
1444 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
1445 set dump_flags appropriately for both pass dump stream and
1446 -fopt-info stream. */
1450 dump_start (int phase
, dump_flags_t
*flag_ptr
)
1454 struct dump_file_info
*dfi
;
1456 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
1459 dfi
= get_dump_file_info (phase
);
1460 name
= get_dump_file_name (phase
);
1463 stream
= dump_open (name
, dfi
->pstate
< 0);
1470 dfi
->pstream
= stream
;
1471 set_dump_file (dfi
->pstream
);
1472 /* Initialize current dump flags. */
1473 pflags
= dfi
->pflags
;
1476 stream
= dump_open_alternate_stream (dfi
);
1479 dfi
->alt_stream
= stream
;
1481 set_alt_dump_file (dfi
->alt_stream
);
1482 /* Initialize current -fopt-info flags. */
1483 alt_flags
= dfi
->alt_flags
;
1487 *flag_ptr
= dfi
->pflags
;
1492 /* Finish a tree dump for PHASE and close associated dump streams. Also
1493 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
1497 dump_finish (int phase
)
1499 struct dump_file_info
*dfi
;
1503 dfi
= get_dump_file_info (phase
);
1504 if (dfi
->pstream
&& dfi
->pstream
!= stdout
&& dfi
->pstream
!= stderr
)
1505 fclose (dfi
->pstream
);
1507 if (dfi
->alt_stream
&& dfi
->alt_stream
!= stdout
&& dfi
->alt_stream
!= stderr
)
1508 fclose (dfi
->alt_stream
);
1510 dfi
->alt_stream
= NULL
;
1511 dfi
->pstream
= NULL
;
1512 set_dump_file (NULL
);
1513 set_alt_dump_file (NULL
);
1514 dump_flags
= TDF_NONE
;
1515 alt_flags
= TDF_NONE
;
1519 /* Begin a tree dump for PHASE. Stores any user supplied flag in
1520 *FLAG_PTR and returns a stream to write to. If the dump is not
1521 enabled, returns NULL.
1522 PART can be used for dump files which should be split to multiple
1523 parts. PART == -1 indicates dump file with no parts.
1524 If PART is -1, multiple calls will reopen and append to the dump file. */
1527 dump_begin (int phase
, dump_flags_t
*flag_ptr
, int part
)
1529 return g
->get_dumps ()->dump_begin (phase
, flag_ptr
, part
);
1534 dump_begin (int phase
, dump_flags_t
*flag_ptr
, int part
)
1536 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
1539 char *name
= get_dump_file_name (phase
, part
);
1542 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1544 /* We do not support re-opening of dump files with parts. This would require
1545 tracking pstate per part of the dump file. */
1546 FILE *stream
= dump_open (name
, part
!= -1 || dfi
->pstate
< 0);
1552 *flag_ptr
= dfi
->pflags
;
1554 /* Initialize current flags */
1555 pflags
= dfi
->pflags
;
1559 /* Returns nonzero if dump PHASE is enabled for at least one stream.
1560 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1565 dump_phase_enabled_p (int phase
) const
1567 if (phase
== TDI_tree_all
)
1570 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1571 if (dump_files
[i
].pstate
|| dump_files
[i
].alt_state
)
1573 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1574 if (m_extra_dump_files
[i
].pstate
|| m_extra_dump_files
[i
].alt_state
)
1580 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1581 return dfi
->pstate
|| dfi
->alt_state
;
1585 /* Returns nonzero if tree dump PHASE has been initialized. */
1589 dump_initialized_p (int phase
) const
1591 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1592 return dfi
->pstate
> 0 || dfi
->alt_state
> 0;
1595 /* Returns the switch name of PHASE. */
1598 dump_flag_name (int phase
)
1600 return g
->get_dumps ()->dump_flag_name (phase
);
1605 dump_flag_name (int phase
) const
1607 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1611 /* Handle -fdump-* and -fopt-info for a pass added after
1612 command-line options are parsed (those from plugins and
1613 those from backends).
1615 Because the registration of plugin/backend passes happens after the
1616 command-line options are parsed, the options that specify single
1617 pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
1618 passes. Therefore we currently can only enable dumping of
1619 new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
1620 are specified. This is done here.
1622 Similarly, the saved -fopt-info options are wired up to the new pass. */
1625 gcc::dump_manager::register_pass (opt_pass
*pass
)
1629 register_one_dump_file (pass
);
1631 dump_file_info
*pass_dfi
= get_dump_file_info (pass
->static_pass_number
);
1632 gcc_assert (pass_dfi
);
1634 enum tree_dump_index tdi
;
1635 if (pass
->type
== SIMPLE_IPA_PASS
1636 || pass
->type
== IPA_PASS
)
1638 else if (pass
->type
== GIMPLE_PASS
)
1642 const dump_file_info
*tdi_dfi
= get_dump_file_info (tdi
);
1643 gcc_assert (tdi_dfi
);
1645 /* Check if dump-all flag is specified. */
1646 if (tdi_dfi
->pstate
)
1648 pass_dfi
->pstate
= tdi_dfi
->pstate
;
1649 pass_dfi
->pflags
= tdi_dfi
->pflags
;
1652 update_dfi_for_opt_info (pass_dfi
);
1655 /* Finish a tree dump for PHASE. STREAM is the stream created by
1659 dump_end (int phase ATTRIBUTE_UNUSED
, FILE *stream
)
1661 if (stream
!= stderr
&& stream
!= stdout
)
1665 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
1666 enabled tree dumps. */
1670 dump_enable_all (dump_kind dkind
, dump_flags_t flags
, const char *filename
)
1675 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1677 if (dump_files
[i
].dkind
== dkind
)
1679 const char *old_filename
= dump_files
[i
].pfilename
;
1680 dump_files
[i
].pstate
= -1;
1681 dump_files
[i
].pflags
|= flags
;
1683 /* Override the existing filename. */
1686 dump_files
[i
].pfilename
= xstrdup (filename
);
1687 /* Since it is a command-line provided file, which is
1688 common to all the phases, use it in append mode. */
1689 dump_files
[i
].pstate
= 1;
1691 if (old_filename
&& filename
!= old_filename
)
1692 free (CONST_CAST (char *, old_filename
));
1696 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1698 if (m_extra_dump_files
[i
].dkind
== dkind
)
1700 const char *old_filename
= m_extra_dump_files
[i
].pfilename
;
1701 m_extra_dump_files
[i
].pstate
= -1;
1702 m_extra_dump_files
[i
].pflags
|= flags
;
1704 /* Override the existing filename. */
1707 m_extra_dump_files
[i
].pfilename
= xstrdup (filename
);
1708 /* Since it is a command-line provided file, which is
1709 common to all the phases, use it in append mode. */
1710 m_extra_dump_files
[i
].pstate
= 1;
1712 if (old_filename
&& filename
!= old_filename
)
1713 free (CONST_CAST (char *, old_filename
));
1720 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1721 Enable dumps with FLAGS on FILENAME. Return the number of enabled
1726 opt_info_enable_passes (optgroup_flags_t optgroup_flags
, dump_flags_t flags
,
1727 const char *filename
)
1731 m_optgroup_flags
= optgroup_flags
;
1732 m_optinfo_flags
= flags
;
1733 m_optinfo_filename
= xstrdup (filename
);
1735 for (size_t i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1736 if (update_dfi_for_opt_info (&dump_files
[i
]))
1739 for (size_t i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1740 if (update_dfi_for_opt_info (&m_extra_dump_files
[i
]))
1746 /* Use the saved -fopt-info options to update DFI.
1747 Return true if the dump is enabled. */
1750 gcc::dump_manager::update_dfi_for_opt_info (dump_file_info
*dfi
) const
1754 if (!(dfi
->optgroup_flags
& m_optgroup_flags
))
1757 const char *old_filename
= dfi
->alt_filename
;
1758 /* Since this file is shared among different passes, it
1759 should be opened in append mode. */
1761 dfi
->alt_flags
|= m_optinfo_flags
;
1762 /* Override the existing filename. */
1763 if (m_optinfo_filename
)
1764 dfi
->alt_filename
= xstrdup (m_optinfo_filename
);
1765 if (old_filename
&& m_optinfo_filename
!= old_filename
)
1766 free (CONST_CAST (char *, old_filename
));
1771 /* Helper routine to parse -<dump format>[=filename]
1772 and return the corresponding dump flag. If POS_P is non-NULL,
1773 assign start of filename into *POS_P. */
1776 parse_dump_option (const char *option_value
, const char **pos_p
)
1785 /* Retain "user-facing" and "internals" messages, but filter out
1786 those from an opt_problem being re-emitted at the top level
1787 (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages
1788 messing up scan-tree-dump-times" in DejaGnu tests. */
1789 flags
= MSG_PRIORITY_USER_FACING
| MSG_PRIORITY_INTERNALS
;
1793 const struct kv_pair
<dump_flags_t
> *option_ptr
;
1794 const char *end_ptr
;
1799 end_ptr
= strchr (ptr
, '-');
1800 eq_ptr
= strchr (ptr
, '=');
1802 if (eq_ptr
&& !end_ptr
)
1806 end_ptr
= ptr
+ strlen (ptr
);
1807 length
= end_ptr
- ptr
;
1809 for (option_ptr
= dump_options
; option_ptr
->name
; option_ptr
++)
1810 if (strlen (option_ptr
->name
) == length
1811 && !memcmp (option_ptr
->name
, ptr
, length
))
1813 flags
|= option_ptr
->value
;
1819 /* Interpret rest of the argument as a dump filename. This
1820 filename overrides other command line filenames. */
1827 warning (0, "ignoring unknown option %q.*s",
1838 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1839 relevant details in the dump_files array. */
1843 dump_switch_p_1 (const char *arg
, struct dump_file_info
*dfi
, bool doglob
)
1845 const char *option_value
;
1846 dump_flags_t flags
= TDF_NONE
;
1848 if (doglob
&& !dfi
->glob
)
1851 option_value
= skip_leading_substring (arg
, doglob
? dfi
->glob
: dfi
->swtch
);
1855 if (*option_value
&& *option_value
!= '-' && *option_value
!= '=')
1858 const char *filename
;
1859 flags
= parse_dump_option (option_value
, &filename
);
1863 free (CONST_CAST (char *, dfi
->pfilename
));
1864 dfi
->pfilename
= xstrdup (filename
);
1868 dfi
->pflags
|= flags
;
1870 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1872 if (dfi
->suffix
== NULL
)
1873 dump_enable_all (dfi
->dkind
, dfi
->pflags
, dfi
->pfilename
);
1880 dump_switch_p (const char *arg
)
1885 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1886 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], false);
1888 /* Don't glob if we got a hit already */
1890 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1891 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], true);
1893 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1894 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], false);
1897 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1898 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], true);
1902 auto_vec
<const char *> candidates
;
1903 for (size_t i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1904 candidates
.safe_push (dump_files
[i
].swtch
);
1905 for (size_t i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1906 candidates
.safe_push (m_extra_dump_files
[i
].swtch
);
1907 const char *hint
= find_closest_string (arg
, &candidates
);
1909 error ("unrecognized command-line option %<-fdump-%s%>; "
1910 "did you mean %<-fdump-%s%>?", arg
, hint
);
1912 error ("unrecognized command-line option %<-fdump-%s%>", arg
);
1916 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1917 and filename. Return non-zero if it is a recognized switch. */
1920 opt_info_switch_p_1 (const char *arg
, dump_flags_t
*flags
,
1921 optgroup_flags_t
*optgroup_flags
, char **filename
)
1923 const char *option_value
;
1931 /* Default to filtering out "internals" messages, and retaining
1932 "user-facing" messages, and those from an opt_problem being
1933 re-emitted at the top level. */
1934 *flags
= MSG_PRIORITY_USER_FACING
| MSG_PRIORITY_REEMITTED
;
1936 *optgroup_flags
= OPTGROUP_NONE
;
1939 return 1; /* Handle '-fopt-info' without any additional options. */
1943 const char *end_ptr
;
1949 end_ptr
= strchr (ptr
, '-');
1950 eq_ptr
= strchr (ptr
, '=');
1952 if (eq_ptr
&& (!end_ptr
|| eq_ptr
< end_ptr
))
1955 end_ptr
= ptr
+ strlen (ptr
);
1956 length
= end_ptr
- ptr
;
1958 for (const kv_pair
<dump_flags_t
> *option_ptr
= optinfo_verbosity_options
;
1959 option_ptr
->name
; option_ptr
++)
1960 if (strlen (option_ptr
->name
) == length
1961 && !memcmp (option_ptr
->name
, ptr
, length
))
1963 *flags
|= option_ptr
->value
;
1967 for (const kv_pair
<optgroup_flags_t
> *option_ptr
= optgroup_options
;
1968 option_ptr
->name
; option_ptr
++)
1969 if (strlen (option_ptr
->name
) == length
1970 && !memcmp (option_ptr
->name
, ptr
, length
))
1972 *optgroup_flags
|= option_ptr
->value
;
1978 /* Interpret rest of the argument as a dump filename. This
1979 filename overrides other command line filenames. */
1980 *filename
= xstrdup (ptr
+ 1);
1985 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1996 /* Return non-zero if ARG is a recognized switch for
1997 -fopt-info. Return zero otherwise. */
2000 opt_info_switch_p (const char *arg
)
2003 optgroup_flags_t optgroup_flags
;
2005 static char *file_seen
= NULL
;
2006 gcc::dump_manager
*dumps
= g
->get_dumps ();
2008 if (!opt_info_switch_p_1 (arg
, &flags
, &optgroup_flags
, &filename
))
2012 filename
= xstrdup ("stderr");
2014 /* Bail out if a different filename has been specified. */
2015 if (file_seen
&& strcmp (file_seen
, filename
))
2017 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
2022 file_seen
= xstrdup (filename
);
2023 if (!(flags
& MSG_ALL_KINDS
))
2024 flags
|= MSG_OPTIMIZED_LOCATIONS
;
2025 if (!optgroup_flags
)
2026 optgroup_flags
= OPTGROUP_ALL
;
2028 return dumps
->opt_info_enable_passes (optgroup_flags
, flags
, filename
);
2031 /* Print basic block on the dump streams. */
2034 dump_basic_block (dump_flags_t dump_kind
, basic_block bb
, int indent
)
2037 && dump_context::get ().apply_dump_filter_p (dump_kind
, pflags
))
2038 dump_bb (dump_file
, bb
, indent
, TDF_DETAILS
);
2040 && dump_context::get ().apply_dump_filter_p (dump_kind
, alt_flags
))
2041 dump_bb (alt_dump_file
, bb
, indent
, TDF_DETAILS
);
2044 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
2047 dump_function (int phase
, tree fn
)
2052 stream
= dump_begin (phase
, &flags
);
2055 dump_function_to_file (fn
, stream
, flags
);
2056 dump_end (phase
, stream
);
2060 /* Print information from the combine pass on dump_file. */
2063 print_combine_total_stats (void)
2066 dump_combine_total_stats (dump_file
);
2069 /* Enable RTL dump for all the RTL passes. */
2072 enable_rtl_dump_file (void)
2074 gcc::dump_manager
*dumps
= g
->get_dumps ();
2076 dumps
->dump_enable_all (DK_rtl
, dump_flags_t (TDF_DETAILS
) | TDF_BLOCKS
,
2078 return num_enabled
> 0;
2081 /* debug_dump_context's ctor. Temporarily override the dump_context
2082 (to forcibly enable output to stderr). */
2084 debug_dump_context::debug_dump_context ()
2086 m_saved (&dump_context::get ()),
2087 m_saved_flags (dump_flags
),
2088 m_saved_pflags (pflags
),
2089 m_saved_file (dump_file
)
2091 set_dump_file (stderr
);
2092 dump_context::s_current
= &m_context
;
2093 pflags
= dump_flags
= MSG_ALL_KINDS
| MSG_ALL_PRIORITIES
;
2094 dump_context::get ().refresh_dumps_are_enabled ();
2097 /* debug_dump_context's dtor. Restore the saved dump_context. */
2099 debug_dump_context::~debug_dump_context ()
2101 set_dump_file (m_saved_file
);
2102 dump_context::s_current
= m_saved
;
2103 dump_flags
= m_saved_flags
;
2104 pflags
= m_saved_pflags
;
2105 dump_context::get ().refresh_dumps_are_enabled ();
2111 namespace selftest
{
2113 /* temp_dump_context's ctor. Temporarily override the dump_context
2114 (to forcibly enable optinfo-generation). */
2116 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo
,
2117 bool forcibly_enable_dumping
,
2118 dump_flags_t test_pp_flags
)
2120 m_saved (&dump_context::get ())
2122 dump_context::s_current
= &m_context
;
2123 if (forcibly_enable_optinfo
)
2124 m_context
.set_json_writer (new optrecord_json_writer ());
2125 /* Conditionally enable the test dump, so that we can verify both the
2126 dump_enabled_p and the !dump_enabled_p cases in selftests. */
2127 if (forcibly_enable_dumping
)
2129 m_context
.m_test_pp
= &m_pp
;
2130 m_context
.m_test_pp_flags
= test_pp_flags
;
2133 dump_context::get ().refresh_dumps_are_enabled ();
2136 /* temp_dump_context's dtor. Restore the saved dump_context. */
2138 temp_dump_context::~temp_dump_context ()
2140 m_context
.set_json_writer (NULL
);
2142 dump_context::s_current
= m_saved
;
2144 dump_context::get ().refresh_dumps_are_enabled ();
2147 /* 0-terminate the text dumped so far, and return it. */
2150 temp_dump_context::get_dumped_text ()
2152 return pp_formatted_text (&m_pp
);
2155 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2156 from EXPECTED_FUNCTION, using LOC for the location of any failure,
2157 provided that the build compiler is sufficiently recent. */
2160 assert_impl_location_eq (const location
&loc ATTRIBUTE_UNUSED
,
2161 const dump_impl_location_t
&impl_loc ATTRIBUTE_UNUSED
,
2162 const char *expected_file ATTRIBUTE_UNUSED
,
2163 int expected_line ATTRIBUTE_UNUSED
,
2164 const char *expected_function ATTRIBUTE_UNUSED
)
2166 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
2167 ASSERT_STR_CONTAINS_AT (loc
, impl_loc
.m_file
, expected_file
);
2168 ASSERT_EQ_AT (loc
, impl_loc
.m_line
, expected_line
);
2169 ASSERT_STR_CONTAINS_AT (loc
, impl_loc
.m_function
, expected_function
);
2173 /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
2174 from EXPECTED_FUNCTION, provided that the build compiler is
2175 sufficiently recent. */
2177 #define ASSERT_IMPL_LOCATION_EQ(IMPL_LOC, EXPECTED_FILE, EXPECTED_LINE, \
2178 EXPECTED_FUNCTION) \
2179 SELFTEST_BEGIN_STMT \
2180 assert_impl_location_eq (SELFTEST_LOCATION, IMPL_LOC, \
2181 EXPECTED_FILE, EXPECTED_LINE, \
2182 EXPECTED_FUNCTION); \
2185 /* Verify that the dump_location_t constructors capture the source location
2186 at which they were called (provided that the build compiler is sufficiently
2190 test_impl_location ()
2194 dump_location_t loc
;
2195 const int expected_line
= __LINE__
- 1;
2196 ASSERT_IMPL_LOCATION_EQ (loc
.get_impl_location (),
2197 "dumpfile.c", expected_line
, "test_impl_location");
2200 /* Constructing from a gimple. */
2202 dump_location_t
loc ((gimple
*)NULL
);
2203 const int expected_line
= __LINE__
- 1;
2204 ASSERT_IMPL_LOCATION_EQ (loc
.get_impl_location (),
2205 "dumpfile.c", expected_line
, "test_impl_location");
2208 /* Constructing from an rtx_insn. */
2210 dump_location_t
loc ((rtx_insn
*)NULL
);
2211 const int expected_line
= __LINE__
- 1;
2212 ASSERT_IMPL_LOCATION_EQ (loc
.get_impl_location (),
2213 "dumpfile.c", expected_line
, "test_impl_location");
2217 /* Verify that the text dumped so far in CONTEXT equals
2218 EXPECTED_TEXT, using LOC for the location of any failure.
2219 As a side-effect, the internal buffer is 0-terminated. */
2222 verify_dumped_text (const location
&loc
,
2223 temp_dump_context
*context
,
2224 const char *expected_text
)
2226 gcc_assert (context
);
2227 ASSERT_STREQ_AT (loc
, context
->get_dumped_text (),
2231 /* Verify that ITEM has the expected values. */
2234 verify_item (const location
&loc
,
2235 const optinfo_item
*item
,
2236 enum optinfo_item_kind expected_kind
,
2237 location_t expected_location
,
2238 const char *expected_text
)
2240 ASSERT_EQ_AT (loc
, item
->get_kind (), expected_kind
);
2241 ASSERT_EQ_AT (loc
, item
->get_location (), expected_location
);
2242 ASSERT_STREQ_AT (loc
, item
->get_text (), expected_text
);
2245 /* Verify that calls to the dump_* API are captured and consolidated into
2246 optimization records. */
2249 test_capture_of_dump_calls (const line_table_case
&case_
)
2251 /* Generate a location_t for testing. */
2252 line_table_test
ltt (case_
);
2253 linemap_add (line_table
, LC_ENTER
, false, "test.txt", 0);
2254 linemap_line_start (line_table
, 5, 100);
2255 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2256 location_t decl_loc
= linemap_position_for_column (line_table
, 8);
2257 location_t stmt_loc
= linemap_position_for_column (line_table
, 10);
2258 if (stmt_loc
> LINE_MAP_MAX_LOCATION_WITH_COLS
)
2261 dump_user_location_t loc
= dump_user_location_t::from_location_t (stmt_loc
);
2263 gimple
*stmt
= gimple_build_return (NULL
);
2264 gimple_set_location (stmt
, stmt_loc
);
2266 tree test_decl
= build_decl (decl_loc
, FUNCTION_DECL
,
2267 get_identifier ("test_decl"),
2268 build_function_type_list (void_type_node
,
2271 symbol_table_test tmp_symtab
;
2273 cgraph_node
*node
= cgraph_node::get_create (test_decl
);
2276 /* Run all tests twice, with and then without optinfo enabled, to ensure
2277 that immediate destinations vs optinfo-based destinations both
2278 work, independently of each other, with no leaks. */
2279 for (int i
= 0 ; i
< 2; i
++)
2281 bool with_optinfo
= (i
== 0);
2283 /* Test of dump_printf. */
2285 temp_dump_context
tmp (with_optinfo
, true,
2286 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2287 dump_printf (MSG_NOTE
, "int: %i str: %s", 42, "foo");
2288 const int expected_impl_line
= __LINE__
- 1;
2290 ASSERT_DUMPED_TEXT_EQ (tmp
, "int: 42 str: foo");
2293 optinfo
*info
= tmp
.get_pending_optinfo ();
2294 ASSERT_TRUE (info
!= NULL
);
2295 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2296 ASSERT_EQ (info
->num_items (), 1);
2297 ASSERT_IS_TEXT (info
->get_item (0), "int: 42 str: foo");
2298 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2299 "dumpfile.c", expected_impl_line
,
2300 "test_capture_of_dump_calls");
2304 /* Test of dump_printf with %T. */
2306 temp_dump_context
tmp (with_optinfo
, true,
2307 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2308 dump_printf (MSG_NOTE
, "tree: %T", integer_zero_node
);
2309 const int expected_impl_line
= __LINE__
- 1;
2311 ASSERT_DUMPED_TEXT_EQ (tmp
, "tree: 0");
2314 optinfo
*info
= tmp
.get_pending_optinfo ();
2315 ASSERT_TRUE (info
!= NULL
);
2316 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2317 ASSERT_EQ (info
->num_items (), 2);
2318 ASSERT_IS_TEXT (info
->get_item (0), "tree: ");
2319 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2320 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2321 "dumpfile.c", expected_impl_line
,
2322 "test_capture_of_dump_calls");
2326 /* Test of dump_printf with %E. */
2328 temp_dump_context
tmp (with_optinfo
, true,
2329 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2330 dump_printf (MSG_NOTE
, "gimple: %E", stmt
);
2331 const int expected_impl_line
= __LINE__
- 1;
2333 ASSERT_DUMPED_TEXT_EQ (tmp
, "gimple: return;");
2336 optinfo
*info
= tmp
.get_pending_optinfo ();
2337 ASSERT_TRUE (info
!= NULL
);
2338 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2339 ASSERT_EQ (info
->num_items (), 2);
2340 ASSERT_IS_TEXT (info
->get_item (0), "gimple: ");
2341 ASSERT_IS_GIMPLE (info
->get_item (1), stmt_loc
, "return;");
2342 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2343 "dumpfile.c", expected_impl_line
,
2344 "test_capture_of_dump_calls");
2348 /* Test of dump_printf with %G. */
2350 temp_dump_context
tmp (with_optinfo
, true,
2351 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2352 dump_printf (MSG_NOTE
, "gimple: %G", stmt
);
2353 const int expected_impl_line
= __LINE__
- 1;
2355 ASSERT_DUMPED_TEXT_EQ (tmp
, "gimple: return;\n");
2358 optinfo
*info
= tmp
.get_pending_optinfo ();
2359 ASSERT_TRUE (info
!= NULL
);
2360 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2361 ASSERT_EQ (info
->num_items (), 2);
2362 ASSERT_IS_TEXT (info
->get_item (0), "gimple: ");
2363 ASSERT_IS_GIMPLE (info
->get_item (1), stmt_loc
, "return;\n");
2364 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2365 "dumpfile.c", expected_impl_line
,
2366 "test_capture_of_dump_calls");
2370 /* Test of dump_printf with %C. */
2372 temp_dump_context
tmp (with_optinfo
, true,
2373 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2374 dump_printf (MSG_NOTE
, "node: %C", node
);
2375 const int expected_impl_line
= __LINE__
- 1;
2377 ASSERT_DUMPED_TEXT_EQ (tmp
, "node: test_decl/0");
2380 optinfo
*info
= tmp
.get_pending_optinfo ();
2381 ASSERT_TRUE (info
!= NULL
);
2382 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2383 ASSERT_EQ (info
->num_items (), 2);
2384 ASSERT_IS_TEXT (info
->get_item (0), "node: ");
2385 ASSERT_IS_SYMTAB_NODE (info
->get_item (1), decl_loc
, "test_decl/0");
2386 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2387 "dumpfile.c", expected_impl_line
,
2388 "test_capture_of_dump_calls");
2392 /* dump_print_loc with multiple format codes. This tests various
2394 - intermingling of text, format codes handled by the base
2395 pretty_printer, and dump-specific format codes
2396 - multiple dump-specific format codes: some consecutive, others
2397 separated by text, trailing text after the final one. */
2399 temp_dump_context
tmp (with_optinfo
, true,
2400 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2401 dump_printf_loc (MSG_NOTE
, loc
, "before %T and %T"
2402 " %i consecutive %E%E after\n",
2403 integer_zero_node
, test_decl
, 42, stmt
, stmt
);
2405 ASSERT_DUMPED_TEXT_EQ (tmp
,
2406 "test.txt:5:10: note: before 0 and test_decl"
2407 " 42 consecutive return;return; after\n");
2410 optinfo
*info
= tmp
.get_pending_optinfo ();
2411 ASSERT_TRUE (info
!= NULL
);
2412 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2413 ASSERT_EQ (info
->num_items (), 8);
2414 ASSERT_IS_TEXT (info
->get_item (0), "before ");
2415 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2416 ASSERT_IS_TEXT (info
->get_item (2), " and ");
2417 ASSERT_IS_TREE (info
->get_item (3), UNKNOWN_LOCATION
, "test_decl");
2418 ASSERT_IS_TEXT (info
->get_item (4), " 42 consecutive ");
2419 ASSERT_IS_GIMPLE (info
->get_item (5), stmt_loc
, "return;");
2420 ASSERT_IS_GIMPLE (info
->get_item (6), stmt_loc
, "return;");
2421 ASSERT_IS_TEXT (info
->get_item (7), " after\n");
2422 /* We don't ASSERT_IMPL_LOCATION_EQ here, to avoid having to
2423 enforce at which exact line the multiline dump_printf_loc
2428 /* Tree, via dump_generic_expr. */
2430 temp_dump_context
tmp (with_optinfo
, true,
2431 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2432 dump_printf_loc (MSG_NOTE
, loc
, "test of tree: ");
2433 const int expected_impl_line
= __LINE__
- 1;
2434 dump_generic_expr (MSG_NOTE
, TDF_SLIM
, integer_zero_node
);
2436 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: test of tree: 0");
2439 optinfo
*info
= tmp
.get_pending_optinfo ();
2440 ASSERT_TRUE (info
!= NULL
);
2441 ASSERT_EQ (info
->get_location_t (), stmt_loc
);
2442 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2443 ASSERT_EQ (info
->num_items (), 2);
2444 ASSERT_IS_TEXT (info
->get_item (0), "test of tree: ");
2445 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2446 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2447 "dumpfile.c", expected_impl_line
,
2448 "test_capture_of_dump_calls");
2452 /* Tree, via dump_generic_expr_loc. */
2454 temp_dump_context
tmp (with_optinfo
, true,
2455 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2456 dump_generic_expr_loc (MSG_NOTE
, loc
, TDF_SLIM
, integer_one_node
);
2457 const int expected_impl_line
= __LINE__
- 1;
2459 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: 1");
2462 optinfo
*info
= tmp
.get_pending_optinfo ();
2463 ASSERT_TRUE (info
!= NULL
);
2464 ASSERT_EQ (info
->get_location_t (), stmt_loc
);
2465 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2466 ASSERT_EQ (info
->num_items (), 1);
2467 ASSERT_IS_TREE (info
->get_item (0), UNKNOWN_LOCATION
, "1");
2468 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2469 "dumpfile.c", expected_impl_line
,
2470 "test_capture_of_dump_calls");
2476 /* dump_gimple_stmt_loc. */
2478 temp_dump_context
tmp (with_optinfo
, true,
2479 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2480 dump_gimple_stmt_loc (MSG_NOTE
, loc
, TDF_SLIM
, stmt
, 2);
2481 const int expected_impl_line
= __LINE__
- 1;
2483 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: return;\n");
2486 optinfo
*info
= tmp
.get_pending_optinfo ();
2487 ASSERT_TRUE (info
!= NULL
);
2488 ASSERT_EQ (info
->num_items (), 1);
2489 ASSERT_IS_GIMPLE (info
->get_item (0), stmt_loc
, "return;\n");
2490 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2491 "dumpfile.c", expected_impl_line
,
2492 "test_capture_of_dump_calls");
2496 /* dump_gimple_stmt. */
2498 temp_dump_context
tmp (with_optinfo
, true,
2499 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2500 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, stmt
, 2);
2501 const int expected_impl_line
= __LINE__
- 1;
2503 ASSERT_DUMPED_TEXT_EQ (tmp
, "return;\n");
2506 optinfo
*info
= tmp
.get_pending_optinfo ();
2507 ASSERT_TRUE (info
!= NULL
);
2508 ASSERT_EQ (info
->num_items (), 1);
2509 ASSERT_IS_GIMPLE (info
->get_item (0), stmt_loc
, "return;\n");
2510 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2511 "dumpfile.c", expected_impl_line
,
2512 "test_capture_of_dump_calls");
2516 /* dump_gimple_expr_loc. */
2518 temp_dump_context
tmp (with_optinfo
, true,
2519 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2520 dump_gimple_expr_loc (MSG_NOTE
, loc
, TDF_SLIM
, stmt
, 2);
2521 const int expected_impl_line
= __LINE__
- 1;
2523 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: return;");
2526 optinfo
*info
= tmp
.get_pending_optinfo ();
2527 ASSERT_TRUE (info
!= NULL
);
2528 ASSERT_EQ (info
->num_items (), 1);
2529 ASSERT_IS_GIMPLE (info
->get_item (0), stmt_loc
, "return;");
2530 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2531 "dumpfile.c", expected_impl_line
,
2532 "test_capture_of_dump_calls");
2536 /* dump_gimple_expr. */
2538 temp_dump_context
tmp (with_optinfo
, true,
2539 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2540 dump_gimple_expr (MSG_NOTE
, TDF_SLIM
, stmt
, 2);
2541 const int expected_impl_line
= __LINE__
- 1;
2543 ASSERT_DUMPED_TEXT_EQ (tmp
, "return;");
2546 optinfo
*info
= tmp
.get_pending_optinfo ();
2547 ASSERT_TRUE (info
!= NULL
);
2548 ASSERT_EQ (info
->num_items (), 1);
2549 ASSERT_IS_GIMPLE (info
->get_item (0), stmt_loc
, "return;");
2550 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2551 "dumpfile.c", expected_impl_line
,
2552 "test_capture_of_dump_calls");
2559 temp_dump_context
tmp (with_optinfo
, true,
2560 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2561 dump_symtab_node (MSG_NOTE
, node
);
2562 const int expected_impl_line
= __LINE__
- 1;
2564 ASSERT_DUMPED_TEXT_EQ (tmp
, "test_decl/0");
2567 optinfo
*info
= tmp
.get_pending_optinfo ();
2568 ASSERT_TRUE (info
!= NULL
);
2569 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2570 ASSERT_EQ (info
->num_items (), 1);
2571 ASSERT_IS_SYMTAB_NODE (info
->get_item (0), decl_loc
, "test_decl/0");
2572 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2573 "dumpfile.c", expected_impl_line
,
2574 "test_capture_of_dump_calls");
2580 temp_dump_context
tmp (with_optinfo
, true,
2581 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2582 dump_dec (MSG_NOTE
, poly_int64 (42));
2583 const int expected_impl_line
= __LINE__
- 1;
2585 ASSERT_DUMPED_TEXT_EQ (tmp
, "42");
2588 optinfo
*info
= tmp
.get_pending_optinfo ();
2589 ASSERT_TRUE (info
!= NULL
);
2590 ASSERT_EQ (info
->num_items (), 1);
2591 ASSERT_IS_TEXT (info
->get_item (0), "42");
2592 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2593 "dumpfile.c", expected_impl_line
,
2594 "test_capture_of_dump_calls");
2598 /* Scopes. Test with all 4 combinations of
2599 filtering by MSG_PRIORITY_USER_FACING
2600 and/or filtering by MSG_PRIORITY_INTERNALS. */
2601 for (int j
= 0; j
< 3; j
++)
2603 dump_flags_t dump_filter
= MSG_ALL_KINDS
;
2605 dump_filter
|= MSG_PRIORITY_USER_FACING
;
2607 dump_filter
|= MSG_PRIORITY_INTERNALS
;
2609 temp_dump_context
tmp (with_optinfo
, true, dump_filter
);
2610 /* Emit various messages, mostly with implicit priority. */
2611 dump_printf_loc (MSG_NOTE
, stmt
, "msg 1\n");
2612 dump_printf_loc (MSG_NOTE
| MSG_PRIORITY_INTERNALS
, stmt
,
2613 "explicitly internal msg\n");
2615 AUTO_DUMP_SCOPE ("outer scope", stmt
);
2616 dump_printf_loc (MSG_NOTE
, stmt
, "msg 2\n");
2618 AUTO_DUMP_SCOPE ("middle scope", stmt
);
2619 dump_printf_loc (MSG_NOTE
, stmt
, "msg 3\n");
2621 AUTO_DUMP_SCOPE ("inner scope", stmt
);
2622 dump_printf_loc (MSG_NOTE
, stmt
, "msg 4\n");
2623 dump_printf_loc (MSG_NOTE
| MSG_PRIORITY_USER_FACING
, stmt
,
2624 "explicitly user-facing msg\n");
2626 dump_printf_loc (MSG_NOTE
, stmt
, "msg 5\n");
2628 dump_printf_loc (MSG_NOTE
, stmt
, "msg 6\n");
2630 dump_printf_loc (MSG_NOTE
, stmt
, "msg 7\n");
2631 const int expected_impl_line
= __LINE__
- 1;
2633 switch (dump_filter
& MSG_ALL_PRIORITIES
)
2638 ASSERT_DUMPED_TEXT_EQ (tmp
, "");
2640 case MSG_PRIORITY_USER_FACING
:
2641 ASSERT_DUMPED_TEXT_EQ
2643 "test.txt:5:10: note: msg 1\n"
2644 "test.txt:5:10: note: explicitly user-facing msg\n"
2645 "test.txt:5:10: note: msg 7\n");
2647 case MSG_PRIORITY_INTERNALS
:
2648 ASSERT_DUMPED_TEXT_EQ
2650 "test.txt:5:10: note: explicitly internal msg\n"
2651 "test.txt:5:10: note: === outer scope ===\n"
2652 "test.txt:5:10: note: msg 2\n"
2653 "test.txt:5:10: note: === middle scope ===\n"
2654 "test.txt:5:10: note: msg 3\n"
2655 "test.txt:5:10: note: === inner scope ===\n"
2656 "test.txt:5:10: note: msg 4\n"
2657 "test.txt:5:10: note: msg 5\n"
2658 "test.txt:5:10: note: msg 6\n");
2660 case MSG_ALL_PRIORITIES
:
2661 ASSERT_DUMPED_TEXT_EQ
2663 "test.txt:5:10: note: msg 1\n"
2664 "test.txt:5:10: note: explicitly internal msg\n"
2665 "test.txt:5:10: note: === outer scope ===\n"
2666 "test.txt:5:10: note: msg 2\n"
2667 "test.txt:5:10: note: === middle scope ===\n"
2668 "test.txt:5:10: note: msg 3\n"
2669 "test.txt:5:10: note: === inner scope ===\n"
2670 "test.txt:5:10: note: msg 4\n"
2671 "test.txt:5:10: note: explicitly user-facing msg\n"
2672 "test.txt:5:10: note: msg 5\n"
2673 "test.txt:5:10: note: msg 6\n"
2674 "test.txt:5:10: note: msg 7\n");
2679 optinfo
*info
= tmp
.get_pending_optinfo ();
2680 ASSERT_TRUE (info
!= NULL
);
2681 ASSERT_EQ (info
->num_items (), 1);
2682 ASSERT_IS_TEXT (info
->get_item (0), "msg 7\n");
2683 ASSERT_IMPL_LOCATION_EQ (info
->get_impl_location (),
2684 "dumpfile.c", expected_impl_line
,
2685 "test_capture_of_dump_calls");
2690 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
2693 /* MSG_OPTIMIZED_LOCATIONS. */
2695 temp_dump_context
tmp (true, true, MSG_ALL_KINDS
);
2696 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS
, loc
, "test");
2697 ASSERT_EQ (tmp
.get_pending_optinfo ()->get_kind (),
2698 OPTINFO_KIND_SUCCESS
);
2701 /* MSG_MISSED_OPTIMIZATION. */
2703 temp_dump_context
tmp (true, true, MSG_ALL_KINDS
);
2704 dump_printf_loc (MSG_MISSED_OPTIMIZATION
, loc
, "test");
2705 ASSERT_EQ (tmp
.get_pending_optinfo ()->get_kind (),
2706 OPTINFO_KIND_FAILURE
);
2710 /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
2712 temp_dump_context
tmp (false, true,
2713 MSG_OPTIMIZED_LOCATIONS
| MSG_ALL_PRIORITIES
);
2714 dump_printf_loc (MSG_NOTE
, stmt
, "msg 1\n");
2716 AUTO_DUMP_SCOPE ("outer scope", stmt
);
2717 dump_printf_loc (MSG_NOTE
, stmt
, "msg 2\n");
2719 AUTO_DUMP_SCOPE ("middle scope", stmt
);
2720 dump_printf_loc (MSG_NOTE
, stmt
, "msg 3\n");
2722 AUTO_DUMP_SCOPE ("inner scope", stmt
);
2723 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS
, stmt
, "msg 4\n");
2725 dump_printf_loc (MSG_NOTE
, stmt
, "msg 5\n");
2727 dump_printf_loc (MSG_NOTE
, stmt
, "msg 6\n");
2729 dump_printf_loc (MSG_NOTE
, stmt
, "msg 7\n");
2731 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: optimized: msg 4\n");
2738 dump_user_location_t loc
2739 = dump_user_location_t::from_location_t (UNKNOWN_LOCATION
);
2741 temp_dump_context
tmp (true, true,
2742 MSG_ALL_KINDS
| MSG_PRIORITY_USER_FACING
);
2744 AUTO_DUMP_SCOPE ("outer scope", loc
);
2745 dump_printf (MSG_NOTE
, "msg1\n");
2749 /* Run all of the selftests within this file. */
2754 test_impl_location ();
2755 for_each_line_table_case (test_capture_of_dump_calls
);
2759 } // namespace selftest
2761 #endif /* CHECKING_P */