111
|
1 /* Dump infrastructure for optimizations and intermediate representation.
|
131
|
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it under
|
|
7 the terms of the GNU General Public License as published by the Free
|
|
8 Software Foundation; either version 3, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
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/>. */
|
|
19
|
|
20 #include "config.h"
|
|
21 #include "system.h"
|
|
22 #include "coretypes.h"
|
|
23 #include "options.h"
|
|
24 #include "tree.h"
|
|
25 #include "gimple-pretty-print.h"
|
|
26 #include "diagnostic-core.h"
|
|
27 #include "dumpfile.h"
|
|
28 #include "context.h"
|
|
29 #include "profile-count.h"
|
|
30 #include "tree-cfg.h"
|
|
31 #include "langhooks.h"
|
131
|
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. */
|
|
35 #include "selftest.h"
|
|
36 #include "optinfo.h"
|
|
37 #include "dump-context.h"
|
|
38 #include "cgraph.h"
|
|
39 #include "tree-pass.h" /* for "current_pass". */
|
|
40 #include "optinfo-emit-json.h"
|
|
41 #include "stringpool.h" /* for get_identifier. */
|
111
|
42
|
|
43 /* If non-NULL, return one past-the-end of the matching SUBPART of
|
|
44 the WHOLE string. */
|
|
45 #define skip_leading_substring(whole, part) \
|
|
46 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
|
|
47
|
|
48 static dump_flags_t pflags; /* current dump_flags */
|
|
49
|
|
50 static void dump_loc (dump_flags_t, FILE *, source_location);
|
131
|
51
|
|
52 /* Current -fopt-info output stream, if any, and flags. */
|
|
53 static FILE *alt_dump_file = NULL;
|
|
54 static dump_flags_t alt_flags;
|
|
55
|
111
|
56 static FILE *dump_open_alternate_stream (struct dump_file_info *);
|
|
57
|
|
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;
|
131
|
64 bool dumps_are_enabled = false;
|
|
65
|
|
66
|
|
67 /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
|
|
68 global. */
|
|
69
|
|
70 void
|
|
71 set_dump_file (FILE *new_dump_file)
|
|
72 {
|
|
73 dumpfile_ensure_any_optinfo_are_flushed ();
|
|
74 dump_file = new_dump_file;
|
|
75 dump_context::get ().refresh_dumps_are_enabled ();
|
|
76 }
|
|
77
|
|
78 /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
|
|
79 global. */
|
|
80
|
|
81 static void
|
|
82 set_alt_dump_file (FILE *new_alt_dump_file)
|
|
83 {
|
|
84 dumpfile_ensure_any_optinfo_are_flushed ();
|
|
85 alt_dump_file = new_alt_dump_file;
|
|
86 dump_context::get ().refresh_dumps_are_enabled ();
|
|
87 }
|
111
|
88
|
|
89 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
|
131
|
90 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
|
|
91 OPTGROUP_NONE, 0, 0, num, false, false}
|
111
|
92
|
|
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] =
|
|
96 {
|
|
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),
|
131
|
104 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
|
111
|
105 #define FIRST_AUTO_NUMBERED_DUMP 1
|
131
|
106 #define FIRST_ME_AUTO_NUMBERED_DUMP 4
|
111
|
107
|
|
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),
|
|
112 };
|
|
113
|
|
114 /* Table of dump options. This must be consistent with the TDF_* flags
|
|
115 in dumpfile.h and opt_info_options below. */
|
131
|
116 static const kv_pair<dump_flags_t> dump_options[] =
|
111
|
117 {
|
|
118 {"address", TDF_ADDRESS},
|
|
119 {"asmname", TDF_ASMNAME},
|
|
120 {"slim", TDF_SLIM},
|
|
121 {"raw", TDF_RAW},
|
|
122 {"graph", TDF_GRAPH},
|
|
123 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
|
|
124 | MSG_MISSED_OPTIMIZATION
|
|
125 | MSG_NOTE)},
|
|
126 {"cselib", TDF_CSELIB},
|
|
127 {"stats", TDF_STATS},
|
|
128 {"blocks", TDF_BLOCKS},
|
|
129 {"vops", TDF_VOPS},
|
|
130 {"lineno", TDF_LINENO},
|
|
131 {"uid", TDF_UID},
|
|
132 {"stmtaddr", TDF_STMTADDR},
|
|
133 {"memsyms", TDF_MEMSYMS},
|
|
134 {"eh", TDF_EH},
|
|
135 {"alias", TDF_ALIAS},
|
|
136 {"nouid", TDF_NOUID},
|
|
137 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
|
|
138 {"scev", TDF_SCEV},
|
|
139 {"gimple", TDF_GIMPLE},
|
|
140 {"folding", TDF_FOLDING},
|
|
141 {"optimized", MSG_OPTIMIZED_LOCATIONS},
|
|
142 {"missed", MSG_MISSED_OPTIMIZATION},
|
|
143 {"note", MSG_NOTE},
|
131
|
144 {"optall", MSG_ALL_KINDS},
|
|
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))},
|
|
149 {NULL, TDF_NONE}
|
111
|
150 };
|
|
151
|
|
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.
|
|
154 */
|
131
|
155 static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
|
111
|
156 {
|
|
157 {"optimized", MSG_OPTIMIZED_LOCATIONS},
|
|
158 {"missed", MSG_MISSED_OPTIMIZATION},
|
|
159 {"note", MSG_NOTE},
|
131
|
160 {"all", MSG_ALL_KINDS},
|
|
161 {"internals", MSG_PRIORITY_INTERNALS},
|
|
162 {NULL, TDF_NONE}
|
111
|
163 };
|
|
164
|
|
165 /* Flags used for -fopt-info groups. */
|
131
|
166 const kv_pair<optgroup_flags_t> optgroup_options[] =
|
111
|
167 {
|
|
168 {"ipa", OPTGROUP_IPA},
|
|
169 {"loop", OPTGROUP_LOOP},
|
|
170 {"inline", OPTGROUP_INLINE},
|
|
171 {"omp", OPTGROUP_OMP},
|
|
172 {"vec", OPTGROUP_VEC},
|
|
173 {"optall", OPTGROUP_ALL},
|
131
|
174 {NULL, OPTGROUP_NONE}
|
111
|
175 };
|
|
176
|
|
177 gcc::dump_manager::dump_manager ():
|
|
178 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
|
|
179 m_extra_dump_files (NULL),
|
|
180 m_extra_dump_files_in_use (0),
|
131
|
181 m_extra_dump_files_alloced (0),
|
|
182 m_optgroup_flags (OPTGROUP_NONE),
|
|
183 m_optinfo_flags (TDF_NONE),
|
|
184 m_optinfo_filename (NULL)
|
111
|
185 {
|
|
186 }
|
|
187
|
|
188 gcc::dump_manager::~dump_manager ()
|
|
189 {
|
131
|
190 free (m_optinfo_filename);
|
111
|
191 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
|
|
192 {
|
|
193 dump_file_info *dfi = &m_extra_dump_files[i];
|
|
194 /* suffix, swtch, glob are statically allocated for the entries
|
|
195 in dump_files, and for statistics, but are dynamically allocated
|
|
196 for those for passes. */
|
|
197 if (dfi->owns_strings)
|
|
198 {
|
|
199 XDELETEVEC (const_cast <char *> (dfi->suffix));
|
|
200 XDELETEVEC (const_cast <char *> (dfi->swtch));
|
|
201 XDELETEVEC (const_cast <char *> (dfi->glob));
|
|
202 }
|
|
203 /* These, if non-NULL, are always dynamically allocated. */
|
|
204 XDELETEVEC (const_cast <char *> (dfi->pfilename));
|
|
205 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
|
|
206 }
|
|
207 XDELETEVEC (m_extra_dump_files);
|
|
208 }
|
|
209
|
|
210 unsigned int
|
|
211 gcc::dump_manager::
|
|
212 dump_register (const char *suffix, const char *swtch, const char *glob,
|
131
|
213 dump_kind dkind, optgroup_flags_t optgroup_flags,
|
|
214 bool take_ownership)
|
111
|
215 {
|
|
216 int num = m_next_dump++;
|
|
217
|
|
218 size_t count = m_extra_dump_files_in_use++;
|
|
219
|
|
220 if (count >= m_extra_dump_files_alloced)
|
|
221 {
|
|
222 if (m_extra_dump_files_alloced == 0)
|
|
223 m_extra_dump_files_alloced = 512;
|
|
224 else
|
|
225 m_extra_dump_files_alloced *= 2;
|
|
226 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
|
|
227 m_extra_dump_files,
|
|
228 m_extra_dump_files_alloced);
|
|
229
|
|
230 /* Construct a new object in the space allocated above. */
|
|
231 new (m_extra_dump_files + count) dump_file_info ();
|
|
232 }
|
|
233 else
|
|
234 {
|
|
235 /* Zero out the already constructed object. */
|
|
236 m_extra_dump_files[count] = dump_file_info ();
|
|
237 }
|
|
238
|
|
239 m_extra_dump_files[count].suffix = suffix;
|
|
240 m_extra_dump_files[count].swtch = swtch;
|
|
241 m_extra_dump_files[count].glob = glob;
|
|
242 m_extra_dump_files[count].dkind = dkind;
|
|
243 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
|
|
244 m_extra_dump_files[count].num = num;
|
|
245 m_extra_dump_files[count].owns_strings = take_ownership;
|
|
246
|
|
247 return count + TDI_end;
|
|
248 }
|
|
249
|
|
250
|
|
251 /* Allow languages and middle-end to register their dumps before the
|
|
252 optimization passes. */
|
|
253
|
|
254 void
|
|
255 gcc::dump_manager::
|
|
256 register_dumps ()
|
|
257 {
|
|
258 lang_hooks.register_dumps (this);
|
|
259 /* If this assert fails, some FE registered more than
|
|
260 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
|
|
261 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
|
|
262 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
|
|
263 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
|
|
264 dump_files[TDI_original].num = m_next_dump++;
|
|
265 dump_files[TDI_gimple].num = m_next_dump++;
|
|
266 dump_files[TDI_nested].num = m_next_dump++;
|
|
267 }
|
|
268
|
|
269
|
|
270 /* Return the dump_file_info for the given phase. */
|
|
271
|
|
272 struct dump_file_info *
|
|
273 gcc::dump_manager::
|
|
274 get_dump_file_info (int phase) const
|
|
275 {
|
|
276 if (phase < TDI_end)
|
|
277 return &dump_files[phase];
|
|
278 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
|
|
279 return NULL;
|
|
280 else
|
|
281 return m_extra_dump_files + (phase - TDI_end);
|
|
282 }
|
|
283
|
|
284 /* Locate the dump_file_info with swtch equal to SWTCH,
|
|
285 or return NULL if no such dump_file_info exists. */
|
|
286
|
|
287 struct dump_file_info *
|
|
288 gcc::dump_manager::
|
|
289 get_dump_file_info_by_switch (const char *swtch) const
|
|
290 {
|
|
291 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
|
131
|
292 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
|
111
|
293 return &m_extra_dump_files[i];
|
|
294
|
|
295 /* Not found. */
|
|
296 return NULL;
|
|
297 }
|
|
298
|
|
299
|
|
300 /* Return the name of the dump file for the given phase.
|
|
301 The caller is responsible for calling free on the returned
|
|
302 buffer.
|
|
303 If the dump is not enabled, returns NULL. */
|
|
304
|
|
305 char *
|
|
306 gcc::dump_manager::
|
131
|
307 get_dump_file_name (int phase, int part) const
|
111
|
308 {
|
|
309 struct dump_file_info *dfi;
|
|
310
|
|
311 if (phase == TDI_none)
|
|
312 return NULL;
|
|
313
|
|
314 dfi = get_dump_file_info (phase);
|
|
315
|
131
|
316 return get_dump_file_name (dfi, part);
|
111
|
317 }
|
|
318
|
|
319 /* Return the name of the dump file for the given dump_file_info.
|
|
320 The caller is responsible for calling free on the returned
|
|
321 buffer.
|
|
322 If the dump is not enabled, returns NULL. */
|
|
323
|
|
324 char *
|
|
325 gcc::dump_manager::
|
131
|
326 get_dump_file_name (struct dump_file_info *dfi, int part) const
|
111
|
327 {
|
|
328 char dump_id[10];
|
|
329
|
|
330 gcc_assert (dfi);
|
|
331
|
|
332 if (dfi->pstate == 0)
|
|
333 return NULL;
|
|
334
|
|
335 /* If available, use the command line dump filename. */
|
|
336 if (dfi->pfilename)
|
|
337 return xstrdup (dfi->pfilename);
|
|
338
|
|
339 if (dfi->num < 0)
|
|
340 dump_id[0] = '\0';
|
|
341 else
|
|
342 {
|
|
343 /* (null), LANG, TREE, RTL, IPA. */
|
|
344 char suffix = " ltri"[dfi->dkind];
|
|
345
|
|
346 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
|
|
347 dump_id[0] = '\0';
|
|
348 }
|
|
349
|
131
|
350 if (part != -1)
|
|
351 {
|
|
352 char part_id[8];
|
|
353 snprintf (part_id, sizeof (part_id), ".%i", part);
|
|
354 return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
|
|
355 }
|
|
356 else
|
|
357 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
|
|
358 }
|
|
359
|
|
360 /* Open a dump file called FILENAME. Some filenames are special and
|
|
361 refer to the standard streams. TRUNC indicates whether this is the
|
|
362 first open (so the file should be truncated, rather than appended).
|
|
363 An error message is emitted in the event of failure. */
|
|
364
|
|
365 static FILE *
|
|
366 dump_open (const char *filename, bool trunc)
|
|
367 {
|
|
368 if (strcmp ("stderr", filename) == 0)
|
|
369 return stderr;
|
|
370
|
|
371 if (strcmp ("stdout", filename) == 0
|
|
372 || strcmp ("-", filename) == 0)
|
|
373 return stdout;
|
|
374
|
|
375 FILE *stream = fopen (filename, trunc ? "w" : "a");
|
|
376
|
|
377 if (!stream)
|
|
378 error ("could not open dump file %qs: %m", filename);
|
|
379 return stream;
|
111
|
380 }
|
|
381
|
|
382 /* For a given DFI, open an alternate dump filename (which could also
|
|
383 be a standard stream such as stdout/stderr). If the alternate dump
|
|
384 file cannot be opened, return NULL. */
|
|
385
|
|
386 static FILE *
|
|
387 dump_open_alternate_stream (struct dump_file_info *dfi)
|
|
388 {
|
|
389 if (!dfi->alt_filename)
|
|
390 return NULL;
|
|
391
|
|
392 if (dfi->alt_stream)
|
|
393 return dfi->alt_stream;
|
|
394
|
131
|
395 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
|
111
|
396
|
131
|
397 if (stream)
|
111
|
398 dfi->alt_state = 1;
|
|
399
|
|
400 return stream;
|
|
401 }
|
|
402
|
131
|
403 /* Construct a dump_user_location_t from STMT (using its location and
|
|
404 hotness). */
|
|
405
|
|
406 dump_user_location_t::dump_user_location_t (const gimple *stmt)
|
|
407 : m_count (), m_loc (UNKNOWN_LOCATION)
|
|
408 {
|
|
409 if (stmt)
|
|
410 {
|
|
411 if (stmt->bb)
|
|
412 m_count = stmt->bb->count;
|
|
413 m_loc = gimple_location (stmt);
|
|
414 }
|
|
415 }
|
|
416
|
|
417 /* Construct a dump_user_location_t from an RTL instruction (using its
|
|
418 location and hotness). */
|
|
419
|
|
420 dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
|
|
421 : m_count (), m_loc (UNKNOWN_LOCATION)
|
|
422 {
|
|
423 if (insn)
|
|
424 {
|
|
425 basic_block bb = BLOCK_FOR_INSN (insn);
|
|
426 if (bb)
|
|
427 m_count = bb->count;
|
|
428 m_loc = INSN_LOCATION (insn);
|
|
429 }
|
|
430 }
|
|
431
|
|
432 /* Construct from a function declaration. This one requires spelling out
|
|
433 to avoid accidentally constructing from other kinds of tree. */
|
|
434
|
|
435 dump_user_location_t
|
|
436 dump_user_location_t::from_function_decl (tree fndecl)
|
|
437 {
|
|
438 gcc_assert (fndecl);
|
|
439
|
|
440 // FIXME: profile count for function?
|
|
441 return dump_user_location_t (profile_count (),
|
|
442 DECL_SOURCE_LOCATION (fndecl));
|
|
443 }
|
|
444
|
|
445 /* Extract the MSG_* component from DUMP_KIND and return a string for use
|
|
446 as a prefix to dump messages.
|
|
447 These match the strings in optinfo_verbosity_options and thus the
|
|
448 "OPTIONS" within "-fopt-info-OPTIONS". */
|
|
449
|
|
450 static const char *
|
|
451 kind_as_string (dump_flags_t dump_kind)
|
|
452 {
|
|
453 switch (dump_kind & MSG_ALL_KINDS)
|
|
454 {
|
|
455 default:
|
|
456 gcc_unreachable ();
|
|
457 case MSG_OPTIMIZED_LOCATIONS:
|
|
458 return "optimized";
|
|
459 case MSG_MISSED_OPTIMIZATION:
|
|
460 return "missed";
|
|
461 case MSG_NOTE:
|
|
462 return "note";
|
|
463 }
|
|
464 }
|
|
465
|
111
|
466 /* Print source location on DFILE if enabled. */
|
|
467
|
131
|
468 static void
|
111
|
469 dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
|
|
470 {
|
|
471 if (dump_kind)
|
|
472 {
|
|
473 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
|
131
|
474 fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc),
|
111
|
475 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
|
|
476 else if (current_function_decl)
|
131
|
477 fprintf (dfile, "%s:%d:%d: ",
|
111
|
478 DECL_SOURCE_FILE (current_function_decl),
|
|
479 DECL_SOURCE_LINE (current_function_decl),
|
|
480 DECL_SOURCE_COLUMN (current_function_decl));
|
131
|
481 fprintf (dfile, "%s: ", kind_as_string (dump_kind));
|
|
482 /* Indentation based on scope depth. */
|
|
483 fprintf (dfile, "%*s", get_dump_scope_depth (), "");
|
|
484 }
|
|
485 }
|
|
486
|
|
487 /* Print source location to PP if enabled. */
|
|
488
|
|
489 static void
|
|
490 dump_loc (dump_flags_t dump_kind, pretty_printer *pp, source_location loc)
|
|
491 {
|
|
492 if (dump_kind)
|
|
493 {
|
|
494 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
|
|
495 pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc),
|
|
496 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
|
|
497 else if (current_function_decl)
|
|
498 pp_printf (pp, "%s:%d:%d: ",
|
|
499 DECL_SOURCE_FILE (current_function_decl),
|
|
500 DECL_SOURCE_LINE (current_function_decl),
|
|
501 DECL_SOURCE_COLUMN (current_function_decl));
|
|
502 pp_printf (pp, "%s: ", kind_as_string (dump_kind));
|
|
503 /* Indentation based on scope depth. */
|
|
504 for (unsigned i = 0; i < get_dump_scope_depth (); i++)
|
|
505 pp_character (pp, ' ');
|
|
506 }
|
|
507 }
|
|
508
|
|
509 /* Implementation of dump_context member functions. */
|
|
510
|
|
511 /* dump_context's dtor. */
|
|
512
|
|
513 dump_context::~dump_context ()
|
|
514 {
|
|
515 delete m_pending;
|
|
516 }
|
|
517
|
|
518 /* Update the "dumps_are_enabled" global; to be called whenever dump_file
|
|
519 or alt_dump_file change, or when changing dump_context in selftests. */
|
|
520
|
|
521 void
|
|
522 dump_context::refresh_dumps_are_enabled ()
|
|
523 {
|
|
524 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
|
|
525 || m_test_pp);
|
|
526 }
|
|
527
|
|
528 /* Determine if a message of kind DUMP_KIND and at the current scope depth
|
|
529 should be printed.
|
|
530
|
|
531 Only show messages that match FILTER both on their kind *and*
|
|
532 their priority. */
|
|
533
|
|
534 bool
|
|
535 dump_context::apply_dump_filter_p (dump_flags_t dump_kind,
|
|
536 dump_flags_t filter) const
|
|
537 {
|
|
538 /* Few messages, if any, have an explicit MSG_PRIORITY.
|
|
539 If DUMP_KIND does, we'll use it.
|
|
540 Otherwise, generate an implicit priority value for the message based
|
|
541 on the current scope depth.
|
|
542 Messages at the top-level scope are MSG_PRIORITY_USER_FACING,
|
|
543 whereas those in nested scopes are MSG_PRIORITY_INTERNALS. */
|
|
544 if (!(dump_kind & MSG_ALL_PRIORITIES))
|
|
545 {
|
|
546 dump_flags_t implicit_priority
|
|
547 = (m_scope_depth > 0
|
|
548 ? MSG_PRIORITY_INTERNALS
|
|
549 : MSG_PRIORITY_USER_FACING);
|
|
550 dump_kind |= implicit_priority;
|
|
551 }
|
|
552
|
|
553 return (dump_kind & (filter & MSG_ALL_KINDS)
|
|
554 && dump_kind & (filter & MSG_ALL_PRIORITIES));
|
|
555 }
|
|
556
|
|
557 /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
|
|
558 If optinfos are enabled, begin a new optinfo. */
|
|
559
|
|
560 void
|
|
561 dump_context::dump_loc (dump_flags_t dump_kind, const dump_location_t &loc)
|
|
562 {
|
|
563 end_any_optinfo ();
|
|
564
|
|
565 dump_loc_immediate (dump_kind, loc);
|
|
566
|
|
567 if (optinfo_enabled_p ())
|
|
568 {
|
|
569 optinfo &info = begin_next_optinfo (loc);
|
|
570 info.handle_dump_file_kind (dump_kind);
|
111
|
571 }
|
|
572 }
|
|
573
|
131
|
574 /* As dump_loc above, but without starting a new optinfo. */
|
|
575
|
|
576 void
|
|
577 dump_context::dump_loc_immediate (dump_flags_t dump_kind,
|
|
578 const dump_location_t &loc)
|
|
579 {
|
|
580 location_t srcloc = loc.get_location_t ();
|
|
581
|
|
582 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
|
|
583 ::dump_loc (dump_kind, dump_file, srcloc);
|
|
584
|
|
585 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
|
|
586 ::dump_loc (dump_kind, alt_dump_file, srcloc);
|
|
587
|
|
588 /* Support for temp_dump_context in selftests. */
|
|
589 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
|
|
590 ::dump_loc (dump_kind, m_test_pp, srcloc);
|
|
591 }
|
|
592
|
|
593 /* Make an item for the given dump call, equivalent to print_gimple_stmt. */
|
|
594
|
|
595 static optinfo_item *
|
|
596 make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
|
|
597 {
|
|
598 pretty_printer pp;
|
|
599 pp_needs_newline (&pp) = true;
|
|
600 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
|
|
601 pp_newline (&pp);
|
|
602
|
|
603 optinfo_item *item
|
|
604 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
|
|
605 xstrdup (pp_formatted_text (&pp)));
|
|
606 return item;
|
|
607 }
|
|
608
|
|
609 /* Dump gimple statement GS with SPC indentation spaces and
|
|
610 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
|
|
611
|
|
612 void
|
|
613 dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
|
|
614 dump_flags_t extra_dump_flags,
|
|
615 gimple *gs, int spc)
|
|
616 {
|
|
617 optinfo_item *item
|
|
618 = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
|
|
619 emit_item (item, dump_kind);
|
|
620
|
|
621 if (optinfo_enabled_p ())
|
|
622 {
|
|
623 optinfo &info = ensure_pending_optinfo ();
|
|
624 info.handle_dump_file_kind (dump_kind);
|
|
625 info.add_item (item);
|
|
626 }
|
|
627 else
|
|
628 delete item;
|
|
629 }
|
|
630
|
|
631 /* Similar to dump_gimple_stmt, except additionally print source location. */
|
|
632
|
|
633 void
|
|
634 dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
|
|
635 const dump_location_t &loc,
|
|
636 dump_flags_t extra_dump_flags,
|
|
637 gimple *gs, int spc)
|
|
638 {
|
|
639 dump_loc (dump_kind, loc);
|
|
640 dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
|
|
641 }
|
|
642
|
|
643 /* Make an item for the given dump call, equivalent to print_gimple_expr. */
|
|
644
|
|
645 static optinfo_item *
|
|
646 make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
|
|
647 {
|
|
648 dump_flags |= TDF_RHS_ONLY;
|
|
649 pretty_printer pp;
|
|
650 pp_needs_newline (&pp) = true;
|
|
651 pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
|
|
652
|
|
653 optinfo_item *item
|
|
654 = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
|
|
655 xstrdup (pp_formatted_text (&pp)));
|
|
656 return item;
|
|
657 }
|
|
658
|
|
659 /* Dump gimple statement GS with SPC indentation spaces and
|
|
660 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
|
|
661 Do not terminate with a newline or semicolon. */
|
|
662
|
|
663 void
|
|
664 dump_context::dump_gimple_expr (dump_flags_t dump_kind,
|
|
665 dump_flags_t extra_dump_flags,
|
|
666 gimple *gs, int spc)
|
|
667 {
|
|
668 optinfo_item *item
|
|
669 = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
|
|
670 emit_item (item, dump_kind);
|
|
671
|
|
672 if (optinfo_enabled_p ())
|
|
673 {
|
|
674 optinfo &info = ensure_pending_optinfo ();
|
|
675 info.handle_dump_file_kind (dump_kind);
|
|
676 info.add_item (item);
|
|
677 }
|
|
678 else
|
|
679 delete item;
|
|
680 }
|
|
681
|
|
682 /* Similar to dump_gimple_expr, except additionally print source location. */
|
|
683
|
|
684 void
|
|
685 dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind,
|
|
686 const dump_location_t &loc,
|
|
687 dump_flags_t extra_dump_flags,
|
|
688 gimple *gs,
|
|
689 int spc)
|
|
690 {
|
|
691 dump_loc (dump_kind, loc);
|
|
692 dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
|
|
693 }
|
|
694
|
|
695 /* Make an item for the given dump call, equivalent to print_generic_expr. */
|
|
696
|
|
697 static optinfo_item *
|
|
698 make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
|
|
699 {
|
|
700 pretty_printer pp;
|
|
701 pp_needs_newline (&pp) = true;
|
|
702 pp_translate_identifiers (&pp) = false;
|
|
703 dump_generic_node (&pp, node, 0, dump_flags, false);
|
|
704
|
|
705 location_t loc = UNKNOWN_LOCATION;
|
|
706 if (EXPR_HAS_LOCATION (node))
|
|
707 loc = EXPR_LOCATION (node);
|
|
708
|
|
709 optinfo_item *item
|
|
710 = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
|
|
711 xstrdup (pp_formatted_text (&pp)));
|
|
712 return item;
|
|
713 }
|
|
714
|
|
715 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
|
|
716 DUMP_KIND is enabled. */
|
|
717
|
|
718 void
|
|
719 dump_context::dump_generic_expr (dump_flags_t dump_kind,
|
|
720 dump_flags_t extra_dump_flags,
|
|
721 tree t)
|
|
722 {
|
|
723 optinfo_item *item
|
|
724 = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
|
|
725 emit_item (item, dump_kind);
|
|
726
|
|
727 if (optinfo_enabled_p ())
|
|
728 {
|
|
729 optinfo &info = ensure_pending_optinfo ();
|
|
730 info.handle_dump_file_kind (dump_kind);
|
|
731 info.add_item (item);
|
|
732 }
|
|
733 else
|
|
734 delete item;
|
|
735 }
|
|
736
|
|
737
|
|
738 /* Similar to dump_generic_expr, except additionally print the source
|
|
739 location. */
|
|
740
|
|
741 void
|
|
742 dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
|
|
743 const dump_location_t &loc,
|
|
744 dump_flags_t extra_dump_flags,
|
|
745 tree t)
|
|
746 {
|
|
747 dump_loc (dump_kind, loc);
|
|
748 dump_generic_expr (dump_kind, extra_dump_flags, t);
|
|
749 }
|
|
750
|
|
751 /* dump_pretty_printer's ctor. */
|
|
752
|
|
753 dump_pretty_printer::dump_pretty_printer (dump_context *context,
|
|
754 dump_flags_t dump_kind)
|
|
755 : pretty_printer (), m_context (context), m_dump_kind (dump_kind),
|
|
756 m_stashed_items ()
|
|
757 {
|
|
758 pp_format_decoder (this) = format_decoder_cb;
|
|
759 }
|
|
760
|
|
761 /* Phase 3 of formatting; compare with pp_output_formatted_text.
|
|
762
|
|
763 Emit optinfo_item instances for the various formatted chunks from phases
|
|
764 1 and 2 (i.e. pp_format).
|
|
765
|
|
766 Some chunks may already have had their items built (during decode_format).
|
|
767 These chunks have been stashed into m_stashed_items; we emit them here.
|
|
768
|
|
769 For all other purely textual chunks, they are printed into
|
|
770 buffer->formatted_obstack, and then emitted as a textual optinfo_item.
|
|
771 This consolidates multiple adjacent text chunks into a single text
|
|
772 optinfo_item. */
|
|
773
|
|
774 void
|
|
775 dump_pretty_printer::emit_items (optinfo *dest)
|
|
776 {
|
|
777 output_buffer *buffer = pp_buffer (this);
|
|
778 struct chunk_info *chunk_array = buffer->cur_chunk_array;
|
|
779 const char **args = chunk_array->args;
|
|
780
|
|
781 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
|
|
782 gcc_assert (buffer->line_length == 0);
|
|
783
|
|
784 unsigned stashed_item_idx = 0;
|
|
785 for (unsigned chunk = 0; args[chunk]; chunk++)
|
|
786 {
|
|
787 if (stashed_item_idx < m_stashed_items.length ()
|
|
788 && args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr)
|
|
789 {
|
|
790 emit_any_pending_textual_chunks (dest);
|
|
791 /* This chunk has a stashed item: use it. */
|
|
792 emit_item (m_stashed_items[stashed_item_idx++].item, dest);
|
|
793 }
|
|
794 else
|
|
795 /* This chunk is purely textual. Print it (to
|
|
796 buffer->formatted_obstack), so that we can consolidate adjacent
|
|
797 chunks into one textual optinfo_item. */
|
|
798 pp_string (this, args[chunk]);
|
|
799 }
|
|
800
|
|
801 emit_any_pending_textual_chunks (dest);
|
|
802
|
|
803 /* Ensure that we consumed all of stashed_items. */
|
|
804 gcc_assert (stashed_item_idx == m_stashed_items.length ());
|
|
805
|
|
806 /* Deallocate the chunk structure and everything after it (i.e. the
|
|
807 associated series of formatted strings). */
|
|
808 buffer->cur_chunk_array = chunk_array->prev;
|
|
809 obstack_free (&buffer->chunk_obstack, chunk_array);
|
|
810 }
|
|
811
|
|
812 /* Subroutine of dump_pretty_printer::emit_items
|
|
813 for consolidating multiple adjacent pure-text chunks into single
|
|
814 optinfo_items (in phase 3). */
|
|
815
|
|
816 void
|
|
817 dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest)
|
|
818 {
|
|
819 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
|
|
820
|
|
821 /* Don't emit an item if the pending text is empty. */
|
|
822 if (output_buffer_last_position_in_text (buffer) == NULL)
|
|
823 return;
|
|
824
|
|
825 char *formatted_text = xstrdup (pp_formatted_text (this));
|
|
826 optinfo_item *item
|
|
827 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
|
|
828 formatted_text);
|
|
829 emit_item (item, dest);
|
|
830
|
|
831 /* Clear the pending text by unwinding formatted_text back to the start
|
|
832 of the buffer (without deallocating). */
|
|
833 obstack_free (&buffer->formatted_obstack,
|
|
834 buffer->formatted_obstack.object_base);
|
|
835 }
|
|
836
|
|
837 /* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
|
|
838 to DEST; otherwise delete ITEM. */
|
|
839
|
|
840 void
|
|
841 dump_pretty_printer::emit_item (optinfo_item *item, optinfo *dest)
|
|
842 {
|
|
843 m_context->emit_item (item, m_dump_kind);
|
|
844 if (dest)
|
|
845 dest->add_item (item);
|
|
846 else
|
|
847 delete item;
|
|
848 }
|
|
849
|
|
850 /* Record that ITEM (generated in phase 2 of formatting) is to be used for
|
|
851 the chunk at BUFFER_PTR in phase 3 (by emit_items). */
|
|
852
|
|
853 void
|
|
854 dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item)
|
|
855 {
|
|
856 gcc_assert (buffer_ptr);
|
|
857 gcc_assert (item);
|
|
858
|
|
859 m_stashed_items.safe_push (stashed_item (buffer_ptr, item));
|
|
860 }
|
|
861
|
|
862 /* pp_format_decoder callback for dump_pretty_printer, and thus for
|
|
863 dump_printf and dump_printf_loc.
|
|
864
|
|
865 A wrapper around decode_format, for type-safety. */
|
|
866
|
|
867 bool
|
|
868 dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
|
|
869 const char *spec, int /*precision*/,
|
|
870 bool /*wide*/, bool /*set_locus*/,
|
|
871 bool /*verbose*/, bool */*quoted*/,
|
|
872 const char **buffer_ptr)
|
|
873 {
|
|
874 dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
|
|
875 return opp->decode_format (text, spec, buffer_ptr);
|
|
876 }
|
|
877
|
|
878 /* Format decoder for dump_pretty_printer, and thus for dump_printf and
|
|
879 dump_printf_loc.
|
|
880
|
|
881 Supported format codes (in addition to the standard pretty_printer ones)
|
|
882 are:
|
|
883
|
|
884 %E: gimple *:
|
|
885 Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
|
|
886 %G: gimple *:
|
|
887 Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
|
|
888 %T: tree:
|
|
889 Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
|
|
890
|
|
891 FIXME: add symtab_node?
|
|
892
|
|
893 These format codes build optinfo_item instances, thus capturing metadata
|
|
894 about the arguments being dumped, as well as the textual output. */
|
|
895
|
|
896 bool
|
|
897 dump_pretty_printer::decode_format (text_info *text, const char *spec,
|
|
898 const char **buffer_ptr)
|
|
899 {
|
|
900 /* Various format codes that imply making an optinfo_item and stashed it
|
|
901 for later use (to capture metadata, rather than plain text). */
|
|
902 switch (*spec)
|
|
903 {
|
|
904 case 'E':
|
|
905 {
|
|
906 gimple *stmt = va_arg (*text->args_ptr, gimple *);
|
|
907
|
|
908 /* Make an item for the stmt, and stash it. */
|
|
909 optinfo_item *item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
|
|
910 stash_item (buffer_ptr, item);
|
|
911 return true;
|
|
912 }
|
|
913
|
|
914 case 'G':
|
|
915 {
|
|
916 gimple *stmt = va_arg (*text->args_ptr, gimple *);
|
|
917
|
|
918 /* Make an item for the stmt, and stash it. */
|
|
919 optinfo_item *item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
|
|
920 stash_item (buffer_ptr, item);
|
|
921 return true;
|
|
922 }
|
|
923
|
|
924 case 'T':
|
|
925 {
|
|
926 tree t = va_arg (*text->args_ptr, tree);
|
|
927
|
|
928 /* Make an item for the tree, and stash it. */
|
|
929 optinfo_item *item = make_item_for_dump_generic_expr (t, TDF_SLIM);
|
|
930 stash_item (buffer_ptr, item);
|
|
931 return true;
|
|
932 }
|
|
933
|
|
934 default:
|
|
935 return false;
|
|
936 }
|
|
937 }
|
|
938
|
|
939 /* Output a formatted message using FORMAT on appropriate dump streams. */
|
|
940
|
|
941 void
|
|
942 dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
|
|
943 va_list *ap)
|
|
944 {
|
|
945 dump_pretty_printer pp (this, dump_kind);
|
|
946
|
|
947 text_info text;
|
|
948 text.err_no = errno;
|
|
949 text.args_ptr = ap;
|
|
950 text.format_spec = format;
|
|
951
|
|
952 /* Phases 1 and 2, using pp_format. */
|
|
953 pp_format (&pp, &text);
|
|
954
|
|
955 /* Phase 3. */
|
|
956 if (optinfo_enabled_p ())
|
|
957 {
|
|
958 optinfo &info = ensure_pending_optinfo ();
|
|
959 info.handle_dump_file_kind (dump_kind);
|
|
960 pp.emit_items (&info);
|
|
961 }
|
|
962 else
|
|
963 pp.emit_items (NULL);
|
|
964 }
|
|
965
|
|
966 /* Similar to dump_printf, except source location is also printed, and
|
|
967 dump location captured. */
|
|
968
|
|
969 void
|
|
970 dump_context::dump_printf_loc_va (dump_flags_t dump_kind,
|
|
971 const dump_location_t &loc,
|
|
972 const char *format, va_list *ap)
|
|
973 {
|
|
974 dump_loc (dump_kind, loc);
|
|
975 dump_printf_va (dump_kind, format, ap);
|
|
976 }
|
|
977
|
|
978 /* Make an item for the given dump call, equivalent to print_dec. */
|
|
979
|
|
980 template<unsigned int N, typename C>
|
|
981 static optinfo_item *
|
|
982 make_item_for_dump_dec (const poly_int<N, C> &value)
|
|
983 {
|
|
984 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
|
|
985 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
|
|
986
|
|
987 pretty_printer pp;
|
|
988
|
|
989 if (value.is_constant ())
|
|
990 pp_wide_int (&pp, value.coeffs[0], sgn);
|
|
991 else
|
|
992 {
|
|
993 pp_character (&pp, '[');
|
|
994 for (unsigned int i = 0; i < N; ++i)
|
|
995 {
|
|
996 pp_wide_int (&pp, value.coeffs[i], sgn);
|
|
997 pp_character (&pp, i == N - 1 ? ']' : ',');
|
|
998 }
|
|
999 }
|
|
1000
|
|
1001 optinfo_item *item
|
|
1002 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
|
|
1003 xstrdup (pp_formatted_text (&pp)));
|
|
1004 return item;
|
|
1005 }
|
|
1006
|
|
1007 /* Output VALUE in decimal to appropriate dump streams. */
|
|
1008
|
|
1009 template<unsigned int N, typename C>
|
|
1010 void
|
|
1011 dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
|
|
1012 {
|
|
1013 optinfo_item *item = make_item_for_dump_dec (value);
|
|
1014 emit_item (item, dump_kind);
|
|
1015
|
|
1016 if (optinfo_enabled_p ())
|
|
1017 {
|
|
1018 optinfo &info = ensure_pending_optinfo ();
|
|
1019 info.handle_dump_file_kind (dump_kind);
|
|
1020 info.add_item (item);
|
|
1021 }
|
|
1022 else
|
|
1023 delete item;
|
|
1024 }
|
|
1025
|
|
1026 /* Make an item for the given dump call. */
|
|
1027
|
|
1028 static optinfo_item *
|
|
1029 make_item_for_dump_symtab_node (symtab_node *node)
|
|
1030 {
|
|
1031 location_t loc = DECL_SOURCE_LOCATION (node->decl);
|
|
1032 optinfo_item *item
|
|
1033 = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
|
|
1034 xstrdup (node->dump_name ()));
|
|
1035 return item;
|
|
1036 }
|
|
1037
|
|
1038 /* Output the name of NODE on appropriate dump streams. */
|
|
1039
|
|
1040 void
|
|
1041 dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
|
|
1042 {
|
|
1043 optinfo_item *item = make_item_for_dump_symtab_node (node);
|
|
1044 emit_item (item, dump_kind);
|
|
1045
|
|
1046 if (optinfo_enabled_p ())
|
|
1047 {
|
|
1048 optinfo &info = ensure_pending_optinfo ();
|
|
1049 info.handle_dump_file_kind (dump_kind);
|
|
1050 info.add_item (item);
|
|
1051 }
|
|
1052 else
|
|
1053 delete item;
|
|
1054 }
|
|
1055
|
|
1056 /* Get the current dump scope-nesting depth.
|
|
1057 For use by -fopt-info (for showing nesting via indentation). */
|
|
1058
|
|
1059 unsigned int
|
|
1060 dump_context::get_scope_depth () const
|
|
1061 {
|
|
1062 return m_scope_depth;
|
|
1063 }
|
|
1064
|
|
1065 /* Push a nested dump scope.
|
|
1066 Increment the scope depth.
|
|
1067 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
|
|
1068 destination, if any.
|
|
1069 Emit a "scope" optinfo if optinfos are enabled. */
|
|
1070
|
|
1071 void
|
|
1072 dump_context::begin_scope (const char *name, const dump_location_t &loc)
|
|
1073 {
|
|
1074 m_scope_depth++;
|
|
1075
|
|
1076 if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags))
|
|
1077 ::dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
|
|
1078
|
|
1079 if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags))
|
|
1080 ::dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
|
|
1081
|
|
1082 /* Support for temp_dump_context in selftests. */
|
|
1083 if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
|
|
1084 ::dump_loc (MSG_NOTE, m_test_pp, loc.get_location_t ());
|
|
1085
|
|
1086 pretty_printer pp;
|
|
1087 pp_printf (&pp, "=== %s ===\n", name);
|
|
1088 optinfo_item *item
|
|
1089 = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
|
|
1090 xstrdup (pp_formatted_text (&pp)));
|
|
1091 emit_item (item, MSG_NOTE);
|
|
1092
|
|
1093 if (optinfo_enabled_p ())
|
|
1094 {
|
|
1095 optinfo &info = begin_next_optinfo (loc);
|
|
1096 info.m_kind = OPTINFO_KIND_SCOPE;
|
|
1097 info.add_item (item);
|
|
1098 }
|
|
1099 else
|
|
1100 delete item;
|
|
1101 }
|
|
1102
|
|
1103 /* Pop a nested dump scope. */
|
|
1104
|
|
1105 void
|
|
1106 dump_context::end_scope ()
|
|
1107 {
|
|
1108 end_any_optinfo ();
|
|
1109 m_scope_depth--;
|
|
1110 optimization_records_maybe_pop_dump_scope ();
|
|
1111 }
|
|
1112
|
|
1113 /* Return the optinfo currently being accumulated, creating one if
|
|
1114 necessary. */
|
|
1115
|
|
1116 optinfo &
|
|
1117 dump_context::ensure_pending_optinfo ()
|
|
1118 {
|
|
1119 if (!m_pending)
|
|
1120 return begin_next_optinfo (dump_location_t (dump_user_location_t ()));
|
|
1121 return *m_pending;
|
|
1122 }
|
|
1123
|
|
1124 /* Start a new optinfo and return it, ending any optinfo that was already
|
|
1125 accumulated. */
|
|
1126
|
|
1127 optinfo &
|
|
1128 dump_context::begin_next_optinfo (const dump_location_t &loc)
|
|
1129 {
|
|
1130 end_any_optinfo ();
|
|
1131 gcc_assert (m_pending == NULL);
|
|
1132 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
|
|
1133 return *m_pending;
|
|
1134 }
|
|
1135
|
|
1136 /* End any optinfo that has been accumulated within this context; emitting
|
|
1137 it to any destinations as appropriate, such as optimization records. */
|
|
1138
|
|
1139 void
|
|
1140 dump_context::end_any_optinfo ()
|
|
1141 {
|
|
1142 if (m_pending)
|
|
1143 m_pending->emit ();
|
|
1144 delete m_pending;
|
|
1145 m_pending = NULL;
|
|
1146 }
|
|
1147
|
|
1148 /* Emit ITEM to all item destinations (those that don't require
|
|
1149 consolidation into optinfo instances). */
|
|
1150
|
|
1151 void
|
|
1152 dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind)
|
|
1153 {
|
|
1154 if (dump_file && apply_dump_filter_p (dump_kind, pflags))
|
|
1155 fprintf (dump_file, "%s", item->get_text ());
|
|
1156
|
|
1157 if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
|
|
1158 fprintf (alt_dump_file, "%s", item->get_text ());
|
|
1159
|
|
1160 /* Support for temp_dump_context in selftests. */
|
|
1161 if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
|
|
1162 pp_string (m_test_pp, item->get_text ());
|
|
1163 }
|
|
1164
|
|
1165 /* The current singleton dump_context, and its default. */
|
|
1166
|
|
1167 dump_context *dump_context::s_current = &dump_context::s_default;
|
|
1168 dump_context dump_context::s_default;
|
|
1169
|
|
1170 /* Implementation of dump_* API calls, calling into dump_context
|
|
1171 member functions. */
|
|
1172
|
111
|
1173 /* Dump gimple statement GS with SPC indentation spaces and
|
|
1174 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
|
|
1175
|
|
1176 void
|
|
1177 dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
|
|
1178 gimple *gs, int spc)
|
|
1179 {
|
131
|
1180 dump_context::get ().dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
|
111
|
1181 }
|
|
1182
|
|
1183 /* Similar to dump_gimple_stmt, except additionally print source location. */
|
|
1184
|
|
1185 void
|
131
|
1186 dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
|
111
|
1187 dump_flags_t extra_dump_flags, gimple *gs, int spc)
|
|
1188 {
|
131
|
1189 dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc, extra_dump_flags,
|
|
1190 gs, spc);
|
|
1191 }
|
|
1192
|
|
1193 /* Dump gimple statement GS with SPC indentation spaces and
|
|
1194 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
|
|
1195 Do not terminate with a newline or semicolon. */
|
111
|
1196
|
131
|
1197 void
|
|
1198 dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
|
|
1199 gimple *gs, int spc)
|
|
1200 {
|
|
1201 dump_context::get ().dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
|
|
1202 }
|
|
1203
|
|
1204 /* Similar to dump_gimple_expr, except additionally print source location. */
|
|
1205
|
|
1206 void
|
|
1207 dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
|
|
1208 dump_flags_t extra_dump_flags, gimple *gs, int spc)
|
|
1209 {
|
|
1210 dump_context::get ().dump_gimple_expr_loc (dump_kind, loc, extra_dump_flags,
|
|
1211 gs, spc);
|
111
|
1212 }
|
|
1213
|
|
1214 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
|
|
1215 DUMP_KIND is enabled. */
|
|
1216
|
|
1217 void
|
|
1218 dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
|
|
1219 tree t)
|
|
1220 {
|
131
|
1221 dump_context::get ().dump_generic_expr (dump_kind, extra_dump_flags, t);
|
111
|
1222 }
|
|
1223
|
|
1224 /* Similar to dump_generic_expr, except additionally print the source
|
|
1225 location. */
|
|
1226
|
|
1227 void
|
131
|
1228 dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
|
111
|
1229 dump_flags_t extra_dump_flags, tree t)
|
|
1230 {
|
131
|
1231 dump_context::get ().dump_generic_expr_loc (dump_kind, loc, extra_dump_flags,
|
|
1232 t);
|
111
|
1233 }
|
|
1234
|
|
1235 /* Output a formatted message using FORMAT on appropriate dump streams. */
|
|
1236
|
|
1237 void
|
|
1238 dump_printf (dump_flags_t dump_kind, const char *format, ...)
|
|
1239 {
|
131
|
1240 va_list ap;
|
|
1241 va_start (ap, format);
|
|
1242 dump_context::get ().dump_printf_va (dump_kind, format, &ap);
|
|
1243 va_end (ap);
|
|
1244 }
|
|
1245
|
|
1246 /* Similar to dump_printf, except source location is also printed, and
|
|
1247 dump location captured. */
|
111
|
1248
|
131
|
1249 void
|
|
1250 dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
|
|
1251 const char *format, ...)
|
|
1252 {
|
|
1253 va_list ap;
|
|
1254 va_start (ap, format);
|
|
1255 dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, &ap);
|
|
1256 va_end (ap);
|
111
|
1257 }
|
|
1258
|
131
|
1259 /* Output VALUE in decimal to appropriate dump streams. */
|
|
1260
|
|
1261 template<unsigned int N, typename C>
|
|
1262 void
|
|
1263 dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
|
|
1264 {
|
|
1265 dump_context::get ().dump_dec (dump_kind, value);
|
|
1266 }
|
|
1267
|
|
1268 template void dump_dec (dump_flags_t, const poly_uint16 &);
|
|
1269 template void dump_dec (dump_flags_t, const poly_int64 &);
|
|
1270 template void dump_dec (dump_flags_t, const poly_uint64 &);
|
|
1271 template void dump_dec (dump_flags_t, const poly_offset_int &);
|
|
1272 template void dump_dec (dump_flags_t, const poly_widest_int &);
|
|
1273
|
|
1274 void
|
|
1275 dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
|
|
1276 {
|
|
1277 if (dump_file
|
|
1278 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
|
|
1279 print_dec (value, dump_file, sgn);
|
|
1280
|
|
1281 if (alt_dump_file
|
|
1282 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
|
|
1283 print_dec (value, alt_dump_file, sgn);
|
|
1284 }
|
|
1285
|
|
1286 /* Output VALUE in hexadecimal to appropriate dump streams. */
|
111
|
1287
|
|
1288 void
|
131
|
1289 dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
|
|
1290 {
|
|
1291 if (dump_file
|
|
1292 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
|
|
1293 print_hex (value, dump_file);
|
|
1294
|
|
1295 if (alt_dump_file
|
|
1296 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
|
|
1297 print_hex (value, alt_dump_file);
|
|
1298 }
|
|
1299
|
|
1300 /* Emit and delete the currently pending optinfo, if there is one,
|
|
1301 without the caller needing to know about class dump_context. */
|
|
1302
|
|
1303 void
|
|
1304 dumpfile_ensure_any_optinfo_are_flushed ()
|
|
1305 {
|
|
1306 dump_context::get().end_any_optinfo ();
|
|
1307 }
|
|
1308
|
|
1309 /* Output the name of NODE on appropriate dump streams. */
|
|
1310
|
|
1311 void
|
|
1312 dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
|
111
|
1313 {
|
131
|
1314 dump_context::get ().dump_symtab_node (dump_kind, node);
|
|
1315 }
|
|
1316
|
|
1317 /* Get the current dump scope-nesting depth.
|
|
1318 For use by -fopt-info (for showing nesting via indentation). */
|
|
1319
|
|
1320 unsigned int
|
|
1321 get_dump_scope_depth ()
|
|
1322 {
|
|
1323 return dump_context::get ().get_scope_depth ();
|
|
1324 }
|
111
|
1325
|
131
|
1326 /* Push a nested dump scope.
|
|
1327 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
|
|
1328 destination, if any.
|
|
1329 Emit a "scope" opinfo if optinfos are enabled.
|
|
1330 Increment the scope depth. */
|
|
1331
|
|
1332 void
|
|
1333 dump_begin_scope (const char *name, const dump_location_t &loc)
|
|
1334 {
|
|
1335 dump_context::get ().begin_scope (name, loc);
|
|
1336 }
|
|
1337
|
|
1338 /* Pop a nested dump scope. */
|
|
1339
|
|
1340 void
|
|
1341 dump_end_scope ()
|
|
1342 {
|
|
1343 dump_context::get ().end_scope ();
|
111
|
1344 }
|
|
1345
|
|
1346 /* Start a dump for PHASE. Store user-supplied dump flags in
|
|
1347 *FLAG_PTR. Return the number of streams opened. Set globals
|
|
1348 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
|
|
1349 set dump_flags appropriately for both pass dump stream and
|
|
1350 -fopt-info stream. */
|
|
1351
|
|
1352 int
|
|
1353 gcc::dump_manager::
|
|
1354 dump_start (int phase, dump_flags_t *flag_ptr)
|
|
1355 {
|
|
1356 int count = 0;
|
|
1357 char *name;
|
|
1358 struct dump_file_info *dfi;
|
|
1359 FILE *stream;
|
|
1360 if (phase == TDI_none || !dump_phase_enabled_p (phase))
|
|
1361 return 0;
|
|
1362
|
|
1363 dfi = get_dump_file_info (phase);
|
|
1364 name = get_dump_file_name (phase);
|
|
1365 if (name)
|
|
1366 {
|
131
|
1367 stream = dump_open (name, dfi->pstate < 0);
|
|
1368 if (stream)
|
111
|
1369 {
|
|
1370 dfi->pstate = 1;
|
|
1371 count++;
|
|
1372 }
|
|
1373 free (name);
|
|
1374 dfi->pstream = stream;
|
131
|
1375 set_dump_file (dfi->pstream);
|
111
|
1376 /* Initialize current dump flags. */
|
|
1377 pflags = dfi->pflags;
|
|
1378 }
|
|
1379
|
|
1380 stream = dump_open_alternate_stream (dfi);
|
|
1381 if (stream)
|
|
1382 {
|
|
1383 dfi->alt_stream = stream;
|
|
1384 count++;
|
131
|
1385 set_alt_dump_file (dfi->alt_stream);
|
111
|
1386 /* Initialize current -fopt-info flags. */
|
|
1387 alt_flags = dfi->alt_flags;
|
|
1388 }
|
|
1389
|
|
1390 if (flag_ptr)
|
|
1391 *flag_ptr = dfi->pflags;
|
|
1392
|
|
1393 return count;
|
|
1394 }
|
|
1395
|
|
1396 /* Finish a tree dump for PHASE and close associated dump streams. Also
|
|
1397 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
|
|
1398
|
|
1399 void
|
|
1400 gcc::dump_manager::
|
|
1401 dump_finish (int phase)
|
|
1402 {
|
|
1403 struct dump_file_info *dfi;
|
|
1404
|
|
1405 if (phase < 0)
|
|
1406 return;
|
|
1407 dfi = get_dump_file_info (phase);
|
131
|
1408 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
|
111
|
1409 fclose (dfi->pstream);
|
|
1410
|
131
|
1411 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
|
111
|
1412 fclose (dfi->alt_stream);
|
|
1413
|
|
1414 dfi->alt_stream = NULL;
|
|
1415 dfi->pstream = NULL;
|
131
|
1416 set_dump_file (NULL);
|
|
1417 set_alt_dump_file (NULL);
|
|
1418 dump_flags = TDF_NONE;
|
|
1419 alt_flags = TDF_NONE;
|
|
1420 pflags = TDF_NONE;
|
111
|
1421 }
|
|
1422
|
|
1423 /* Begin a tree dump for PHASE. Stores any user supplied flag in
|
|
1424 *FLAG_PTR and returns a stream to write to. If the dump is not
|
|
1425 enabled, returns NULL.
|
131
|
1426 PART can be used for dump files which should be split to multiple
|
|
1427 parts. PART == -1 indicates dump file with no parts.
|
|
1428 If PART is -1, multiple calls will reopen and append to the dump file. */
|
111
|
1429
|
|
1430 FILE *
|
131
|
1431 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
|
111
|
1432 {
|
131
|
1433 return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
|
111
|
1434 }
|
|
1435
|
|
1436 FILE *
|
|
1437 gcc::dump_manager::
|
131
|
1438 dump_begin (int phase, dump_flags_t *flag_ptr, int part)
|
111
|
1439 {
|
|
1440 char *name;
|
|
1441 struct dump_file_info *dfi;
|
|
1442 FILE *stream;
|
|
1443
|
|
1444 if (phase == TDI_none || !dump_phase_enabled_p (phase))
|
|
1445 return NULL;
|
|
1446
|
131
|
1447 name = get_dump_file_name (phase, part);
|
111
|
1448 if (!name)
|
|
1449 return NULL;
|
|
1450 dfi = get_dump_file_info (phase);
|
|
1451
|
131
|
1452 /* We do not support re-opening of dump files with parts. This would require
|
|
1453 tracking pstate per part of the dump file. */
|
|
1454 stream = dump_open (name, part != -1 || dfi->pstate < 0);
|
|
1455 if (stream)
|
111
|
1456 dfi->pstate = 1;
|
|
1457 free (name);
|
|
1458
|
|
1459 if (flag_ptr)
|
|
1460 *flag_ptr = dfi->pflags;
|
|
1461
|
|
1462 /* Initialize current flags */
|
|
1463 pflags = dfi->pflags;
|
|
1464 return stream;
|
|
1465 }
|
|
1466
|
|
1467 /* Returns nonzero if dump PHASE is enabled for at least one stream.
|
|
1468 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
|
|
1469 any phase. */
|
|
1470
|
|
1471 int
|
|
1472 gcc::dump_manager::
|
|
1473 dump_phase_enabled_p (int phase) const
|
|
1474 {
|
|
1475 if (phase == TDI_tree_all)
|
|
1476 {
|
|
1477 size_t i;
|
|
1478 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
|
|
1479 if (dump_files[i].pstate || dump_files[i].alt_state)
|
|
1480 return 1;
|
|
1481 for (i = 0; i < m_extra_dump_files_in_use; i++)
|
|
1482 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
|
|
1483 return 1;
|
|
1484 return 0;
|
|
1485 }
|
|
1486 else
|
|
1487 {
|
|
1488 struct dump_file_info *dfi = get_dump_file_info (phase);
|
|
1489 return dfi->pstate || dfi->alt_state;
|
|
1490 }
|
|
1491 }
|
|
1492
|
|
1493 /* Returns nonzero if tree dump PHASE has been initialized. */
|
|
1494
|
|
1495 int
|
|
1496 gcc::dump_manager::
|
|
1497 dump_initialized_p (int phase) const
|
|
1498 {
|
|
1499 struct dump_file_info *dfi = get_dump_file_info (phase);
|
|
1500 return dfi->pstate > 0 || dfi->alt_state > 0;
|
|
1501 }
|
|
1502
|
|
1503 /* Returns the switch name of PHASE. */
|
|
1504
|
|
1505 const char *
|
|
1506 dump_flag_name (int phase)
|
|
1507 {
|
|
1508 return g->get_dumps ()->dump_flag_name (phase);
|
|
1509 }
|
|
1510
|
|
1511 const char *
|
|
1512 gcc::dump_manager::
|
|
1513 dump_flag_name (int phase) const
|
|
1514 {
|
|
1515 struct dump_file_info *dfi = get_dump_file_info (phase);
|
|
1516 return dfi->swtch;
|
|
1517 }
|
|
1518
|
131
|
1519 /* Handle -fdump-* and -fopt-info for a pass added after
|
|
1520 command-line options are parsed (those from plugins and
|
|
1521 those from backends).
|
|
1522
|
|
1523 Because the registration of plugin/backend passes happens after the
|
|
1524 command-line options are parsed, the options that specify single
|
|
1525 pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
|
|
1526 passes. Therefore we currently can only enable dumping of
|
|
1527 new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
|
|
1528 are specified. This is done here.
|
|
1529
|
|
1530 Similarly, the saved -fopt-info options are wired up to the new pass. */
|
|
1531
|
|
1532 void
|
|
1533 gcc::dump_manager::register_pass (opt_pass *pass)
|
|
1534 {
|
|
1535 gcc_assert (pass);
|
|
1536
|
|
1537 register_one_dump_file (pass);
|
|
1538
|
|
1539 dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number);
|
|
1540 gcc_assert (pass_dfi);
|
|
1541
|
|
1542 enum tree_dump_index tdi;
|
|
1543 if (pass->type == SIMPLE_IPA_PASS
|
|
1544 || pass->type == IPA_PASS)
|
|
1545 tdi = TDI_ipa_all;
|
|
1546 else if (pass->type == GIMPLE_PASS)
|
|
1547 tdi = TDI_tree_all;
|
|
1548 else
|
|
1549 tdi = TDI_rtl_all;
|
|
1550 const dump_file_info *tdi_dfi = get_dump_file_info (tdi);
|
|
1551 gcc_assert (tdi_dfi);
|
|
1552
|
|
1553 /* Check if dump-all flag is specified. */
|
|
1554 if (tdi_dfi->pstate)
|
|
1555 {
|
|
1556 pass_dfi->pstate = tdi_dfi->pstate;
|
|
1557 pass_dfi->pflags = tdi_dfi->pflags;
|
|
1558 }
|
|
1559
|
|
1560 update_dfi_for_opt_info (pass_dfi);
|
|
1561 }
|
|
1562
|
111
|
1563 /* Finish a tree dump for PHASE. STREAM is the stream created by
|
|
1564 dump_begin. */
|
|
1565
|
|
1566 void
|
|
1567 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
|
|
1568 {
|
|
1569 if (stream != stderr && stream != stdout)
|
|
1570 fclose (stream);
|
|
1571 }
|
|
1572
|
|
1573 /* Enable all tree dumps with FLAGS on FILENAME. Return number of
|
|
1574 enabled tree dumps. */
|
|
1575
|
|
1576 int
|
|
1577 gcc::dump_manager::
|
|
1578 dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
|
|
1579 {
|
|
1580 int n = 0;
|
|
1581 size_t i;
|
|
1582
|
|
1583 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
|
|
1584 {
|
131
|
1585 if (dump_files[i].dkind == dkind)
|
111
|
1586 {
|
|
1587 const char *old_filename = dump_files[i].pfilename;
|
|
1588 dump_files[i].pstate = -1;
|
|
1589 dump_files[i].pflags |= flags;
|
|
1590 n++;
|
|
1591 /* Override the existing filename. */
|
|
1592 if (filename)
|
|
1593 {
|
|
1594 dump_files[i].pfilename = xstrdup (filename);
|
|
1595 /* Since it is a command-line provided file, which is
|
|
1596 common to all the phases, use it in append mode. */
|
|
1597 dump_files[i].pstate = 1;
|
|
1598 }
|
|
1599 if (old_filename && filename != old_filename)
|
|
1600 free (CONST_CAST (char *, old_filename));
|
|
1601 }
|
|
1602 }
|
|
1603
|
|
1604 for (i = 0; i < m_extra_dump_files_in_use; i++)
|
|
1605 {
|
131
|
1606 if (m_extra_dump_files[i].dkind == dkind)
|
111
|
1607 {
|
|
1608 const char *old_filename = m_extra_dump_files[i].pfilename;
|
|
1609 m_extra_dump_files[i].pstate = -1;
|
|
1610 m_extra_dump_files[i].pflags |= flags;
|
|
1611 n++;
|
|
1612 /* Override the existing filename. */
|
|
1613 if (filename)
|
|
1614 {
|
|
1615 m_extra_dump_files[i].pfilename = xstrdup (filename);
|
|
1616 /* Since it is a command-line provided file, which is
|
|
1617 common to all the phases, use it in append mode. */
|
|
1618 m_extra_dump_files[i].pstate = 1;
|
|
1619 }
|
|
1620 if (old_filename && filename != old_filename)
|
|
1621 free (CONST_CAST (char *, old_filename));
|
|
1622 }
|
|
1623 }
|
|
1624
|
|
1625 return n;
|
|
1626 }
|
|
1627
|
|
1628 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
|
|
1629 Enable dumps with FLAGS on FILENAME. Return the number of enabled
|
|
1630 dumps. */
|
|
1631
|
|
1632 int
|
|
1633 gcc::dump_manager::
|
131
|
1634 opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
|
111
|
1635 const char *filename)
|
|
1636 {
|
|
1637 int n = 0;
|
131
|
1638
|
|
1639 m_optgroup_flags = optgroup_flags;
|
|
1640 m_optinfo_flags = flags;
|
|
1641 m_optinfo_filename = xstrdup (filename);
|
111
|
1642
|
131
|
1643 for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++)
|
|
1644 if (update_dfi_for_opt_info (&dump_files[i]))
|
|
1645 n++;
|
111
|
1646
|
131
|
1647 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
|
|
1648 if (update_dfi_for_opt_info (&m_extra_dump_files[i]))
|
|
1649 n++;
|
111
|
1650
|
|
1651 return n;
|
|
1652 }
|
|
1653
|
131
|
1654 /* Use the saved -fopt-info options to update DFI.
|
|
1655 Return true if the dump is enabled. */
|
|
1656
|
|
1657 bool
|
|
1658 gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const
|
|
1659 {
|
|
1660 gcc_assert (dfi);
|
|
1661
|
|
1662 if (!(dfi->optgroup_flags & m_optgroup_flags))
|
|
1663 return false;
|
|
1664
|
|
1665 const char *old_filename = dfi->alt_filename;
|
|
1666 /* Since this file is shared among different passes, it
|
|
1667 should be opened in append mode. */
|
|
1668 dfi->alt_state = 1;
|
|
1669 dfi->alt_flags |= m_optinfo_flags;
|
|
1670 /* Override the existing filename. */
|
|
1671 if (m_optinfo_filename)
|
|
1672 dfi->alt_filename = xstrdup (m_optinfo_filename);
|
|
1673 if (old_filename && m_optinfo_filename != old_filename)
|
|
1674 free (CONST_CAST (char *, old_filename));
|
|
1675
|
|
1676 return true;
|
|
1677 }
|
|
1678
|
111
|
1679 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
|
|
1680 relevant details in the dump_files array. */
|
|
1681
|
|
1682 int
|
|
1683 gcc::dump_manager::
|
|
1684 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
|
|
1685 {
|
|
1686 const char *option_value;
|
|
1687 const char *ptr;
|
|
1688 dump_flags_t flags;
|
|
1689
|
|
1690 if (doglob && !dfi->glob)
|
|
1691 return 0;
|
|
1692
|
|
1693 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
|
|
1694 if (!option_value)
|
|
1695 return 0;
|
|
1696
|
|
1697 if (*option_value && *option_value != '-' && *option_value != '=')
|
|
1698 return 0;
|
|
1699
|
|
1700 ptr = option_value;
|
131
|
1701
|
|
1702 /* Retain "user-facing" and "internals" messages, but filter out
|
|
1703 those from an opt_problem being re-emitted at the top level
|
|
1704 (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages
|
|
1705 messing up scan-tree-dump-times" in DejaGnu tests. */
|
|
1706 flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_INTERNALS;
|
111
|
1707
|
|
1708 while (*ptr)
|
|
1709 {
|
131
|
1710 const struct kv_pair<dump_flags_t> *option_ptr;
|
111
|
1711 const char *end_ptr;
|
|
1712 const char *eq_ptr;
|
|
1713 unsigned length;
|
|
1714
|
|
1715 while (*ptr == '-')
|
|
1716 ptr++;
|
|
1717 end_ptr = strchr (ptr, '-');
|
|
1718 eq_ptr = strchr (ptr, '=');
|
|
1719
|
|
1720 if (eq_ptr && !end_ptr)
|
|
1721 end_ptr = eq_ptr;
|
|
1722
|
|
1723 if (!end_ptr)
|
|
1724 end_ptr = ptr + strlen (ptr);
|
|
1725 length = end_ptr - ptr;
|
|
1726
|
|
1727 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
|
|
1728 if (strlen (option_ptr->name) == length
|
|
1729 && !memcmp (option_ptr->name, ptr, length))
|
|
1730 {
|
|
1731 flags |= option_ptr->value;
|
|
1732 goto found;
|
|
1733 }
|
|
1734
|
|
1735 if (*ptr == '=')
|
|
1736 {
|
|
1737 /* Interpret rest of the argument as a dump filename. This
|
|
1738 filename overrides other command line filenames. */
|
|
1739 if (dfi->pfilename)
|
|
1740 free (CONST_CAST (char *, dfi->pfilename));
|
|
1741 dfi->pfilename = xstrdup (ptr + 1);
|
|
1742 break;
|
|
1743 }
|
|
1744 else
|
|
1745 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
|
|
1746 length, ptr, dfi->swtch);
|
|
1747 found:;
|
|
1748 ptr = end_ptr;
|
|
1749 }
|
|
1750
|
|
1751 dfi->pstate = -1;
|
|
1752 dfi->pflags |= flags;
|
|
1753
|
|
1754 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
|
|
1755 known dumps. */
|
|
1756 if (dfi->suffix == NULL)
|
|
1757 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
|
|
1758
|
|
1759 return 1;
|
|
1760 }
|
|
1761
|
|
1762 int
|
|
1763 gcc::dump_manager::
|
|
1764 dump_switch_p (const char *arg)
|
|
1765 {
|
|
1766 size_t i;
|
|
1767 int any = 0;
|
|
1768
|
|
1769 for (i = TDI_none + 1; i != TDI_end; i++)
|
|
1770 any |= dump_switch_p_1 (arg, &dump_files[i], false);
|
|
1771
|
|
1772 /* Don't glob if we got a hit already */
|
|
1773 if (!any)
|
|
1774 for (i = TDI_none + 1; i != TDI_end; i++)
|
|
1775 any |= dump_switch_p_1 (arg, &dump_files[i], true);
|
|
1776
|
|
1777 for (i = 0; i < m_extra_dump_files_in_use; i++)
|
|
1778 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
|
|
1779
|
|
1780 if (!any)
|
|
1781 for (i = 0; i < m_extra_dump_files_in_use; i++)
|
|
1782 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
|
|
1783
|
|
1784
|
|
1785 return any;
|
|
1786 }
|
|
1787
|
|
1788 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
|
|
1789 and filename. Return non-zero if it is a recognized switch. */
|
|
1790
|
|
1791 static int
|
131
|
1792 opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
|
|
1793 optgroup_flags_t *optgroup_flags, char **filename)
|
111
|
1794 {
|
|
1795 const char *option_value;
|
|
1796 const char *ptr;
|
|
1797
|
|
1798 option_value = arg;
|
|
1799 ptr = option_value;
|
|
1800
|
|
1801 *filename = NULL;
|
131
|
1802
|
|
1803 /* Default to filtering out "internals" messages, and retaining
|
|
1804 "user-facing" messages, and those from an opt_problem being
|
|
1805 re-emitted at the top level. */
|
|
1806 *flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_REEMITTED;
|
|
1807
|
|
1808 *optgroup_flags = OPTGROUP_NONE;
|
111
|
1809
|
|
1810 if (!ptr)
|
|
1811 return 1; /* Handle '-fopt-info' without any additional options. */
|
|
1812
|
|
1813 while (*ptr)
|
|
1814 {
|
|
1815 const char *end_ptr;
|
|
1816 const char *eq_ptr;
|
|
1817 unsigned length;
|
|
1818
|
|
1819 while (*ptr == '-')
|
|
1820 ptr++;
|
|
1821 end_ptr = strchr (ptr, '-');
|
|
1822 eq_ptr = strchr (ptr, '=');
|
|
1823
|
|
1824 if (eq_ptr && !end_ptr)
|
|
1825 end_ptr = eq_ptr;
|
|
1826
|
|
1827 if (!end_ptr)
|
|
1828 end_ptr = ptr + strlen (ptr);
|
|
1829 length = end_ptr - ptr;
|
|
1830
|
131
|
1831 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
|
|
1832 option_ptr->name; option_ptr++)
|
111
|
1833 if (strlen (option_ptr->name) == length
|
|
1834 && !memcmp (option_ptr->name, ptr, length))
|
|
1835 {
|
|
1836 *flags |= option_ptr->value;
|
|
1837 goto found;
|
|
1838 }
|
|
1839
|
131
|
1840 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
|
|
1841 option_ptr->name; option_ptr++)
|
111
|
1842 if (strlen (option_ptr->name) == length
|
|
1843 && !memcmp (option_ptr->name, ptr, length))
|
|
1844 {
|
|
1845 *optgroup_flags |= option_ptr->value;
|
|
1846 goto found;
|
|
1847 }
|
|
1848
|
|
1849 if (*ptr == '=')
|
|
1850 {
|
|
1851 /* Interpret rest of the argument as a dump filename. This
|
|
1852 filename overrides other command line filenames. */
|
|
1853 *filename = xstrdup (ptr + 1);
|
|
1854 break;
|
|
1855 }
|
|
1856 else
|
|
1857 {
|
|
1858 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
|
|
1859 length, ptr, arg);
|
|
1860 return 0;
|
|
1861 }
|
|
1862 found:;
|
|
1863 ptr = end_ptr;
|
|
1864 }
|
|
1865
|
|
1866 return 1;
|
|
1867 }
|
|
1868
|
|
1869 /* Return non-zero if ARG is a recognized switch for
|
|
1870 -fopt-info. Return zero otherwise. */
|
|
1871
|
|
1872 int
|
|
1873 opt_info_switch_p (const char *arg)
|
|
1874 {
|
|
1875 dump_flags_t flags;
|
131
|
1876 optgroup_flags_t optgroup_flags;
|
111
|
1877 char *filename;
|
|
1878 static char *file_seen = NULL;
|
|
1879 gcc::dump_manager *dumps = g->get_dumps ();
|
|
1880
|
|
1881 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
|
|
1882 return 0;
|
|
1883
|
|
1884 if (!filename)
|
|
1885 filename = xstrdup ("stderr");
|
|
1886
|
|
1887 /* Bail out if a different filename has been specified. */
|
|
1888 if (file_seen && strcmp (file_seen, filename))
|
|
1889 {
|
|
1890 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
|
|
1891 arg);
|
|
1892 return 1;
|
|
1893 }
|
|
1894
|
|
1895 file_seen = xstrdup (filename);
|
131
|
1896 if (!(flags & MSG_ALL_KINDS))
|
|
1897 flags |= MSG_OPTIMIZED_LOCATIONS;
|
111
|
1898 if (!optgroup_flags)
|
|
1899 optgroup_flags = OPTGROUP_ALL;
|
|
1900
|
|
1901 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
|
|
1902 }
|
|
1903
|
|
1904 /* Print basic block on the dump streams. */
|
|
1905
|
|
1906 void
|
131
|
1907 dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
|
111
|
1908 {
|
131
|
1909 if (dump_file
|
|
1910 && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
|
111
|
1911 dump_bb (dump_file, bb, indent, TDF_DETAILS);
|
131
|
1912 if (alt_dump_file
|
|
1913 && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
|
111
|
1914 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
|
|
1915 }
|
|
1916
|
|
1917 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
|
|
1918
|
|
1919 void
|
|
1920 dump_function (int phase, tree fn)
|
|
1921 {
|
|
1922 FILE *stream;
|
|
1923 dump_flags_t flags;
|
|
1924
|
|
1925 stream = dump_begin (phase, &flags);
|
|
1926 if (stream)
|
|
1927 {
|
|
1928 dump_function_to_file (fn, stream, flags);
|
|
1929 dump_end (phase, stream);
|
|
1930 }
|
|
1931 }
|
|
1932
|
|
1933 /* Print information from the combine pass on dump_file. */
|
|
1934
|
|
1935 void
|
|
1936 print_combine_total_stats (void)
|
|
1937 {
|
|
1938 if (dump_file)
|
|
1939 dump_combine_total_stats (dump_file);
|
|
1940 }
|
|
1941
|
|
1942 /* Enable RTL dump for all the RTL passes. */
|
|
1943
|
|
1944 bool
|
|
1945 enable_rtl_dump_file (void)
|
|
1946 {
|
|
1947 gcc::dump_manager *dumps = g->get_dumps ();
|
|
1948 int num_enabled =
|
|
1949 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
|
|
1950 NULL);
|
|
1951 return num_enabled > 0;
|
|
1952 }
|
131
|
1953
|
|
1954 #if CHECKING_P
|
|
1955
|
|
1956 namespace selftest {
|
|
1957
|
|
1958 /* temp_dump_context's ctor. Temporarily override the dump_context
|
|
1959 (to forcibly enable optinfo-generation). */
|
|
1960
|
|
1961 temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
|
|
1962 bool forcibly_enable_dumping,
|
|
1963 dump_flags_t test_pp_flags)
|
|
1964 : m_context (),
|
|
1965 m_saved (&dump_context ().get ())
|
|
1966 {
|
|
1967 dump_context::s_current = &m_context;
|
|
1968 m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
|
|
1969 /* Conditionally enable the test dump, so that we can verify both the
|
|
1970 dump_enabled_p and the !dump_enabled_p cases in selftests. */
|
|
1971 if (forcibly_enable_dumping)
|
|
1972 {
|
|
1973 m_context.m_test_pp = &m_pp;
|
|
1974 m_context.m_test_pp_flags = test_pp_flags;
|
|
1975 }
|
|
1976
|
|
1977 dump_context::get ().refresh_dumps_are_enabled ();
|
|
1978 }
|
|
1979
|
|
1980 /* temp_dump_context's dtor. Restore the saved dump_context. */
|
|
1981
|
|
1982 temp_dump_context::~temp_dump_context ()
|
|
1983 {
|
|
1984 dump_context::s_current = m_saved;
|
|
1985
|
|
1986 dump_context::get ().refresh_dumps_are_enabled ();
|
|
1987 }
|
|
1988
|
|
1989 /* 0-terminate the text dumped so far, and return it. */
|
|
1990
|
|
1991 const char *
|
|
1992 temp_dump_context::get_dumped_text ()
|
|
1993 {
|
|
1994 return pp_formatted_text (&m_pp);
|
|
1995 }
|
|
1996
|
|
1997 /* Verify that the dump_location_t constructors capture the source location
|
|
1998 at which they were called (provided that the build compiler is sufficiently
|
|
1999 recent). */
|
|
2000
|
|
2001 static void
|
|
2002 test_impl_location ()
|
|
2003 {
|
|
2004 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
|
2005 /* Default ctor. */
|
|
2006 {
|
|
2007 dump_location_t loc;
|
|
2008 const int expected_line = __LINE__ - 1;
|
|
2009 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
|
|
2010 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
|
|
2011 }
|
|
2012
|
|
2013 /* Constructing from a gimple. */
|
|
2014 {
|
|
2015 dump_location_t loc ((gimple *)NULL);
|
|
2016 const int expected_line = __LINE__ - 1;
|
|
2017 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
|
|
2018 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
|
|
2019 }
|
|
2020
|
|
2021 /* Constructing from an rtx_insn. */
|
|
2022 {
|
|
2023 dump_location_t loc ((rtx_insn *)NULL);
|
|
2024 const int expected_line = __LINE__ - 1;
|
|
2025 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
|
|
2026 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
|
|
2027 }
|
|
2028 #endif
|
|
2029 }
|
|
2030
|
|
2031 /* Verify that the text dumped so far in CONTEXT equals
|
|
2032 EXPECTED_TEXT, using LOC for the location of any failure.
|
|
2033 As a side-effect, the internal buffer is 0-terminated. */
|
|
2034
|
|
2035 void
|
|
2036 verify_dumped_text (const location &loc,
|
|
2037 temp_dump_context *context,
|
|
2038 const char *expected_text)
|
|
2039 {
|
|
2040 gcc_assert (context);
|
|
2041 ASSERT_STREQ_AT (loc, context->get_dumped_text (),
|
|
2042 expected_text);
|
|
2043 }
|
|
2044
|
|
2045 /* Verify that ITEM has the expected values. */
|
|
2046
|
|
2047 void
|
|
2048 verify_item (const location &loc,
|
|
2049 const optinfo_item *item,
|
|
2050 enum optinfo_item_kind expected_kind,
|
|
2051 location_t expected_location,
|
|
2052 const char *expected_text)
|
|
2053 {
|
|
2054 ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
|
|
2055 ASSERT_EQ_AT (loc, item->get_location (), expected_location);
|
|
2056 ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
|
|
2057 }
|
|
2058
|
|
2059 /* Verify that calls to the dump_* API are captured and consolidated into
|
|
2060 optimization records. */
|
|
2061
|
|
2062 static void
|
|
2063 test_capture_of_dump_calls (const line_table_case &case_)
|
|
2064 {
|
|
2065 /* Generate a location_t for testing. */
|
|
2066 line_table_test ltt (case_);
|
|
2067 linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
|
|
2068 linemap_line_start (line_table, 5, 100);
|
|
2069 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
|
|
2070 location_t where = linemap_position_for_column (line_table, 10);
|
|
2071 if (where > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
|
2072 return;
|
|
2073
|
|
2074 dump_location_t loc = dump_location_t::from_location_t (where);
|
|
2075
|
|
2076 gimple *stmt = gimple_build_return (NULL);
|
|
2077 gimple_set_location (stmt, where);
|
|
2078
|
|
2079 tree test_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
|
2080 get_identifier ("test_decl"),
|
|
2081 integer_type_node);
|
|
2082 /* Run all tests twice, with and then without optinfo enabled, to ensure
|
|
2083 that immediate destinations vs optinfo-based destinations both
|
|
2084 work, independently of each other, with no leaks. */
|
|
2085 for (int i = 0 ; i < 2; i++)
|
|
2086 {
|
|
2087 bool with_optinfo = (i == 0);
|
|
2088
|
|
2089 /* Test of dump_printf. */
|
|
2090 {
|
|
2091 temp_dump_context tmp (with_optinfo, true,
|
|
2092 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2093 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
|
|
2094
|
|
2095 ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
|
|
2096 if (with_optinfo)
|
|
2097 {
|
|
2098 optinfo *info = tmp.get_pending_optinfo ();
|
|
2099 ASSERT_TRUE (info != NULL);
|
|
2100 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2101 ASSERT_EQ (info->num_items (), 1);
|
|
2102 ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
|
|
2103 }
|
|
2104 }
|
|
2105
|
|
2106 /* Test of dump_printf with %T. */
|
|
2107 {
|
|
2108 temp_dump_context tmp (with_optinfo, true,
|
|
2109 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2110 dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
|
|
2111
|
|
2112 ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
|
|
2113 if (with_optinfo)
|
|
2114 {
|
|
2115 optinfo *info = tmp.get_pending_optinfo ();
|
|
2116 ASSERT_TRUE (info != NULL);
|
|
2117 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2118 ASSERT_EQ (info->num_items (), 2);
|
|
2119 ASSERT_IS_TEXT (info->get_item (0), "tree: ");
|
|
2120 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
|
|
2121 }
|
|
2122 }
|
|
2123
|
|
2124 /* Test of dump_printf with %E. */
|
|
2125 {
|
|
2126 temp_dump_context tmp (with_optinfo, true,
|
|
2127 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2128 dump_printf (MSG_NOTE, "gimple: %E", stmt);
|
|
2129
|
|
2130 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
|
|
2131 if (with_optinfo)
|
|
2132 {
|
|
2133 optinfo *info = tmp.get_pending_optinfo ();
|
|
2134 ASSERT_TRUE (info != NULL);
|
|
2135 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2136 ASSERT_EQ (info->num_items (), 2);
|
|
2137 ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
|
|
2138 ASSERT_IS_GIMPLE (info->get_item (1), where, "return;");
|
|
2139 }
|
|
2140 }
|
|
2141
|
|
2142 /* Test of dump_printf with %G. */
|
|
2143 {
|
|
2144 temp_dump_context tmp (with_optinfo, true,
|
|
2145 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2146 dump_printf (MSG_NOTE, "gimple: %G", stmt);
|
|
2147
|
|
2148 ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
|
|
2149 if (with_optinfo)
|
|
2150 {
|
|
2151 optinfo *info = tmp.get_pending_optinfo ();
|
|
2152 ASSERT_TRUE (info != NULL);
|
|
2153 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2154 ASSERT_EQ (info->num_items (), 2);
|
|
2155 ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
|
|
2156 ASSERT_IS_GIMPLE (info->get_item (1), where, "return;\n");
|
|
2157 }
|
|
2158 }
|
|
2159
|
|
2160 /* dump_print_loc with multiple format codes. This tests various
|
|
2161 things:
|
|
2162 - intermingling of text, format codes handled by the base
|
|
2163 pretty_printer, and dump-specific format codes
|
|
2164 - multiple dump-specific format codes: some consecutive, others
|
|
2165 separated by text, trailing text after the final one. */
|
|
2166 {
|
|
2167 temp_dump_context tmp (with_optinfo, true,
|
|
2168 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2169 dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
|
|
2170 " %i consecutive %E%E after\n",
|
|
2171 integer_zero_node, test_decl, 42, stmt, stmt);
|
|
2172
|
|
2173 ASSERT_DUMPED_TEXT_EQ (tmp,
|
|
2174 "test.txt:5:10: note: before 0 and test_decl"
|
|
2175 " 42 consecutive return;return; after\n");
|
|
2176 if (with_optinfo)
|
|
2177 {
|
|
2178 optinfo *info = tmp.get_pending_optinfo ();
|
|
2179 ASSERT_TRUE (info != NULL);
|
|
2180 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2181 ASSERT_EQ (info->num_items (), 8);
|
|
2182 ASSERT_IS_TEXT (info->get_item (0), "before ");
|
|
2183 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
|
|
2184 ASSERT_IS_TEXT (info->get_item (2), " and ");
|
|
2185 ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
|
|
2186 ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
|
|
2187 ASSERT_IS_GIMPLE (info->get_item (5), where, "return;");
|
|
2188 ASSERT_IS_GIMPLE (info->get_item (6), where, "return;");
|
|
2189 ASSERT_IS_TEXT (info->get_item (7), " after\n");
|
|
2190 }
|
|
2191 }
|
|
2192
|
|
2193 /* Tree, via dump_generic_expr. */
|
|
2194 {
|
|
2195 temp_dump_context tmp (with_optinfo, true,
|
|
2196 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2197 dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
|
|
2198 dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
|
|
2199
|
|
2200 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
|
|
2201 if (with_optinfo)
|
|
2202 {
|
|
2203 optinfo *info = tmp.get_pending_optinfo ();
|
|
2204 ASSERT_TRUE (info != NULL);
|
|
2205 ASSERT_EQ (info->get_location_t (), where);
|
|
2206 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2207 ASSERT_EQ (info->num_items (), 2);
|
|
2208 ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
|
|
2209 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
|
|
2210 }
|
|
2211 }
|
|
2212
|
|
2213 /* Tree, via dump_generic_expr_loc. */
|
|
2214 {
|
|
2215 temp_dump_context tmp (with_optinfo, true,
|
|
2216 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2217 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
|
|
2218
|
|
2219 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
|
|
2220 if (with_optinfo)
|
|
2221 {
|
|
2222 optinfo *info = tmp.get_pending_optinfo ();
|
|
2223 ASSERT_TRUE (info != NULL);
|
|
2224 ASSERT_EQ (info->get_location_t (), where);
|
|
2225 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
|
|
2226 ASSERT_EQ (info->num_items (), 1);
|
|
2227 ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
|
|
2228 }
|
|
2229 }
|
|
2230
|
|
2231 /* Gimple. */
|
|
2232 {
|
|
2233 /* dump_gimple_stmt_loc. */
|
|
2234 {
|
|
2235 temp_dump_context tmp (with_optinfo, true,
|
|
2236 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2237 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
|
|
2238
|
|
2239 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
|
|
2240 if (with_optinfo)
|
|
2241 {
|
|
2242 optinfo *info = tmp.get_pending_optinfo ();
|
|
2243 ASSERT_TRUE (info != NULL);
|
|
2244 ASSERT_EQ (info->num_items (), 1);
|
|
2245 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
|
|
2246 }
|
|
2247 }
|
|
2248
|
|
2249 /* dump_gimple_stmt. */
|
|
2250 {
|
|
2251 temp_dump_context tmp (with_optinfo, true,
|
|
2252 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2253 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
|
|
2254
|
|
2255 ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
|
|
2256 if (with_optinfo)
|
|
2257 {
|
|
2258 optinfo *info = tmp.get_pending_optinfo ();
|
|
2259 ASSERT_TRUE (info != NULL);
|
|
2260 ASSERT_EQ (info->num_items (), 1);
|
|
2261 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
|
|
2262 }
|
|
2263 }
|
|
2264
|
|
2265 /* dump_gimple_expr_loc. */
|
|
2266 {
|
|
2267 temp_dump_context tmp (with_optinfo, true,
|
|
2268 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2269 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
|
|
2270
|
|
2271 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
|
|
2272 if (with_optinfo)
|
|
2273 {
|
|
2274 optinfo *info = tmp.get_pending_optinfo ();
|
|
2275 ASSERT_TRUE (info != NULL);
|
|
2276 ASSERT_EQ (info->num_items (), 1);
|
|
2277 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
|
|
2278 }
|
|
2279 }
|
|
2280
|
|
2281 /* dump_gimple_expr. */
|
|
2282 {
|
|
2283 temp_dump_context tmp (with_optinfo, true,
|
|
2284 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2285 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
|
|
2286
|
|
2287 ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
|
|
2288 if (with_optinfo)
|
|
2289 {
|
|
2290 optinfo *info = tmp.get_pending_optinfo ();
|
|
2291 ASSERT_TRUE (info != NULL);
|
|
2292 ASSERT_EQ (info->num_items (), 1);
|
|
2293 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
|
|
2294 }
|
|
2295 }
|
|
2296 }
|
|
2297
|
|
2298 /* poly_int. */
|
|
2299 {
|
|
2300 temp_dump_context tmp (with_optinfo, true,
|
|
2301 MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
|
|
2302 dump_dec (MSG_NOTE, poly_int64 (42));
|
|
2303
|
|
2304 ASSERT_DUMPED_TEXT_EQ (tmp, "42");
|
|
2305 if (with_optinfo)
|
|
2306 {
|
|
2307 optinfo *info = tmp.get_pending_optinfo ();
|
|
2308 ASSERT_TRUE (info != NULL);
|
|
2309 ASSERT_EQ (info->num_items (), 1);
|
|
2310 ASSERT_IS_TEXT (info->get_item (0), "42");
|
|
2311 }
|
|
2312 }
|
|
2313
|
|
2314 /* Scopes. Test with all 4 combinations of
|
|
2315 filtering by MSG_PRIORITY_USER_FACING
|
|
2316 and/or filtering by MSG_PRIORITY_INTERNALS. */
|
|
2317 for (int j = 0; j < 3; j++)
|
|
2318 {
|
|
2319 dump_flags_t dump_filter = MSG_ALL_KINDS;
|
|
2320 if (j % 2)
|
|
2321 dump_filter |= MSG_PRIORITY_USER_FACING;
|
|
2322 if (j / 2)
|
|
2323 dump_filter |= MSG_PRIORITY_INTERNALS;
|
|
2324
|
|
2325 temp_dump_context tmp (with_optinfo, true, dump_filter);
|
|
2326 /* Emit various messages, mostly with implicit priority. */
|
|
2327 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
|
|
2328 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt,
|
|
2329 "explicitly internal msg\n");
|
|
2330 {
|
|
2331 AUTO_DUMP_SCOPE ("outer scope", stmt);
|
|
2332 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
|
|
2333 {
|
|
2334 AUTO_DUMP_SCOPE ("middle scope", stmt);
|
|
2335 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
|
|
2336 {
|
|
2337 AUTO_DUMP_SCOPE ("inner scope", stmt);
|
|
2338 dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
|
|
2339 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt,
|
|
2340 "explicitly user-facing msg\n");
|
|
2341 }
|
|
2342 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
|
|
2343 }
|
|
2344 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
|
|
2345 }
|
|
2346 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
|
|
2347
|
|
2348 switch (dump_filter & MSG_ALL_PRIORITIES)
|
|
2349 {
|
|
2350 default:
|
|
2351 gcc_unreachable ();
|
|
2352 case 0:
|
|
2353 ASSERT_DUMPED_TEXT_EQ (tmp, "");
|
|
2354 break;
|
|
2355 case MSG_PRIORITY_USER_FACING:
|
|
2356 ASSERT_DUMPED_TEXT_EQ
|
|
2357 (tmp,
|
|
2358 "test.txt:5:10: note: msg 1\n"
|
|
2359 "test.txt:5:10: note: explicitly user-facing msg\n"
|
|
2360 "test.txt:5:10: note: msg 7\n");
|
|
2361 break;
|
|
2362 case MSG_PRIORITY_INTERNALS:
|
|
2363 ASSERT_DUMPED_TEXT_EQ
|
|
2364 (tmp,
|
|
2365 "test.txt:5:10: note: explicitly internal msg\n"
|
|
2366 "test.txt:5:10: note: === outer scope ===\n"
|
|
2367 "test.txt:5:10: note: msg 2\n"
|
|
2368 "test.txt:5:10: note: === middle scope ===\n"
|
|
2369 "test.txt:5:10: note: msg 3\n"
|
|
2370 "test.txt:5:10: note: === inner scope ===\n"
|
|
2371 "test.txt:5:10: note: msg 4\n"
|
|
2372 "test.txt:5:10: note: msg 5\n"
|
|
2373 "test.txt:5:10: note: msg 6\n");
|
|
2374 break;
|
|
2375 case MSG_ALL_PRIORITIES:
|
|
2376 ASSERT_DUMPED_TEXT_EQ
|
|
2377 (tmp,
|
|
2378 "test.txt:5:10: note: msg 1\n"
|
|
2379 "test.txt:5:10: note: explicitly internal msg\n"
|
|
2380 "test.txt:5:10: note: === outer scope ===\n"
|
|
2381 "test.txt:5:10: note: msg 2\n"
|
|
2382 "test.txt:5:10: note: === middle scope ===\n"
|
|
2383 "test.txt:5:10: note: msg 3\n"
|
|
2384 "test.txt:5:10: note: === inner scope ===\n"
|
|
2385 "test.txt:5:10: note: msg 4\n"
|
|
2386 "test.txt:5:10: note: explicitly user-facing msg\n"
|
|
2387 "test.txt:5:10: note: msg 5\n"
|
|
2388 "test.txt:5:10: note: msg 6\n"
|
|
2389 "test.txt:5:10: note: msg 7\n");
|
|
2390 break;
|
|
2391 }
|
|
2392 if (with_optinfo)
|
|
2393 {
|
|
2394 optinfo *info = tmp.get_pending_optinfo ();
|
|
2395 ASSERT_TRUE (info != NULL);
|
|
2396 ASSERT_EQ (info->num_items (), 1);
|
|
2397 ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
|
|
2398 }
|
|
2399 }
|
|
2400 }
|
|
2401
|
|
2402 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
|
|
2403 above. */
|
|
2404 {
|
|
2405 /* MSG_OPTIMIZED_LOCATIONS. */
|
|
2406 {
|
|
2407 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
|
|
2408 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
|
|
2409 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
|
|
2410 OPTINFO_KIND_SUCCESS);
|
|
2411 }
|
|
2412
|
|
2413 /* MSG_MISSED_OPTIMIZATION. */
|
|
2414 {
|
|
2415 temp_dump_context tmp (true, true, MSG_ALL_KINDS);
|
|
2416 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
|
|
2417 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
|
|
2418 OPTINFO_KIND_FAILURE);
|
|
2419 }
|
|
2420 }
|
|
2421
|
|
2422 /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
|
|
2423 {
|
|
2424 temp_dump_context tmp (false, true,
|
|
2425 MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
|
|
2426 dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
|
|
2427 {
|
|
2428 AUTO_DUMP_SCOPE ("outer scope", stmt);
|
|
2429 dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
|
|
2430 {
|
|
2431 AUTO_DUMP_SCOPE ("middle scope", stmt);
|
|
2432 dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
|
|
2433 {
|
|
2434 AUTO_DUMP_SCOPE ("inner scope", stmt);
|
|
2435 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
|
|
2436 }
|
|
2437 dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
|
|
2438 }
|
|
2439 dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
|
|
2440 }
|
|
2441 dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
|
|
2442
|
|
2443 ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized: msg 4\n");
|
|
2444 }
|
|
2445 }
|
|
2446
|
|
2447 /* Run all of the selftests within this file. */
|
|
2448
|
|
2449 void
|
|
2450 dumpfile_c_tests ()
|
|
2451 {
|
|
2452 test_impl_location ();
|
|
2453 for_each_line_table_case (test_capture_of_dump_calls);
|
|
2454 }
|
|
2455
|
|
2456 } // namespace selftest
|
|
2457
|
|
2458 #endif /* CHECKING_P */
|