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