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 #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. */
43 /* If non-NULL, return one past-the-end of the matching SUBPART of
45 #define skip_leading_substring(whole, part) \
46 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
48 static dump_flags_t pflags
; /* current dump_flags */
50 static void dump_loc (dump_flags_t
, FILE *, source_location
);
52 /* Current -fopt-info output stream, if any, and flags. */
53 static FILE *alt_dump_file
= NULL
;
54 static dump_flags_t alt_flags
;
56 static FILE *dump_open_alternate_stream (struct dump_file_info
*);
58 /* These are currently used for communicating between passes.
59 However, instead of accessing them directly, the passes can use
60 dump_printf () for dumps. */
61 FILE *dump_file
= NULL
;
62 const char *dump_file_name
;
63 dump_flags_t dump_flags
;
64 bool dumps_are_enabled
= false;
67 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
71 set_dump_file (FILE *new_dump_file
)
73 dumpfile_ensure_any_optinfo_are_flushed ();
74 dump_file
= new_dump_file
;
75 dump_context::get ().refresh_dumps_are_enabled ();
78 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
82 set_alt_dump_file (FILE *new_alt_dump_file
)
84 dumpfile_ensure_any_optinfo_are_flushed ();
85 alt_dump_file
= new_alt_dump_file
;
86 dump_context::get ().refresh_dumps_are_enabled ();
89 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
90 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
91 OPTGROUP_NONE, 0, 0, num, false, false}
93 /* Table of tree dump switches. This must be consistent with the
94 TREE_DUMP_INDEX enumeration in dumpfile.h. */
95 static struct dump_file_info dump_files
[TDI_end
] =
97 DUMP_FILE_INFO (NULL
, NULL
, DK_none
, 0),
98 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa
, 0),
99 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa
, 0),
100 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa
, 0),
101 DUMP_FILE_INFO (".original", "tree-original", DK_tree
, 0),
102 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree
, 0),
103 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree
, 0),
104 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa
, 0),
105 #define FIRST_AUTO_NUMBERED_DUMP 1
106 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
108 DUMP_FILE_INFO (NULL
, "lang-all", DK_lang
, 0),
109 DUMP_FILE_INFO (NULL
, "tree-all", DK_tree
, 0),
110 DUMP_FILE_INFO (NULL
, "rtl-all", DK_rtl
, 0),
111 DUMP_FILE_INFO (NULL
, "ipa-all", DK_ipa
, 0),
114 /* Table of dump options. This must be consistent with the TDF_* flags
115 in dumpfile.h and opt_info_options below. */
116 static const kv_pair
<dump_flags_t
> dump_options
[] =
118 {"address", TDF_ADDRESS
},
119 {"asmname", TDF_ASMNAME
},
122 {"graph", TDF_GRAPH
},
123 {"details", (TDF_DETAILS
| MSG_OPTIMIZED_LOCATIONS
124 | MSG_MISSED_OPTIMIZATION
126 {"cselib", TDF_CSELIB
},
127 {"stats", TDF_STATS
},
128 {"blocks", TDF_BLOCKS
},
130 {"lineno", TDF_LINENO
},
132 {"stmtaddr", TDF_STMTADDR
},
133 {"memsyms", TDF_MEMSYMS
},
135 {"alias", TDF_ALIAS
},
136 {"nouid", TDF_NOUID
},
137 {"enumerate_locals", TDF_ENUMERATE_LOCALS
},
139 {"gimple", TDF_GIMPLE
},
140 {"folding", TDF_FOLDING
},
141 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
142 {"missed", MSG_MISSED_OPTIMIZATION
},
145 {"all", dump_flags_t (TDF_ALL_VALUES
146 & ~(TDF_RAW
| TDF_SLIM
| TDF_LINENO
| TDF_GRAPH
147 | TDF_STMTADDR
| TDF_RHS_ONLY
| TDF_NOUID
148 | TDF_ENUMERATE_LOCALS
| TDF_SCEV
| TDF_GIMPLE
))},
152 /* A subset of the dump_options table which is used for -fopt-info
153 types. This must be consistent with the MSG_* flags in dumpfile.h.
155 static const kv_pair
<dump_flags_t
> optinfo_verbosity_options
[] =
157 {"optimized", MSG_OPTIMIZED_LOCATIONS
},
158 {"missed", MSG_MISSED_OPTIMIZATION
},
164 /* Flags used for -fopt-info groups. */
165 const kv_pair
<optgroup_flags_t
> optgroup_options
[] =
167 {"ipa", OPTGROUP_IPA
},
168 {"loop", OPTGROUP_LOOP
},
169 {"inline", OPTGROUP_INLINE
},
170 {"omp", OPTGROUP_OMP
},
171 {"vec", OPTGROUP_VEC
},
172 {"optall", OPTGROUP_ALL
},
173 {NULL
, OPTGROUP_NONE
}
176 gcc::dump_manager::dump_manager ():
177 m_next_dump (FIRST_AUTO_NUMBERED_DUMP
),
178 m_extra_dump_files (NULL
),
179 m_extra_dump_files_in_use (0),
180 m_extra_dump_files_alloced (0)
184 gcc::dump_manager::~dump_manager ()
186 for (size_t i
= 0; i
< m_extra_dump_files_in_use
; i
++)
188 dump_file_info
*dfi
= &m_extra_dump_files
[i
];
189 /* suffix, swtch, glob are statically allocated for the entries
190 in dump_files, and for statistics, but are dynamically allocated
191 for those for passes. */
192 if (dfi
->owns_strings
)
194 XDELETEVEC (const_cast <char *> (dfi
->suffix
));
195 XDELETEVEC (const_cast <char *> (dfi
->swtch
));
196 XDELETEVEC (const_cast <char *> (dfi
->glob
));
198 /* These, if non-NULL, are always dynamically allocated. */
199 XDELETEVEC (const_cast <char *> (dfi
->pfilename
));
200 XDELETEVEC (const_cast <char *> (dfi
->alt_filename
));
202 XDELETEVEC (m_extra_dump_files
);
207 dump_register (const char *suffix
, const char *swtch
, const char *glob
,
208 dump_kind dkind
, optgroup_flags_t optgroup_flags
,
211 int num
= m_next_dump
++;
213 size_t count
= m_extra_dump_files_in_use
++;
215 if (count
>= m_extra_dump_files_alloced
)
217 if (m_extra_dump_files_alloced
== 0)
218 m_extra_dump_files_alloced
= 512;
220 m_extra_dump_files_alloced
*= 2;
221 m_extra_dump_files
= XRESIZEVEC (struct dump_file_info
,
223 m_extra_dump_files_alloced
);
225 /* Construct a new object in the space allocated above. */
226 new (m_extra_dump_files
+ count
) dump_file_info ();
230 /* Zero out the already constructed object. */
231 m_extra_dump_files
[count
] = dump_file_info ();
234 m_extra_dump_files
[count
].suffix
= suffix
;
235 m_extra_dump_files
[count
].swtch
= swtch
;
236 m_extra_dump_files
[count
].glob
= glob
;
237 m_extra_dump_files
[count
].dkind
= dkind
;
238 m_extra_dump_files
[count
].optgroup_flags
= optgroup_flags
;
239 m_extra_dump_files
[count
].num
= num
;
240 m_extra_dump_files
[count
].owns_strings
= take_ownership
;
242 return count
+ TDI_end
;
246 /* Allow languages and middle-end to register their dumps before the
247 optimization passes. */
253 lang_hooks
.register_dumps (this);
254 /* If this assert fails, some FE registered more than
255 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
256 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
257 gcc_assert (m_next_dump
<= FIRST_ME_AUTO_NUMBERED_DUMP
);
258 m_next_dump
= FIRST_ME_AUTO_NUMBERED_DUMP
;
259 dump_files
[TDI_original
].num
= m_next_dump
++;
260 dump_files
[TDI_gimple
].num
= m_next_dump
++;
261 dump_files
[TDI_nested
].num
= m_next_dump
++;
265 /* Return the dump_file_info for the given phase. */
267 struct dump_file_info
*
269 get_dump_file_info (int phase
) const
272 return &dump_files
[phase
];
273 else if ((size_t) (phase
- TDI_end
) >= m_extra_dump_files_in_use
)
276 return m_extra_dump_files
+ (phase
- TDI_end
);
279 /* Locate the dump_file_info with swtch equal to SWTCH,
280 or return NULL if no such dump_file_info exists. */
282 struct dump_file_info
*
284 get_dump_file_info_by_switch (const char *swtch
) const
286 for (unsigned i
= 0; i
< m_extra_dump_files_in_use
; i
++)
287 if (strcmp (m_extra_dump_files
[i
].swtch
, swtch
) == 0)
288 return &m_extra_dump_files
[i
];
295 /* Return the name of the dump file for the given phase.
296 The caller is responsible for calling free on the returned
298 If the dump is not enabled, returns NULL. */
302 get_dump_file_name (int phase
, int part
) const
304 struct dump_file_info
*dfi
;
306 if (phase
== TDI_none
)
309 dfi
= get_dump_file_info (phase
);
311 return get_dump_file_name (dfi
, part
);
314 /* Return the name of the dump file for the given dump_file_info.
315 The caller is responsible for calling free on the returned
317 If the dump is not enabled, returns NULL. */
321 get_dump_file_name (struct dump_file_info
*dfi
, int part
) const
327 if (dfi
->pstate
== 0)
330 /* If available, use the command line dump filename. */
332 return xstrdup (dfi
->pfilename
);
338 /* (null), LANG, TREE, RTL, IPA. */
339 char suffix
= " ltri"[dfi
->dkind
];
341 if (snprintf (dump_id
, sizeof (dump_id
), ".%03d%c", dfi
->num
, suffix
) < 0)
348 snprintf (part_id
, sizeof (part_id
), ".%i", part
);
349 return concat (dump_base_name
, dump_id
, part_id
, dfi
->suffix
, NULL
);
352 return concat (dump_base_name
, dump_id
, dfi
->suffix
, NULL
);
355 /* Open a dump file called FILENAME. Some filenames are special and
356 refer to the standard streams. TRUNC indicates whether this is the
357 first open (so the file should be truncated, rather than appended).
358 An error message is emitted in the event of failure. */
361 dump_open (const char *filename
, bool trunc
)
363 if (strcmp ("stderr", filename
) == 0)
366 if (strcmp ("stdout", filename
) == 0
367 || strcmp ("-", filename
) == 0)
370 FILE *stream
= fopen (filename
, trunc
? "w" : "a");
373 error ("could not open dump file %qs: %m", filename
);
377 /* For a given DFI, open an alternate dump filename (which could also
378 be a standard stream such as stdout/stderr). If the alternate dump
379 file cannot be opened, return NULL. */
382 dump_open_alternate_stream (struct dump_file_info
*dfi
)
384 if (!dfi
->alt_filename
)
388 return dfi
->alt_stream
;
390 FILE *stream
= dump_open (dfi
->alt_filename
, dfi
->alt_state
< 0);
398 /* Construct a dump_user_location_t from STMT (using its location and
401 dump_user_location_t::dump_user_location_t (const gimple
*stmt
)
402 : m_count (), m_loc (UNKNOWN_LOCATION
)
407 m_count
= stmt
->bb
->count
;
408 m_loc
= gimple_location (stmt
);
412 /* Construct a dump_user_location_t from an RTL instruction (using its
413 location and hotness). */
415 dump_user_location_t::dump_user_location_t (const rtx_insn
*insn
)
416 : m_count (), m_loc (UNKNOWN_LOCATION
)
420 basic_block bb
= BLOCK_FOR_INSN (insn
);
423 m_loc
= INSN_LOCATION (insn
);
427 /* Construct from a function declaration. This one requires spelling out
428 to avoid accidentally constructing from other kinds of tree. */
431 dump_user_location_t::from_function_decl (tree fndecl
)
435 // FIXME: profile count for function?
436 return dump_user_location_t (profile_count (),
437 DECL_SOURCE_LOCATION (fndecl
));
440 /* Print source location on DFILE if enabled. */
443 dump_loc (dump_flags_t dump_kind
, FILE *dfile
, source_location loc
)
447 if (LOCATION_LOCUS (loc
) > BUILTINS_LOCATION
)
448 fprintf (dfile
, "%s:%d:%d: note: ", LOCATION_FILE (loc
),
449 LOCATION_LINE (loc
), LOCATION_COLUMN (loc
));
450 else if (current_function_decl
)
451 fprintf (dfile
, "%s:%d:%d: note: ",
452 DECL_SOURCE_FILE (current_function_decl
),
453 DECL_SOURCE_LINE (current_function_decl
),
454 DECL_SOURCE_COLUMN (current_function_decl
));
455 /* Indentation based on scope depth. */
456 fprintf (dfile
, "%*s", get_dump_scope_depth (), "");
460 /* Print source location to PP if enabled. */
463 dump_loc (dump_flags_t dump_kind
, pretty_printer
*pp
, source_location loc
)
467 if (LOCATION_LOCUS (loc
) > BUILTINS_LOCATION
)
468 pp_printf (pp
, "%s:%d:%d: note: ", LOCATION_FILE (loc
),
469 LOCATION_LINE (loc
), LOCATION_COLUMN (loc
));
470 else if (current_function_decl
)
471 pp_printf (pp
, "%s:%d:%d: note: ",
472 DECL_SOURCE_FILE (current_function_decl
),
473 DECL_SOURCE_LINE (current_function_decl
),
474 DECL_SOURCE_COLUMN (current_function_decl
));
475 /* Indentation based on scope depth. */
476 for (unsigned i
= 0; i
< get_dump_scope_depth (); i
++)
477 pp_character (pp
, ' ');
481 /* Implementation of dump_context member functions. */
483 /* dump_context's dtor. */
485 dump_context::~dump_context ()
490 /* Update the "dumps_are_enabled" global; to be called whenever dump_file
491 or alt_dump_file change, or when changing dump_context in selftests. */
494 dump_context::refresh_dumps_are_enabled ()
496 dumps_are_enabled
= (dump_file
|| alt_dump_file
|| optinfo_enabled_p ()
500 /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
501 If optinfos are enabled, begin a new optinfo. */
504 dump_context::dump_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
)
508 location_t srcloc
= loc
.get_location_t ();
510 if (dump_file
&& (dump_kind
& pflags
))
511 ::dump_loc (dump_kind
, dump_file
, srcloc
);
513 if (alt_dump_file
&& (dump_kind
& alt_flags
))
514 ::dump_loc (dump_kind
, alt_dump_file
, srcloc
);
516 /* Support for temp_dump_context in selftests. */
517 if (m_test_pp
&& (dump_kind
& m_test_pp_flags
))
518 ::dump_loc (dump_kind
, m_test_pp
, srcloc
);
520 if (optinfo_enabled_p ())
522 optinfo
&info
= begin_next_optinfo (loc
);
523 info
.handle_dump_file_kind (dump_kind
);
527 /* Make an item for the given dump call, equivalent to print_gimple_stmt. */
529 static optinfo_item
*
530 make_item_for_dump_gimple_stmt (gimple
*stmt
, int spc
, dump_flags_t dump_flags
)
533 pp_needs_newline (&pp
) = true;
534 pp_gimple_stmt_1 (&pp
, stmt
, spc
, dump_flags
);
538 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE
, gimple_location (stmt
),
539 xstrdup (pp_formatted_text (&pp
)));
543 /* Dump gimple statement GS with SPC indentation spaces and
544 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
547 dump_context::dump_gimple_stmt (dump_flags_t dump_kind
,
548 dump_flags_t extra_dump_flags
,
552 = make_item_for_dump_gimple_stmt (gs
, spc
, dump_flags
| extra_dump_flags
);
553 emit_item (item
, dump_kind
);
555 if (optinfo_enabled_p ())
557 optinfo
&info
= ensure_pending_optinfo ();
558 info
.handle_dump_file_kind (dump_kind
);
559 info
.add_item (item
);
565 /* Similar to dump_gimple_stmt, except additionally print source location. */
568 dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind
,
569 const dump_location_t
&loc
,
570 dump_flags_t extra_dump_flags
,
573 dump_loc (dump_kind
, loc
);
574 dump_gimple_stmt (dump_kind
, extra_dump_flags
, gs
, spc
);
577 /* Make an item for the given dump call, equivalent to print_gimple_expr. */
579 static optinfo_item
*
580 make_item_for_dump_gimple_expr (gimple
*stmt
, int spc
, dump_flags_t dump_flags
)
582 dump_flags
|= TDF_RHS_ONLY
;
584 pp_needs_newline (&pp
) = true;
585 pp_gimple_stmt_1 (&pp
, stmt
, spc
, dump_flags
);
588 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE
, gimple_location (stmt
),
589 xstrdup (pp_formatted_text (&pp
)));
593 /* Dump gimple statement GS with SPC indentation spaces and
594 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
595 Do not terminate with a newline or semicolon. */
598 dump_context::dump_gimple_expr (dump_flags_t dump_kind
,
599 dump_flags_t extra_dump_flags
,
603 = make_item_for_dump_gimple_expr (gs
, spc
, dump_flags
| extra_dump_flags
);
604 emit_item (item
, dump_kind
);
606 if (optinfo_enabled_p ())
608 optinfo
&info
= ensure_pending_optinfo ();
609 info
.handle_dump_file_kind (dump_kind
);
610 info
.add_item (item
);
616 /* Similar to dump_gimple_expr, except additionally print source location. */
619 dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind
,
620 const dump_location_t
&loc
,
621 dump_flags_t extra_dump_flags
,
625 dump_loc (dump_kind
, loc
);
626 dump_gimple_expr (dump_kind
, extra_dump_flags
, gs
, spc
);
629 /* Make an item for the given dump call, equivalent to print_generic_expr. */
631 static optinfo_item
*
632 make_item_for_dump_generic_expr (tree node
, dump_flags_t dump_flags
)
635 pp_needs_newline (&pp
) = true;
636 pp_translate_identifiers (&pp
) = false;
637 dump_generic_node (&pp
, node
, 0, dump_flags
, false);
639 location_t loc
= UNKNOWN_LOCATION
;
640 if (EXPR_HAS_LOCATION (node
))
641 loc
= EXPR_LOCATION (node
);
644 = new optinfo_item (OPTINFO_ITEM_KIND_TREE
, loc
,
645 xstrdup (pp_formatted_text (&pp
)));
649 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
650 DUMP_KIND is enabled. */
653 dump_context::dump_generic_expr (dump_flags_t dump_kind
,
654 dump_flags_t extra_dump_flags
,
658 = make_item_for_dump_generic_expr (t
, dump_flags
| extra_dump_flags
);
659 emit_item (item
, dump_kind
);
661 if (optinfo_enabled_p ())
663 optinfo
&info
= ensure_pending_optinfo ();
664 info
.handle_dump_file_kind (dump_kind
);
665 info
.add_item (item
);
672 /* Similar to dump_generic_expr, except additionally print the source
676 dump_context::dump_generic_expr_loc (dump_flags_t dump_kind
,
677 const dump_location_t
&loc
,
678 dump_flags_t extra_dump_flags
,
681 dump_loc (dump_kind
, loc
);
682 dump_generic_expr (dump_kind
, extra_dump_flags
, t
);
685 /* A subclass of pretty_printer for implementing dump_context::dump_printf_va.
686 In particular, the formatted chunks are captured as optinfo_item instances,
687 thus retaining metadata about the entities being dumped (e.g. source
688 locations), rather than just as plain text. */
690 class dump_pretty_printer
: public pretty_printer
693 dump_pretty_printer (dump_context
*context
, dump_flags_t dump_kind
);
695 void emit_items (optinfo
*dest
);
698 /* Information on an optinfo_item that was generated during phase 2 of
702 stashed_item (const char **buffer_ptr_
, optinfo_item
*item_
)
703 : buffer_ptr (buffer_ptr_
), item (item_
) {}
704 const char **buffer_ptr
;
708 static bool format_decoder_cb (pretty_printer
*pp
, text_info
*text
,
709 const char *spec
, int /*precision*/,
710 bool /*wide*/, bool /*set_locus*/,
711 bool /*verbose*/, bool */
*quoted*/
,
712 const char **buffer_ptr
);
714 bool decode_format (text_info
*text
, const char *spec
,
715 const char **buffer_ptr
);
717 void stash_item (const char **buffer_ptr
, optinfo_item
*item
);
719 void emit_any_pending_textual_chunks (optinfo
*dest
);
721 void emit_item (optinfo_item
*item
, optinfo
*dest
);
723 dump_context
*m_context
;
724 dump_flags_t m_dump_kind
;
725 auto_vec
<stashed_item
> m_stashed_items
;
728 /* dump_pretty_printer's ctor. */
730 dump_pretty_printer::dump_pretty_printer (dump_context
*context
,
731 dump_flags_t dump_kind
)
732 : pretty_printer (), m_context (context
), m_dump_kind (dump_kind
),
735 pp_format_decoder (this) = format_decoder_cb
;
738 /* Phase 3 of formatting; compare with pp_output_formatted_text.
740 Emit optinfo_item instances for the various formatted chunks from phases
741 1 and 2 (i.e. pp_format).
743 Some chunks may already have had their items built (during decode_format).
744 These chunks have been stashed into m_stashed_items; we emit them here.
746 For all other purely textual chunks, they are printed into
747 buffer->formatted_obstack, and then emitted as a textual optinfo_item.
748 This consolidates multiple adjacent text chunks into a single text
752 dump_pretty_printer::emit_items (optinfo
*dest
)
754 output_buffer
*buffer
= pp_buffer (this);
755 struct chunk_info
*chunk_array
= buffer
->cur_chunk_array
;
756 const char **args
= chunk_array
->args
;
758 gcc_assert (buffer
->obstack
== &buffer
->formatted_obstack
);
759 gcc_assert (buffer
->line_length
== 0);
761 unsigned stashed_item_idx
= 0;
762 for (unsigned chunk
= 0; args
[chunk
]; chunk
++)
764 if (stashed_item_idx
< m_stashed_items
.length ()
765 && args
[chunk
] == *m_stashed_items
[stashed_item_idx
].buffer_ptr
)
767 emit_any_pending_textual_chunks (dest
);
768 /* This chunk has a stashed item: use it. */
769 emit_item (m_stashed_items
[stashed_item_idx
++].item
, dest
);
772 /* This chunk is purely textual. Print it (to
773 buffer->formatted_obstack), so that we can consolidate adjacent
774 chunks into one textual optinfo_item. */
775 pp_string (this, args
[chunk
]);
778 emit_any_pending_textual_chunks (dest
);
780 /* Ensure that we consumed all of stashed_items. */
781 gcc_assert (stashed_item_idx
== m_stashed_items
.length ());
783 /* Deallocate the chunk structure and everything after it (i.e. the
784 associated series of formatted strings). */
785 buffer
->cur_chunk_array
= chunk_array
->prev
;
786 obstack_free (&buffer
->chunk_obstack
, chunk_array
);
789 /* Subroutine of dump_pretty_printer::emit_items
790 for consolidating multiple adjacent pure-text chunks into single
791 optinfo_items (in phase 3). */
794 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo
*dest
)
796 gcc_assert (buffer
->obstack
== &buffer
->formatted_obstack
);
798 /* Don't emit an item if the pending text is empty. */
799 if (output_buffer_last_position_in_text (buffer
) == NULL
)
802 char *formatted_text
= xstrdup (pp_formatted_text (this));
804 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
806 emit_item (item
, dest
);
808 /* Clear the pending text by unwinding formatted_text back to the start
809 of the buffer (without deallocating). */
810 obstack_free (&buffer
->formatted_obstack
,
811 buffer
->formatted_obstack
.object_base
);
814 /* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
815 to DEST; otherwise delete ITEM. */
818 dump_pretty_printer::emit_item (optinfo_item
*item
, optinfo
*dest
)
820 m_context
->emit_item (item
, m_dump_kind
);
822 dest
->add_item (item
);
827 /* Record that ITEM (generated in phase 2 of formatting) is to be used for
828 the chunk at BUFFER_PTR in phase 3 (by emit_items). */
831 dump_pretty_printer::stash_item (const char **buffer_ptr
, optinfo_item
*item
)
833 gcc_assert (buffer_ptr
);
836 m_stashed_items
.safe_push (stashed_item (buffer_ptr
, item
));
839 /* pp_format_decoder callback for dump_pretty_printer, and thus for
840 dump_printf and dump_printf_loc.
842 A wrapper around decode_format, for type-safety. */
845 dump_pretty_printer::format_decoder_cb (pretty_printer
*pp
, text_info
*text
,
846 const char *spec
, int /*precision*/,
847 bool /*wide*/, bool /*set_locus*/,
848 bool /*verbose*/, bool */
*quoted*/
,
849 const char **buffer_ptr
)
851 dump_pretty_printer
*opp
= static_cast <dump_pretty_printer
*> (pp
);
852 return opp
->decode_format (text
, spec
, buffer_ptr
);
855 /* Format decoder for dump_pretty_printer, and thus for dump_printf and
858 Supported format codes (in addition to the standard pretty_printer ones)
862 Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
864 Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
866 Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
868 FIXME: add symtab_node?
870 These format codes build optinfo_item instances, thus capturing metadata
871 about the arguments being dumped, as well as the textual output. */
874 dump_pretty_printer::decode_format (text_info
*text
, const char *spec
,
875 const char **buffer_ptr
)
877 /* Various format codes that imply making an optinfo_item and stashed it
878 for later use (to capture metadata, rather than plain text). */
883 gimple
*stmt
= va_arg (*text
->args_ptr
, gimple
*);
885 /* Make an item for the stmt, and stash it. */
886 optinfo_item
*item
= make_item_for_dump_gimple_expr (stmt
, 0, TDF_SLIM
);
887 stash_item (buffer_ptr
, item
);
893 gimple
*stmt
= va_arg (*text
->args_ptr
, gimple
*);
895 /* Make an item for the stmt, and stash it. */
896 optinfo_item
*item
= make_item_for_dump_gimple_stmt (stmt
, 0, TDF_SLIM
);
897 stash_item (buffer_ptr
, item
);
903 tree t
= va_arg (*text
->args_ptr
, tree
);
905 /* Make an item for the tree, and stash it. */
906 optinfo_item
*item
= make_item_for_dump_generic_expr (t
, TDF_SLIM
);
907 stash_item (buffer_ptr
, item
);
916 /* Output a formatted message using FORMAT on appropriate dump streams. */
919 dump_context::dump_printf_va (dump_flags_t dump_kind
, const char *format
,
922 dump_pretty_printer
pp (this, dump_kind
);
927 text
.format_spec
= format
;
929 /* Phases 1 and 2, using pp_format. */
930 pp_format (&pp
, &text
);
933 if (optinfo_enabled_p ())
935 optinfo
&info
= ensure_pending_optinfo ();
936 info
.handle_dump_file_kind (dump_kind
);
937 pp
.emit_items (&info
);
940 pp
.emit_items (NULL
);
943 /* Similar to dump_printf, except source location is also printed, and
944 dump location captured. */
947 dump_context::dump_printf_loc_va (dump_flags_t dump_kind
,
948 const dump_location_t
&loc
,
949 const char *format
, va_list *ap
)
951 dump_loc (dump_kind
, loc
);
952 dump_printf_va (dump_kind
, format
, ap
);
955 /* Make an item for the given dump call, equivalent to print_dec. */
957 template<unsigned int N
, typename C
>
958 static optinfo_item
*
959 make_item_for_dump_dec (const poly_int
<N
, C
> &value
)
961 STATIC_ASSERT (poly_coeff_traits
<C
>::signedness
>= 0);
962 signop sgn
= poly_coeff_traits
<C
>::signedness
? SIGNED
: UNSIGNED
;
966 if (value
.is_constant ())
967 pp_wide_int (&pp
, value
.coeffs
[0], sgn
);
970 pp_character (&pp
, '[');
971 for (unsigned int i
= 0; i
< N
; ++i
)
973 pp_wide_int (&pp
, value
.coeffs
[i
], sgn
);
974 pp_character (&pp
, i
== N
- 1 ? ']' : ',');
979 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
980 xstrdup (pp_formatted_text (&pp
)));
984 /* Output VALUE in decimal to appropriate dump streams. */
986 template<unsigned int N
, typename C
>
988 dump_context::dump_dec (dump_flags_t dump_kind
, const poly_int
<N
, C
> &value
)
990 optinfo_item
*item
= make_item_for_dump_dec (value
);
991 emit_item (item
, dump_kind
);
993 if (optinfo_enabled_p ())
995 optinfo
&info
= ensure_pending_optinfo ();
996 info
.handle_dump_file_kind (dump_kind
);
997 info
.add_item (item
);
1003 /* Make an item for the given dump call. */
1005 static optinfo_item
*
1006 make_item_for_dump_symtab_node (symtab_node
*node
)
1008 location_t loc
= DECL_SOURCE_LOCATION (node
->decl
);
1010 = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE
, loc
,
1011 xstrdup (node
->dump_name ()));
1015 /* Output the name of NODE on appropriate dump streams. */
1018 dump_context::dump_symtab_node (dump_flags_t dump_kind
, symtab_node
*node
)
1020 optinfo_item
*item
= make_item_for_dump_symtab_node (node
);
1021 emit_item (item
, dump_kind
);
1023 if (optinfo_enabled_p ())
1025 optinfo
&info
= ensure_pending_optinfo ();
1026 info
.handle_dump_file_kind (dump_kind
);
1027 info
.add_item (item
);
1033 /* Get the current dump scope-nesting depth.
1034 For use by -fopt-info (for showing nesting via indentation). */
1037 dump_context::get_scope_depth () const
1039 return m_scope_depth
;
1042 /* Push a nested dump scope.
1043 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1044 destination, if any.
1045 Emit a "scope" optinfo if optinfos are enabled.
1046 Increment the scope depth. */
1049 dump_context::begin_scope (const char *name
, const dump_location_t
&loc
)
1052 ::dump_loc (MSG_NOTE
, dump_file
, loc
.get_location_t ());
1055 ::dump_loc (MSG_NOTE
, alt_dump_file
, loc
.get_location_t ());
1057 /* Support for temp_dump_context in selftests. */
1059 ::dump_loc (MSG_NOTE
, m_test_pp
, loc
.get_location_t ());
1062 pp_printf (&pp
, "=== %s ===\n", name
);
1064 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT
, UNKNOWN_LOCATION
,
1065 xstrdup (pp_formatted_text (&pp
)));
1066 emit_item (item
, MSG_NOTE
);
1068 if (optinfo_enabled_p ())
1070 optinfo
&info
= begin_next_optinfo (loc
);
1071 info
.m_kind
= OPTINFO_KIND_SCOPE
;
1072 info
.add_item (item
);
1080 /* Pop a nested dump scope. */
1083 dump_context::end_scope ()
1087 optimization_records_maybe_pop_dump_scope ();
1090 /* Return the optinfo currently being accumulated, creating one if
1094 dump_context::ensure_pending_optinfo ()
1097 return begin_next_optinfo (dump_location_t (dump_user_location_t ()));
1101 /* Start a new optinfo and return it, ending any optinfo that was already
1105 dump_context::begin_next_optinfo (const dump_location_t
&loc
)
1108 gcc_assert (m_pending
== NULL
);
1109 m_pending
= new optinfo (loc
, OPTINFO_KIND_NOTE
, current_pass
);
1113 /* End any optinfo that has been accumulated within this context; emitting
1114 it to any destinations as appropriate, such as optimization records. */
1117 dump_context::end_any_optinfo ()
1125 /* Emit ITEM to all item destinations (those that don't require
1126 consolidation into optinfo instances). */
1129 dump_context::emit_item (optinfo_item
*item
, dump_flags_t dump_kind
)
1131 if (dump_file
&& (dump_kind
& pflags
))
1132 fprintf (dump_file
, "%s", item
->get_text ());
1134 if (alt_dump_file
&& (dump_kind
& alt_flags
))
1135 fprintf (alt_dump_file
, "%s", item
->get_text ());
1137 /* Support for temp_dump_context in selftests. */
1138 if (m_test_pp
&& (dump_kind
& m_test_pp_flags
))
1139 pp_string (m_test_pp
, item
->get_text ());
1142 /* The current singleton dump_context, and its default. */
1144 dump_context
*dump_context::s_current
= &dump_context::s_default
;
1145 dump_context
dump_context::s_default
;
1147 /* Implementation of dump_* API calls, calling into dump_context
1148 member functions. */
1150 /* Dump gimple statement GS with SPC indentation spaces and
1151 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
1154 dump_gimple_stmt (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
1155 gimple
*gs
, int spc
)
1157 dump_context::get ().dump_gimple_stmt (dump_kind
, extra_dump_flags
, gs
, spc
);
1160 /* Similar to dump_gimple_stmt, except additionally print source location. */
1163 dump_gimple_stmt_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
1164 dump_flags_t extra_dump_flags
, gimple
*gs
, int spc
)
1166 dump_context::get ().dump_gimple_stmt_loc (dump_kind
, loc
, extra_dump_flags
,
1170 /* Dump gimple statement GS with SPC indentation spaces and
1171 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
1172 Do not terminate with a newline or semicolon. */
1175 dump_gimple_expr (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
1176 gimple
*gs
, int spc
)
1178 dump_context::get ().dump_gimple_expr (dump_kind
, extra_dump_flags
, gs
, spc
);
1181 /* Similar to dump_gimple_expr, except additionally print source location. */
1184 dump_gimple_expr_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
1185 dump_flags_t extra_dump_flags
, gimple
*gs
, int spc
)
1187 dump_context::get ().dump_gimple_expr_loc (dump_kind
, loc
, extra_dump_flags
,
1191 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
1192 DUMP_KIND is enabled. */
1195 dump_generic_expr (dump_flags_t dump_kind
, dump_flags_t extra_dump_flags
,
1198 dump_context::get ().dump_generic_expr (dump_kind
, extra_dump_flags
, t
);
1201 /* Similar to dump_generic_expr, except additionally print the source
1205 dump_generic_expr_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
1206 dump_flags_t extra_dump_flags
, tree t
)
1208 dump_context::get ().dump_generic_expr_loc (dump_kind
, loc
, extra_dump_flags
,
1212 /* Output a formatted message using FORMAT on appropriate dump streams. */
1215 dump_printf (dump_flags_t dump_kind
, const char *format
, ...)
1218 va_start (ap
, format
);
1219 dump_context::get ().dump_printf_va (dump_kind
, format
, &ap
);
1223 /* Similar to dump_printf, except source location is also printed, and
1224 dump location captured. */
1227 dump_printf_loc (dump_flags_t dump_kind
, const dump_location_t
&loc
,
1228 const char *format
, ...)
1231 va_start (ap
, format
);
1232 dump_context::get ().dump_printf_loc_va (dump_kind
, loc
, format
, &ap
);
1236 /* Output VALUE in decimal to appropriate dump streams. */
1238 template<unsigned int N
, typename C
>
1240 dump_dec (dump_flags_t dump_kind
, const poly_int
<N
, C
> &value
)
1242 dump_context::get ().dump_dec (dump_kind
, value
);
1245 template void dump_dec (dump_flags_t
, const poly_uint16
&);
1246 template void dump_dec (dump_flags_t
, const poly_int64
&);
1247 template void dump_dec (dump_flags_t
, const poly_uint64
&);
1248 template void dump_dec (dump_flags_t
, const poly_offset_int
&);
1249 template void dump_dec (dump_flags_t
, const poly_widest_int
&);
1252 dump_dec (dump_flags_t dump_kind
, const poly_wide_int
&value
, signop sgn
)
1254 if (dump_file
&& (dump_kind
& pflags
))
1255 print_dec (value
, dump_file
, sgn
);
1257 if (alt_dump_file
&& (dump_kind
& alt_flags
))
1258 print_dec (value
, alt_dump_file
, sgn
);
1261 /* Output VALUE in hexadecimal to appropriate dump streams. */
1264 dump_hex (dump_flags_t dump_kind
, const poly_wide_int
&value
)
1266 if (dump_file
&& (dump_kind
& pflags
))
1267 print_hex (value
, dump_file
);
1269 if (alt_dump_file
&& (dump_kind
& alt_flags
))
1270 print_hex (value
, alt_dump_file
);
1273 /* Emit and delete the currently pending optinfo, if there is one,
1274 without the caller needing to know about class dump_context. */
1277 dumpfile_ensure_any_optinfo_are_flushed ()
1279 dump_context::get().end_any_optinfo ();
1282 /* Output the name of NODE on appropriate dump streams. */
1285 dump_symtab_node (dump_flags_t dump_kind
, symtab_node
*node
)
1287 dump_context::get ().dump_symtab_node (dump_kind
, node
);
1290 /* Get the current dump scope-nesting depth.
1291 For use by -fopt-info (for showing nesting via indentation). */
1294 get_dump_scope_depth ()
1296 return dump_context::get ().get_scope_depth ();
1299 /* Push a nested dump scope.
1300 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
1301 destination, if any.
1302 Emit a "scope" opinfo if optinfos are enabled.
1303 Increment the scope depth. */
1306 dump_begin_scope (const char *name
, const dump_location_t
&loc
)
1308 dump_context::get ().begin_scope (name
, loc
);
1311 /* Pop a nested dump scope. */
1316 dump_context::get ().end_scope ();
1319 /* Start a dump for PHASE. Store user-supplied dump flags in
1320 *FLAG_PTR. Return the number of streams opened. Set globals
1321 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
1322 set dump_flags appropriately for both pass dump stream and
1323 -fopt-info stream. */
1327 dump_start (int phase
, dump_flags_t
*flag_ptr
)
1331 struct dump_file_info
*dfi
;
1333 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
1336 dfi
= get_dump_file_info (phase
);
1337 name
= get_dump_file_name (phase
);
1340 stream
= dump_open (name
, dfi
->pstate
< 0);
1347 dfi
->pstream
= stream
;
1348 set_dump_file (dfi
->pstream
);
1349 /* Initialize current dump flags. */
1350 pflags
= dfi
->pflags
;
1353 stream
= dump_open_alternate_stream (dfi
);
1356 dfi
->alt_stream
= stream
;
1358 set_alt_dump_file (dfi
->alt_stream
);
1359 /* Initialize current -fopt-info flags. */
1360 alt_flags
= dfi
->alt_flags
;
1364 *flag_ptr
= dfi
->pflags
;
1369 /* Finish a tree dump for PHASE and close associated dump streams. Also
1370 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
1374 dump_finish (int phase
)
1376 struct dump_file_info
*dfi
;
1380 dfi
= get_dump_file_info (phase
);
1381 if (dfi
->pstream
&& dfi
->pstream
!= stdout
&& dfi
->pstream
!= stderr
)
1382 fclose (dfi
->pstream
);
1384 if (dfi
->alt_stream
&& dfi
->alt_stream
!= stdout
&& dfi
->alt_stream
!= stderr
)
1385 fclose (dfi
->alt_stream
);
1387 dfi
->alt_stream
= NULL
;
1388 dfi
->pstream
= NULL
;
1389 set_dump_file (NULL
);
1390 set_alt_dump_file (NULL
);
1391 dump_flags
= TDF_NONE
;
1392 alt_flags
= TDF_NONE
;
1396 /* Begin a tree dump for PHASE. Stores any user supplied flag in
1397 *FLAG_PTR and returns a stream to write to. If the dump is not
1398 enabled, returns NULL.
1399 PART can be used for dump files which should be split to multiple
1400 parts. PART == -1 indicates dump file with no parts.
1401 If PART is -1, multiple calls will reopen and append to the dump file. */
1404 dump_begin (int phase
, dump_flags_t
*flag_ptr
, int part
)
1406 return g
->get_dumps ()->dump_begin (phase
, flag_ptr
, part
);
1411 dump_begin (int phase
, dump_flags_t
*flag_ptr
, int part
)
1414 struct dump_file_info
*dfi
;
1417 if (phase
== TDI_none
|| !dump_phase_enabled_p (phase
))
1420 name
= get_dump_file_name (phase
, part
);
1423 dfi
= get_dump_file_info (phase
);
1425 /* We do not support re-opening of dump files with parts. This would require
1426 tracking pstate per part of the dump file. */
1427 stream
= dump_open (name
, part
!= -1 || dfi
->pstate
< 0);
1433 *flag_ptr
= dfi
->pflags
;
1435 /* Initialize current flags */
1436 pflags
= dfi
->pflags
;
1440 /* Returns nonzero if dump PHASE is enabled for at least one stream.
1441 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1446 dump_phase_enabled_p (int phase
) const
1448 if (phase
== TDI_tree_all
)
1451 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1452 if (dump_files
[i
].pstate
|| dump_files
[i
].alt_state
)
1454 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1455 if (m_extra_dump_files
[i
].pstate
|| m_extra_dump_files
[i
].alt_state
)
1461 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1462 return dfi
->pstate
|| dfi
->alt_state
;
1466 /* Returns nonzero if tree dump PHASE has been initialized. */
1470 dump_initialized_p (int phase
) const
1472 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1473 return dfi
->pstate
> 0 || dfi
->alt_state
> 0;
1476 /* Returns the switch name of PHASE. */
1479 dump_flag_name (int phase
)
1481 return g
->get_dumps ()->dump_flag_name (phase
);
1486 dump_flag_name (int phase
) const
1488 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
1492 /* Finish a tree dump for PHASE. STREAM is the stream created by
1496 dump_end (int phase ATTRIBUTE_UNUSED
, FILE *stream
)
1498 if (stream
!= stderr
&& stream
!= stdout
)
1502 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
1503 enabled tree dumps. */
1507 dump_enable_all (dump_kind dkind
, dump_flags_t flags
, const char *filename
)
1512 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1514 if ((dump_files
[i
].dkind
== dkind
))
1516 const char *old_filename
= dump_files
[i
].pfilename
;
1517 dump_files
[i
].pstate
= -1;
1518 dump_files
[i
].pflags
|= flags
;
1520 /* Override the existing filename. */
1523 dump_files
[i
].pfilename
= xstrdup (filename
);
1524 /* Since it is a command-line provided file, which is
1525 common to all the phases, use it in append mode. */
1526 dump_files
[i
].pstate
= 1;
1528 if (old_filename
&& filename
!= old_filename
)
1529 free (CONST_CAST (char *, old_filename
));
1533 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1535 if ((m_extra_dump_files
[i
].dkind
== dkind
))
1537 const char *old_filename
= m_extra_dump_files
[i
].pfilename
;
1538 m_extra_dump_files
[i
].pstate
= -1;
1539 m_extra_dump_files
[i
].pflags
|= flags
;
1541 /* Override the existing filename. */
1544 m_extra_dump_files
[i
].pfilename
= xstrdup (filename
);
1545 /* Since it is a command-line provided file, which is
1546 common to all the phases, use it in append mode. */
1547 m_extra_dump_files
[i
].pstate
= 1;
1549 if (old_filename
&& filename
!= old_filename
)
1550 free (CONST_CAST (char *, old_filename
));
1557 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1558 Enable dumps with FLAGS on FILENAME. Return the number of enabled
1563 opt_info_enable_passes (optgroup_flags_t optgroup_flags
, dump_flags_t flags
,
1564 const char *filename
)
1569 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1571 if ((dump_files
[i
].optgroup_flags
& optgroup_flags
))
1573 const char *old_filename
= dump_files
[i
].alt_filename
;
1574 /* Since this file is shared among different passes, it
1575 should be opened in append mode. */
1576 dump_files
[i
].alt_state
= 1;
1577 dump_files
[i
].alt_flags
|= flags
;
1579 /* Override the existing filename. */
1581 dump_files
[i
].alt_filename
= xstrdup (filename
);
1582 if (old_filename
&& filename
!= old_filename
)
1583 free (CONST_CAST (char *, old_filename
));
1587 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1589 if ((m_extra_dump_files
[i
].optgroup_flags
& optgroup_flags
))
1591 const char *old_filename
= m_extra_dump_files
[i
].alt_filename
;
1592 /* Since this file is shared among different passes, it
1593 should be opened in append mode. */
1594 m_extra_dump_files
[i
].alt_state
= 1;
1595 m_extra_dump_files
[i
].alt_flags
|= flags
;
1597 /* Override the existing filename. */
1599 m_extra_dump_files
[i
].alt_filename
= xstrdup (filename
);
1600 if (old_filename
&& filename
!= old_filename
)
1601 free (CONST_CAST (char *, old_filename
));
1608 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1609 relevant details in the dump_files array. */
1613 dump_switch_p_1 (const char *arg
, struct dump_file_info
*dfi
, bool doglob
)
1615 const char *option_value
;
1619 if (doglob
&& !dfi
->glob
)
1622 option_value
= skip_leading_substring (arg
, doglob
? dfi
->glob
: dfi
->swtch
);
1626 if (*option_value
&& *option_value
!= '-' && *option_value
!= '=')
1634 const struct kv_pair
<dump_flags_t
> *option_ptr
;
1635 const char *end_ptr
;
1641 end_ptr
= strchr (ptr
, '-');
1642 eq_ptr
= strchr (ptr
, '=');
1644 if (eq_ptr
&& !end_ptr
)
1648 end_ptr
= ptr
+ strlen (ptr
);
1649 length
= end_ptr
- ptr
;
1651 for (option_ptr
= dump_options
; option_ptr
->name
; option_ptr
++)
1652 if (strlen (option_ptr
->name
) == length
1653 && !memcmp (option_ptr
->name
, ptr
, length
))
1655 flags
|= option_ptr
->value
;
1661 /* Interpret rest of the argument as a dump filename. This
1662 filename overrides other command line filenames. */
1664 free (CONST_CAST (char *, dfi
->pfilename
));
1665 dfi
->pfilename
= xstrdup (ptr
+ 1);
1669 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1670 length
, ptr
, dfi
->swtch
);
1676 dfi
->pflags
|= flags
;
1678 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1680 if (dfi
->suffix
== NULL
)
1681 dump_enable_all (dfi
->dkind
, dfi
->pflags
, dfi
->pfilename
);
1688 dump_switch_p (const char *arg
)
1693 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1694 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], false);
1696 /* Don't glob if we got a hit already */
1698 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1699 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], true);
1701 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1702 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], false);
1705 for (i
= 0; i
< m_extra_dump_files_in_use
; i
++)
1706 any
|= dump_switch_p_1 (arg
, &m_extra_dump_files
[i
], true);
1712 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1713 and filename. Return non-zero if it is a recognized switch. */
1716 opt_info_switch_p_1 (const char *arg
, dump_flags_t
*flags
,
1717 optgroup_flags_t
*optgroup_flags
, char **filename
)
1719 const char *option_value
;
1727 *optgroup_flags
= OPTGROUP_NONE
;
1730 return 1; /* Handle '-fopt-info' without any additional options. */
1734 const char *end_ptr
;
1740 end_ptr
= strchr (ptr
, '-');
1741 eq_ptr
= strchr (ptr
, '=');
1743 if (eq_ptr
&& !end_ptr
)
1747 end_ptr
= ptr
+ strlen (ptr
);
1748 length
= end_ptr
- ptr
;
1750 for (const kv_pair
<dump_flags_t
> *option_ptr
= optinfo_verbosity_options
;
1751 option_ptr
->name
; option_ptr
++)
1752 if (strlen (option_ptr
->name
) == length
1753 && !memcmp (option_ptr
->name
, ptr
, length
))
1755 *flags
|= option_ptr
->value
;
1759 for (const kv_pair
<optgroup_flags_t
> *option_ptr
= optgroup_options
;
1760 option_ptr
->name
; option_ptr
++)
1761 if (strlen (option_ptr
->name
) == length
1762 && !memcmp (option_ptr
->name
, ptr
, length
))
1764 *optgroup_flags
|= option_ptr
->value
;
1770 /* Interpret rest of the argument as a dump filename. This
1771 filename overrides other command line filenames. */
1772 *filename
= xstrdup (ptr
+ 1);
1777 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1788 /* Return non-zero if ARG is a recognized switch for
1789 -fopt-info. Return zero otherwise. */
1792 opt_info_switch_p (const char *arg
)
1795 optgroup_flags_t optgroup_flags
;
1797 static char *file_seen
= NULL
;
1798 gcc::dump_manager
*dumps
= g
->get_dumps ();
1800 if (!opt_info_switch_p_1 (arg
, &flags
, &optgroup_flags
, &filename
))
1804 filename
= xstrdup ("stderr");
1806 /* Bail out if a different filename has been specified. */
1807 if (file_seen
&& strcmp (file_seen
, filename
))
1809 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1814 file_seen
= xstrdup (filename
);
1816 flags
= MSG_OPTIMIZED_LOCATIONS
;
1817 if (!optgroup_flags
)
1818 optgroup_flags
= OPTGROUP_ALL
;
1820 return dumps
->opt_info_enable_passes (optgroup_flags
, flags
, filename
);
1823 /* Print basic block on the dump streams. */
1826 dump_basic_block (dump_flags_t dump_kind
, basic_block bb
, int indent
)
1828 if (dump_file
&& (dump_kind
& pflags
))
1829 dump_bb (dump_file
, bb
, indent
, TDF_DETAILS
);
1830 if (alt_dump_file
&& (dump_kind
& alt_flags
))
1831 dump_bb (alt_dump_file
, bb
, indent
, TDF_DETAILS
);
1834 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1837 dump_function (int phase
, tree fn
)
1842 stream
= dump_begin (phase
, &flags
);
1845 dump_function_to_file (fn
, stream
, flags
);
1846 dump_end (phase
, stream
);
1850 /* Print information from the combine pass on dump_file. */
1853 print_combine_total_stats (void)
1856 dump_combine_total_stats (dump_file
);
1859 /* Enable RTL dump for all the RTL passes. */
1862 enable_rtl_dump_file (void)
1864 gcc::dump_manager
*dumps
= g
->get_dumps ();
1866 dumps
->dump_enable_all (DK_rtl
, dump_flags_t (TDF_DETAILS
) | TDF_BLOCKS
,
1868 return num_enabled
> 0;
1873 /* temp_dump_context's ctor. Temporarily override the dump_context
1874 (to forcibly enable optinfo-generation). */
1876 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo
,
1877 dump_flags_t test_pp_flags
)
1880 m_saved (&dump_context ().get ())
1882 dump_context::s_current
= &m_context
;
1883 m_context
.m_forcibly_enable_optinfo
= forcibly_enable_optinfo
;
1884 m_context
.m_test_pp
= &m_pp
;
1885 m_context
.m_test_pp_flags
= test_pp_flags
;
1887 dump_context::get ().refresh_dumps_are_enabled ();
1890 /* temp_dump_context's dtor. Restore the saved dump_context. */
1892 temp_dump_context::~temp_dump_context ()
1894 dump_context::s_current
= m_saved
;
1896 dump_context::get ().refresh_dumps_are_enabled ();
1899 /* 0-terminate the text dumped so far, and return it. */
1902 temp_dump_context::get_dumped_text ()
1904 return pp_formatted_text (&m_pp
);
1907 namespace selftest
{
1909 /* Verify that the dump_location_t constructors capture the source location
1910 at which they were called (provided that the build compiler is sufficiently
1914 test_impl_location ()
1916 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
1919 dump_location_t loc
;
1920 const int expected_line
= __LINE__
- 1;
1921 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1922 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1925 /* Constructing from a gimple. */
1927 dump_location_t
loc ((gimple
*)NULL
);
1928 const int expected_line
= __LINE__
- 1;
1929 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1930 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1933 /* Constructing from an rtx_insn. */
1935 dump_location_t
loc ((rtx_insn
*)NULL
);
1936 const int expected_line
= __LINE__
- 1;
1937 ASSERT_STR_CONTAINS (loc
.get_impl_location ().m_file
, "dumpfile.c");
1938 ASSERT_EQ (loc
.get_impl_location ().m_line
, expected_line
);
1943 /* Verify that the text dumped so far in CONTEXT equals
1944 EXPECTED_TEXT, using LOC for the location of any failure.
1945 As a side-effect, the internal buffer is 0-terminated. */
1948 verify_dumped_text (const location
&loc
,
1949 temp_dump_context
*context
,
1950 const char *expected_text
)
1952 gcc_assert (context
);
1953 ASSERT_STREQ_AT (loc
, context
->get_dumped_text (),
1957 /* Verify that the text dumped so far in CONTEXT equals
1959 As a side-effect, the internal buffer is 0-terminated. */
1961 #define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT) \
1962 SELFTEST_BEGIN_STMT \
1963 verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \
1966 /* Verify that ITEM has the expected values. */
1969 verify_item (const location
&loc
,
1970 const optinfo_item
*item
,
1971 enum optinfo_item_kind expected_kind
,
1972 location_t expected_location
,
1973 const char *expected_text
)
1975 ASSERT_EQ_AT (loc
, item
->get_kind (), expected_kind
);
1976 ASSERT_EQ_AT (loc
, item
->get_location (), expected_location
);
1977 ASSERT_STREQ_AT (loc
, item
->get_text (), expected_text
);
1980 /* Verify that ITEM is a text item, with EXPECTED_TEXT. */
1982 #define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
1983 SELFTEST_BEGIN_STMT \
1984 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
1985 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \
1988 /* Verify that ITEM is a tree item, with the expected values. */
1990 #define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1991 SELFTEST_BEGIN_STMT \
1992 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
1993 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
1996 /* Verify that ITEM is a gimple item, with the expected values. */
1998 #define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1999 SELFTEST_BEGIN_STMT \
2000 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
2001 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
2004 /* Verify that calls to the dump_* API are captured and consolidated into
2005 optimization records. */
2008 test_capture_of_dump_calls (const line_table_case
&case_
)
2010 /* Generate a location_t for testing. */
2011 line_table_test
ltt (case_
);
2012 linemap_add (line_table
, LC_ENTER
, false, "test.txt", 0);
2013 linemap_line_start (line_table
, 5, 100);
2014 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2015 location_t where
= linemap_position_for_column (line_table
, 10);
2016 if (where
> LINE_MAP_MAX_LOCATION_WITH_COLS
)
2019 dump_location_t loc
= dump_location_t::from_location_t (where
);
2021 gimple
*stmt
= gimple_build_return (NULL
);
2022 gimple_set_location (stmt
, where
);
2024 tree test_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
2025 get_identifier ("test_decl"),
2027 /* Run all tests twice, with and then without optinfo enabled, to ensure
2028 that immediate destinations vs optinfo-based destinations both
2029 work, independently of each other, with no leaks. */
2030 for (int i
= 0 ; i
< 2; i
++)
2032 bool with_optinfo
= (i
== 0);
2034 /* Test of dump_printf. */
2036 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2037 dump_printf (MSG_NOTE
, "int: %i str: %s", 42, "foo");
2039 ASSERT_DUMPED_TEXT_EQ (tmp
, "int: 42 str: foo");
2042 optinfo
*info
= tmp
.get_pending_optinfo ();
2043 ASSERT_TRUE (info
!= NULL
);
2044 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2045 ASSERT_EQ (info
->num_items (), 1);
2046 ASSERT_IS_TEXT (info
->get_item (0), "int: 42 str: foo");
2050 /* Test of dump_printf with %T. */
2052 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2053 dump_printf (MSG_NOTE
, "tree: %T", integer_zero_node
);
2055 ASSERT_DUMPED_TEXT_EQ (tmp
, "tree: 0");
2058 optinfo
*info
= tmp
.get_pending_optinfo ();
2059 ASSERT_TRUE (info
!= NULL
);
2060 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2061 ASSERT_EQ (info
->num_items (), 2);
2062 ASSERT_IS_TEXT (info
->get_item (0), "tree: ");
2063 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2067 /* Test of dump_printf with %E. */
2069 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2070 dump_printf (MSG_NOTE
, "gimple: %E", stmt
);
2072 ASSERT_DUMPED_TEXT_EQ (tmp
, "gimple: return;");
2075 optinfo
*info
= tmp
.get_pending_optinfo ();
2076 ASSERT_TRUE (info
!= NULL
);
2077 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2078 ASSERT_EQ (info
->num_items (), 2);
2079 ASSERT_IS_TEXT (info
->get_item (0), "gimple: ");
2080 ASSERT_IS_GIMPLE (info
->get_item (1), where
, "return;");
2084 /* Test of dump_printf with %G. */
2086 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2087 dump_printf (MSG_NOTE
, "gimple: %G", stmt
);
2089 ASSERT_DUMPED_TEXT_EQ (tmp
, "gimple: return;\n");
2092 optinfo
*info
= tmp
.get_pending_optinfo ();
2093 ASSERT_TRUE (info
!= NULL
);
2094 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2095 ASSERT_EQ (info
->num_items (), 2);
2096 ASSERT_IS_TEXT (info
->get_item (0), "gimple: ");
2097 ASSERT_IS_GIMPLE (info
->get_item (1), where
, "return;\n");
2101 /* dump_print_loc with multiple format codes. This tests various
2103 - intermingling of text, format codes handled by the base
2104 pretty_printer, and dump-specific format codes
2105 - multiple dump-specific format codes: some consecutive, others
2106 separated by text, trailing text after the final one. */
2108 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2109 dump_printf_loc (MSG_NOTE
, loc
, "before %T and %T"
2110 " %i consecutive %E%E after\n",
2111 integer_zero_node
, test_decl
, 42, stmt
, stmt
);
2113 ASSERT_DUMPED_TEXT_EQ (tmp
,
2114 "test.txt:5:10: note: before 0 and test_decl"
2115 " 42 consecutive return;return; after\n");
2118 optinfo
*info
= tmp
.get_pending_optinfo ();
2119 ASSERT_TRUE (info
!= NULL
);
2120 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2121 ASSERT_EQ (info
->num_items (), 8);
2122 ASSERT_IS_TEXT (info
->get_item (0), "before ");
2123 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2124 ASSERT_IS_TEXT (info
->get_item (2), " and ");
2125 ASSERT_IS_TREE (info
->get_item (3), UNKNOWN_LOCATION
, "test_decl");
2126 ASSERT_IS_TEXT (info
->get_item (4), " 42 consecutive ");
2127 ASSERT_IS_GIMPLE (info
->get_item (5), where
, "return;");
2128 ASSERT_IS_GIMPLE (info
->get_item (6), where
, "return;");
2129 ASSERT_IS_TEXT (info
->get_item (7), " after\n");
2133 /* Tree, via dump_generic_expr. */
2135 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2136 dump_printf_loc (MSG_NOTE
, loc
, "test of tree: ");
2137 dump_generic_expr (MSG_NOTE
, TDF_SLIM
, integer_zero_node
);
2139 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: test of tree: 0");
2142 optinfo
*info
= tmp
.get_pending_optinfo ();
2143 ASSERT_TRUE (info
!= NULL
);
2144 ASSERT_EQ (info
->get_location_t (), where
);
2145 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2146 ASSERT_EQ (info
->num_items (), 2);
2147 ASSERT_IS_TEXT (info
->get_item (0), "test of tree: ");
2148 ASSERT_IS_TREE (info
->get_item (1), UNKNOWN_LOCATION
, "0");
2152 /* Tree, via dump_generic_expr_loc. */
2154 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2155 dump_generic_expr_loc (MSG_NOTE
, loc
, TDF_SLIM
, integer_one_node
);
2157 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: 1");
2160 optinfo
*info
= tmp
.get_pending_optinfo ();
2161 ASSERT_TRUE (info
!= NULL
);
2162 ASSERT_EQ (info
->get_location_t (), where
);
2163 ASSERT_EQ (info
->get_kind (), OPTINFO_KIND_NOTE
);
2164 ASSERT_EQ (info
->num_items (), 1);
2165 ASSERT_IS_TREE (info
->get_item (0), UNKNOWN_LOCATION
, "1");
2171 /* dump_gimple_stmt_loc. */
2173 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2174 dump_gimple_stmt_loc (MSG_NOTE
, loc
, TDF_SLIM
, stmt
, 2);
2176 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: return;\n");
2179 optinfo
*info
= tmp
.get_pending_optinfo ();
2180 ASSERT_TRUE (info
!= NULL
);
2181 ASSERT_EQ (info
->num_items (), 1);
2182 ASSERT_IS_GIMPLE (info
->get_item (0), where
, "return;\n");
2186 /* dump_gimple_stmt. */
2188 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2189 dump_gimple_stmt (MSG_NOTE
, TDF_SLIM
, stmt
, 2);
2191 ASSERT_DUMPED_TEXT_EQ (tmp
, "return;\n");
2194 optinfo
*info
= tmp
.get_pending_optinfo ();
2195 ASSERT_TRUE (info
!= NULL
);
2196 ASSERT_EQ (info
->num_items (), 1);
2197 ASSERT_IS_GIMPLE (info
->get_item (0), where
, "return;\n");
2201 /* dump_gimple_expr_loc. */
2203 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2204 dump_gimple_expr_loc (MSG_NOTE
, loc
, TDF_SLIM
, stmt
, 2);
2206 ASSERT_DUMPED_TEXT_EQ (tmp
, "test.txt:5:10: note: return;");
2209 optinfo
*info
= tmp
.get_pending_optinfo ();
2210 ASSERT_TRUE (info
!= NULL
);
2211 ASSERT_EQ (info
->num_items (), 1);
2212 ASSERT_IS_GIMPLE (info
->get_item (0), where
, "return;");
2216 /* dump_gimple_expr. */
2218 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2219 dump_gimple_expr (MSG_NOTE
, TDF_SLIM
, stmt
, 2);
2221 ASSERT_DUMPED_TEXT_EQ (tmp
, "return;");
2224 optinfo
*info
= tmp
.get_pending_optinfo ();
2225 ASSERT_TRUE (info
!= NULL
);
2226 ASSERT_EQ (info
->num_items (), 1);
2227 ASSERT_IS_GIMPLE (info
->get_item (0), where
, "return;");
2234 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2235 dump_dec (MSG_NOTE
, poly_int64 (42));
2237 ASSERT_DUMPED_TEXT_EQ (tmp
, "42");
2240 optinfo
*info
= tmp
.get_pending_optinfo ();
2241 ASSERT_TRUE (info
!= NULL
);
2242 ASSERT_EQ (info
->num_items (), 1);
2243 ASSERT_IS_TEXT (info
->get_item (0), "42");
2249 temp_dump_context
tmp (with_optinfo
, MSG_ALL
);
2250 dump_printf_loc (MSG_NOTE
, stmt
, "msg 1\n");
2252 AUTO_DUMP_SCOPE ("outer scope", stmt
);
2253 dump_printf_loc (MSG_NOTE
, stmt
, "msg 2\n");
2255 AUTO_DUMP_SCOPE ("middle scope", stmt
);
2256 dump_printf_loc (MSG_NOTE
, stmt
, "msg 3\n");
2258 AUTO_DUMP_SCOPE ("inner scope", stmt
);
2259 dump_printf_loc (MSG_NOTE
, stmt
, "msg 4\n");
2261 dump_printf_loc (MSG_NOTE
, stmt
, "msg 5\n");
2263 dump_printf_loc (MSG_NOTE
, stmt
, "msg 6\n");
2265 dump_printf_loc (MSG_NOTE
, stmt
, "msg 7\n");
2267 ASSERT_DUMPED_TEXT_EQ (tmp
,
2268 "test.txt:5:10: note: msg 1\n"
2269 "test.txt:5:10: note: === outer scope ===\n"
2270 "test.txt:5:10: note: msg 2\n"
2271 "test.txt:5:10: note: === middle scope ===\n"
2272 "test.txt:5:10: note: msg 3\n"
2273 "test.txt:5:10: note: === inner scope ===\n"
2274 "test.txt:5:10: note: msg 4\n"
2275 "test.txt:5:10: note: msg 5\n"
2276 "test.txt:5:10: note: msg 6\n"
2277 "test.txt:5:10: note: msg 7\n");
2280 optinfo
*info
= tmp
.get_pending_optinfo ();
2281 ASSERT_TRUE (info
!= NULL
);
2282 ASSERT_EQ (info
->num_items (), 1);
2283 ASSERT_IS_TEXT (info
->get_item (0), "msg 7\n");
2288 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
2291 /* MSG_OPTIMIZED_LOCATIONS. */
2293 temp_dump_context
tmp (true, MSG_ALL
);
2294 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS
, loc
, "test");
2295 ASSERT_EQ (tmp
.get_pending_optinfo ()->get_kind (),
2296 OPTINFO_KIND_SUCCESS
);
2299 /* MSG_MISSED_OPTIMIZATION. */
2301 temp_dump_context
tmp (true, MSG_ALL
);
2302 dump_printf_loc (MSG_MISSED_OPTIMIZATION
, loc
, "test");
2303 ASSERT_EQ (tmp
.get_pending_optinfo ()->get_kind (),
2304 OPTINFO_KIND_FAILURE
);
2309 /* Run all of the selftests within this file. */
2314 test_impl_location ();
2315 for_each_line_table_case (test_capture_of_dump_calls
);
2318 } // namespace selftest
2320 #endif /* CHECKING_P */