]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dumpfile.c
Explain asan parameters in params.def (PR sanitizer/79635).
[thirdparty/gcc.git] / gcc / dumpfile.c
CommitLineData
b5f47924 1/* Dump infrastructure for optimizations and intermediate representation.
85ec4feb 2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
b5f47924
SS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
957060b5
AM
23#include "options.h"
24#include "tree.h"
25#include "gimple-pretty-print.h"
b5f47924
SS
26#include "diagnostic-core.h"
27#include "dumpfile.h"
47e0da37 28#include "context.h"
0de11d4d 29#include "profile-count.h"
c24e924f 30#include "tree-cfg.h"
363dc72c 31#include "langhooks.h"
4f5b9c80
DM
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"
4df3629e
DM
36#include "optinfo.h"
37#include "dump-context.h"
38#include "cgraph.h"
39#include "tree-pass.h" /* for "current_pass". */
4a4412b9 40#include "optinfo-emit-json.h"
b5f47924
SS
41
42/* If non-NULL, return one past-the-end of the matching SUBPART of
43 the WHOLE string. */
44#define skip_leading_substring(whole, part) \
45 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
46
1a817418 47static dump_flags_t pflags; /* current dump_flags */
b5f47924 48
1a817418 49static void dump_loc (dump_flags_t, FILE *, source_location);
29b54a9d
DM
50
51/* Current -fopt-info output stream, if any, and flags. */
52static FILE *alt_dump_file = NULL;
53static dump_flags_t alt_flags;
54
b5f47924
SS
55static FILE *dump_open_alternate_stream (struct dump_file_info *);
56
73fbfcad
SS
57/* These are currently used for communicating between passes.
58 However, instead of accessing them directly, the passes can use
59 dump_printf () for dumps. */
60FILE *dump_file = NULL;
73fbfcad 61const char *dump_file_name;
1a817418 62dump_flags_t dump_flags;
29b54a9d
DM
63bool dumps_are_enabled = false;
64
65
66/* Update the "dumps_are_enabled" global; to be called whenever dump_file
67 or alt_dump_file change. */
68
69static void
70refresh_dumps_are_enabled ()
71{
4df3629e 72 dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ());
29b54a9d
DM
73}
74
75/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
76 global. */
77
78void
79set_dump_file (FILE *new_dump_file)
80{
4df3629e 81 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d
DM
82 dump_file = new_dump_file;
83 refresh_dumps_are_enabled ();
84}
85
86/* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
87 global. */
88
89static void
90set_alt_dump_file (FILE *new_alt_dump_file)
91{
4df3629e 92 dumpfile_ensure_any_optinfo_are_flushed ();
29b54a9d
DM
93 alt_dump_file = new_alt_dump_file;
94 refresh_dumps_are_enabled ();
95}
73fbfcad 96
63523736 97#define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
4af78ef8
DM
98 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
99 OPTGROUP_NONE, 0, 0, num, false, false}
8264c84d 100
b5f47924
SS
101/* Table of tree dump switches. This must be consistent with the
102 TREE_DUMP_INDEX enumeration in dumpfile.h. */
103static struct dump_file_info dump_files[TDI_end] =
104{
63523736
ML
105 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
106 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
107 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
108 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
363dc72c
JJ
109 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
110 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
111 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
b4da704c 112 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
363dc72c 113#define FIRST_AUTO_NUMBERED_DUMP 1
29a50dfb 114#define FIRST_ME_AUTO_NUMBERED_DUMP 4
b5f47924 115
63523736
ML
116 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
117 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
118 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
119 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
b5f47924
SS
120};
121
b5f47924
SS
122/* Table of dump options. This must be consistent with the TDF_* flags
123 in dumpfile.h and opt_info_options below. */
4af78ef8 124static const kv_pair<dump_flags_t> dump_options[] =
b5f47924
SS
125{
126 {"address", TDF_ADDRESS},
127 {"asmname", TDF_ASMNAME},
128 {"slim", TDF_SLIM},
129 {"raw", TDF_RAW},
130 {"graph", TDF_GRAPH},
131 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
132 | MSG_MISSED_OPTIMIZATION
133 | MSG_NOTE)},
134 {"cselib", TDF_CSELIB},
135 {"stats", TDF_STATS},
136 {"blocks", TDF_BLOCKS},
137 {"vops", TDF_VOPS},
138 {"lineno", TDF_LINENO},
139 {"uid", TDF_UID},
140 {"stmtaddr", TDF_STMTADDR},
141 {"memsyms", TDF_MEMSYMS},
b5f47924
SS
142 {"eh", TDF_EH},
143 {"alias", TDF_ALIAS},
144 {"nouid", TDF_NOUID},
145 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
146 {"scev", TDF_SCEV},
1ee62b92 147 {"gimple", TDF_GIMPLE},
56af751e 148 {"folding", TDF_FOLDING},
f14726bd
TJ
149 {"optimized", MSG_OPTIMIZED_LOCATIONS},
150 {"missed", MSG_MISSED_OPTIMIZATION},
151 {"note", MSG_NOTE},
152 {"optall", MSG_ALL},
f6b3ca5a
JJ
153 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
154 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
155 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
4af78ef8 156 {NULL, TDF_NONE}
b5f47924
SS
157};
158
2b4e6bf1
SS
159/* A subset of the dump_options table which is used for -fopt-info
160 types. This must be consistent with the MSG_* flags in dumpfile.h.
b5f47924 161 */
4af78ef8 162static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
b5f47924
SS
163{
164 {"optimized", MSG_OPTIMIZED_LOCATIONS},
165 {"missed", MSG_MISSED_OPTIMIZATION},
166 {"note", MSG_NOTE},
2b4e6bf1 167 {"all", MSG_ALL},
4af78ef8 168 {NULL, TDF_NONE}
2b4e6bf1
SS
169};
170
171/* Flags used for -fopt-info groups. */
4a4412b9 172const kv_pair<optgroup_flags_t> optgroup_options[] =
2b4e6bf1
SS
173{
174 {"ipa", OPTGROUP_IPA},
175 {"loop", OPTGROUP_LOOP},
176 {"inline", OPTGROUP_INLINE},
fd2b8c8b 177 {"omp", OPTGROUP_OMP},
2b4e6bf1
SS
178 {"vec", OPTGROUP_VEC},
179 {"optall", OPTGROUP_ALL},
4af78ef8 180 {NULL, OPTGROUP_NONE}
b5f47924
SS
181};
182
47e0da37
DM
183gcc::dump_manager::dump_manager ():
184 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
185 m_extra_dump_files (NULL),
186 m_extra_dump_files_in_use (0),
187 m_extra_dump_files_alloced (0)
188{
189}
190
10fdd6e9
DM
191gcc::dump_manager::~dump_manager ()
192{
193 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
194 {
195 dump_file_info *dfi = &m_extra_dump_files[i];
196 /* suffix, swtch, glob are statically allocated for the entries
197 in dump_files, and for statistics, but are dynamically allocated
198 for those for passes. */
199 if (dfi->owns_strings)
200 {
201 XDELETEVEC (const_cast <char *> (dfi->suffix));
202 XDELETEVEC (const_cast <char *> (dfi->swtch));
203 XDELETEVEC (const_cast <char *> (dfi->glob));
204 }
205 /* These, if non-NULL, are always dynamically allocated. */
206 XDELETEVEC (const_cast <char *> (dfi->pfilename));
207 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
208 }
209 XDELETEVEC (m_extra_dump_files);
210}
211
b5f47924 212unsigned int
47e0da37 213gcc::dump_manager::
b5f47924 214dump_register (const char *suffix, const char *swtch, const char *glob,
4af78ef8
DM
215 dump_kind dkind, optgroup_flags_t optgroup_flags,
216 bool take_ownership)
b5f47924 217{
47e0da37 218 int num = m_next_dump++;
b5f47924 219
47e0da37 220 size_t count = m_extra_dump_files_in_use++;
b5f47924 221
47e0da37 222 if (count >= m_extra_dump_files_alloced)
b5f47924 223 {
47e0da37 224 if (m_extra_dump_files_alloced == 0)
363dc72c 225 m_extra_dump_files_alloced = 512;
b5f47924 226 else
47e0da37
DM
227 m_extra_dump_files_alloced *= 2;
228 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
229 m_extra_dump_files,
230 m_extra_dump_files_alloced);
c3684b7b
MS
231
232 /* Construct a new object in the space allocated above. */
233 new (m_extra_dump_files + count) dump_file_info ();
234 }
235 else
236 {
237 /* Zero out the already constructed object. */
238 m_extra_dump_files[count] = dump_file_info ();
b5f47924
SS
239 }
240
47e0da37
DM
241 m_extra_dump_files[count].suffix = suffix;
242 m_extra_dump_files[count].swtch = swtch;
243 m_extra_dump_files[count].glob = glob;
8264c84d 244 m_extra_dump_files[count].dkind = dkind;
47e0da37
DM
245 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
246 m_extra_dump_files[count].num = num;
10fdd6e9 247 m_extra_dump_files[count].owns_strings = take_ownership;
b5f47924
SS
248
249 return count + TDI_end;
250}
251
252
363dc72c
JJ
253/* Allow languages and middle-end to register their dumps before the
254 optimization passes. */
255
256void
257gcc::dump_manager::
258register_dumps ()
259{
260 lang_hooks.register_dumps (this);
261 /* If this assert fails, some FE registered more than
262 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
263 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
264 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
265 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
266 dump_files[TDI_original].num = m_next_dump++;
267 dump_files[TDI_gimple].num = m_next_dump++;
268 dump_files[TDI_nested].num = m_next_dump++;
269}
270
271
b5f47924
SS
272/* Return the dump_file_info for the given phase. */
273
274struct dump_file_info *
47e0da37
DM
275gcc::dump_manager::
276get_dump_file_info (int phase) const
b5f47924
SS
277{
278 if (phase < TDI_end)
279 return &dump_files[phase];
47e0da37 280 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
b5f47924
SS
281 return NULL;
282 else
47e0da37 283 return m_extra_dump_files + (phase - TDI_end);
b5f47924
SS
284}
285
799505ae
DM
286/* Locate the dump_file_info with swtch equal to SWTCH,
287 or return NULL if no such dump_file_info exists. */
288
289struct dump_file_info *
290gcc::dump_manager::
291get_dump_file_info_by_switch (const char *swtch) const
292{
293 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
01512446 294 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
799505ae
DM
295 return &m_extra_dump_files[i];
296
297 /* Not found. */
298 return NULL;
299}
300
b5f47924
SS
301
302/* Return the name of the dump file for the given phase.
799505ae
DM
303 The caller is responsible for calling free on the returned
304 buffer.
b5f47924
SS
305 If the dump is not enabled, returns NULL. */
306
307char *
47e0da37 308gcc::dump_manager::
75fdb07e 309get_dump_file_name (int phase, int part) const
b5f47924 310{
b5f47924
SS
311 struct dump_file_info *dfi;
312
313 if (phase == TDI_none)
314 return NULL;
315
316 dfi = get_dump_file_info (phase);
799505ae 317
75fdb07e 318 return get_dump_file_name (dfi, part);
799505ae
DM
319}
320
321/* Return the name of the dump file for the given dump_file_info.
322 The caller is responsible for calling free on the returned
323 buffer.
324 If the dump is not enabled, returns NULL. */
325
326char *
327gcc::dump_manager::
75fdb07e 328get_dump_file_name (struct dump_file_info *dfi, int part) const
799505ae
DM
329{
330 char dump_id[10];
331
332 gcc_assert (dfi);
333
b5f47924
SS
334 if (dfi->pstate == 0)
335 return NULL;
336
337 /* If available, use the command line dump filename. */
338 if (dfi->pfilename)
339 return xstrdup (dfi->pfilename);
340
341 if (dfi->num < 0)
342 dump_id[0] = '\0';
343 else
344 {
8264c84d
ML
345 /* (null), LANG, TREE, RTL, IPA. */
346 char suffix = " ltri"[dfi->dkind];
a529e0a6 347
8264c84d 348 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
b5f47924
SS
349 dump_id[0] = '\0';
350 }
351
75fdb07e
JH
352 if (part != -1)
353 {
354 char part_id[8];
355 snprintf (part_id, sizeof (part_id), ".%i", part);
356 return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
357 }
358 else
359 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
b5f47924
SS
360}
361
5d8b352a
NS
362/* Open a dump file called FILENAME. Some filenames are special and
363 refer to the standard streams. TRUNC indicates whether this is the
364 first open (so the file should be truncated, rather than appended).
365 An error message is emitted in the event of failure. */
366
367static FILE *
368dump_open (const char *filename, bool trunc)
369{
370 if (strcmp ("stderr", filename) == 0)
371 return stderr;
372
bd9918c4
NS
373 if (strcmp ("stdout", filename) == 0
374 || strcmp ("-", filename) == 0)
5d8b352a
NS
375 return stdout;
376
377 FILE *stream = fopen (filename, trunc ? "w" : "a");
378
379 if (!stream)
380 error ("could not open dump file %qs: %m", filename);
381 return stream;
382}
383
b5f47924
SS
384/* For a given DFI, open an alternate dump filename (which could also
385 be a standard stream such as stdout/stderr). If the alternate dump
386 file cannot be opened, return NULL. */
387
388static FILE *
389dump_open_alternate_stream (struct dump_file_info *dfi)
390{
b5f47924
SS
391 if (!dfi->alt_filename)
392 return NULL;
393
394 if (dfi->alt_stream)
395 return dfi->alt_stream;
396
5d8b352a 397 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
b5f47924 398
5d8b352a 399 if (stream)
b5f47924
SS
400 dfi->alt_state = 1;
401
402 return stream;
403}
404
4f5b9c80
DM
405/* Construct a dump_user_location_t from STMT (using its location and
406 hotness). */
407
408dump_user_location_t::dump_user_location_t (gimple *stmt)
409: m_count (), m_loc (UNKNOWN_LOCATION)
410{
411 if (stmt)
412 {
413 if (stmt->bb)
414 m_count = stmt->bb->count;
415 m_loc = gimple_location (stmt);
416 }
417}
418
419/* Construct a dump_user_location_t from an RTL instruction (using its
420 location and hotness). */
421
422dump_user_location_t::dump_user_location_t (rtx_insn *insn)
423: m_count (), m_loc (UNKNOWN_LOCATION)
424{
425 if (insn)
426 {
427 basic_block bb = BLOCK_FOR_INSN (insn);
428 if (bb)
429 m_count = bb->count;
430 m_loc = INSN_LOCATION (insn);
431 }
432}
433
434/* Construct from a function declaration. This one requires spelling out
435 to avoid accidentally constructing from other kinds of tree. */
436
437dump_user_location_t
438dump_user_location_t::from_function_decl (tree fndecl)
439{
440 gcc_assert (fndecl);
441
442 // FIXME: profile count for function?
443 return dump_user_location_t (profile_count (),
444 DECL_SOURCE_LOCATION (fndecl));
445}
446
b5f47924
SS
447/* Print source location on DFILE if enabled. */
448
4f5b9c80 449static void
1a817418 450dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
b5f47924 451{
b5f47924
SS
452 if (dump_kind)
453 {
502498d5 454 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
e645e942 455 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
103ff0d6 456 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
a3d7af04 457 else if (current_function_decl)
e645e942 458 fprintf (dfile, "%s:%d:%d: note: ",
b5f47924 459 DECL_SOURCE_FILE (current_function_decl),
103ff0d6
TJ
460 DECL_SOURCE_LINE (current_function_decl),
461 DECL_SOURCE_COLUMN (current_function_decl));
6475e077
DM
462 /* Indentation based on scope depth. */
463 fprintf (dfile, "%*s", get_dump_scope_depth (), "");
b5f47924
SS
464 }
465}
466
4df3629e
DM
467/* Implementation of dump_context member functions. */
468
469/* dump_context's dtor. */
470
471dump_context::~dump_context ()
472{
473 delete m_pending;
474}
475
b5f47924
SS
476/* Dump gimple statement GS with SPC indentation spaces and
477 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
478
479void
4df3629e
DM
480dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
481 dump_flags_t extra_dump_flags,
482 gimple *gs, int spc)
b5f47924
SS
483{
484 if (dump_file && (dump_kind & pflags))
485 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
486
487 if (alt_dump_file && (dump_kind & alt_flags))
488 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
4df3629e
DM
489
490 if (optinfo_enabled_p ())
491 {
492 optinfo &info = ensure_pending_optinfo ();
493 info.handle_dump_file_kind (dump_kind);
494 info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
495 }
b5f47924
SS
496}
497
498/* Similar to dump_gimple_stmt, except additionally print source location. */
499
500void
4df3629e
DM
501dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
502 const dump_location_t &loc,
503 dump_flags_t extra_dump_flags,
504 gimple *gs, int spc)
b5f47924 505{
4f5b9c80 506 location_t srcloc = loc.get_location_t ();
b5f47924
SS
507 if (dump_file && (dump_kind & pflags))
508 {
4f5b9c80 509 dump_loc (dump_kind, dump_file, srcloc);
b5f47924
SS
510 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
511 }
512
513 if (alt_dump_file && (dump_kind & alt_flags))
514 {
4f5b9c80 515 dump_loc (dump_kind, alt_dump_file, srcloc);
b5f47924
SS
516 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
517 }
4df3629e
DM
518
519 if (optinfo_enabled_p ())
520 {
521 optinfo &info = begin_next_optinfo (loc);
522 info.handle_dump_file_kind (dump_kind);
523 info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
524 }
b5f47924
SS
525}
526
30f502ed
RB
527/* Dump gimple statement GS with SPC indentation spaces and
528 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
529 Do not terminate with a newline or semicolon. */
530
531void
4df3629e
DM
532dump_context::dump_gimple_expr (dump_flags_t dump_kind,
533 dump_flags_t extra_dump_flags,
534 gimple *gs, int spc)
30f502ed
RB
535{
536 if (dump_file && (dump_kind & pflags))
537 print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
538
539 if (alt_dump_file && (dump_kind & alt_flags))
540 print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
4df3629e
DM
541
542 if (optinfo_enabled_p ())
543 {
544 optinfo &info = ensure_pending_optinfo ();
545 info.handle_dump_file_kind (dump_kind);
546 info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
547 }
30f502ed
RB
548}
549
550/* Similar to dump_gimple_expr, except additionally print source location. */
551
552void
4df3629e
DM
553dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind,
554 const dump_location_t &loc,
555 dump_flags_t extra_dump_flags,
556 gimple *gs,
557 int spc)
30f502ed
RB
558{
559 location_t srcloc = loc.get_location_t ();
560 if (dump_file && (dump_kind & pflags))
561 {
562 dump_loc (dump_kind, dump_file, srcloc);
563 print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
564 }
565
566 if (alt_dump_file && (dump_kind & alt_flags))
567 {
568 dump_loc (dump_kind, alt_dump_file, srcloc);
569 print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
570 }
4df3629e
DM
571
572 if (optinfo_enabled_p ())
573 {
574 optinfo &info = begin_next_optinfo (loc);
575 info.handle_dump_file_kind (dump_kind);
576 info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
577 }
30f502ed
RB
578}
579
580
b5f47924
SS
581/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
582 DUMP_KIND is enabled. */
583
584void
4df3629e
DM
585dump_context::dump_generic_expr (dump_flags_t dump_kind,
586 dump_flags_t extra_dump_flags,
587 tree t)
b5f47924
SS
588{
589 if (dump_file && (dump_kind & pflags))
590 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
591
592 if (alt_dump_file && (dump_kind & alt_flags))
593 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
4df3629e
DM
594
595 if (optinfo_enabled_p ())
596 {
597 optinfo &info = ensure_pending_optinfo ();
598 info.handle_dump_file_kind (dump_kind);
599 info.add_tree (t, dump_flags | extra_dump_flags);
600 }
b5f47924
SS
601}
602
d7259673
DM
603
604/* Similar to dump_generic_expr, except additionally print the source
605 location. */
606
607void
4df3629e
DM
608dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
609 const dump_location_t &loc,
610 dump_flags_t extra_dump_flags,
611 tree t)
d7259673
DM
612{
613 location_t srcloc = loc.get_location_t ();
614 if (dump_file && (dump_kind & pflags))
615 {
616 dump_loc (dump_kind, dump_file, srcloc);
617 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
618 }
619
620 if (alt_dump_file && (dump_kind & alt_flags))
621 {
622 dump_loc (dump_kind, alt_dump_file, srcloc);
623 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
624 }
4df3629e
DM
625
626 if (optinfo_enabled_p ())
627 {
628 optinfo &info = begin_next_optinfo (loc);
629 info.handle_dump_file_kind (dump_kind);
630 info.add_tree (t, dump_flags | extra_dump_flags);
631 }
d7259673
DM
632}
633
b5f47924
SS
634/* Output a formatted message using FORMAT on appropriate dump streams. */
635
636void
4df3629e
DM
637dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
638 va_list ap)
b5f47924
SS
639{
640 if (dump_file && (dump_kind & pflags))
641 {
4df3629e
DM
642 va_list aq;
643 va_copy (aq, ap);
644 vfprintf (dump_file, format, aq);
645 va_end (aq);
b5f47924
SS
646 }
647
648 if (alt_dump_file && (dump_kind & alt_flags))
649 {
4df3629e
DM
650 va_list aq;
651 va_copy (aq, ap);
652 vfprintf (alt_dump_file, format, aq);
653 va_end (aq);
654 }
655
656 if (optinfo_enabled_p ())
657 {
658 optinfo &info = ensure_pending_optinfo ();
659 va_list aq;
660 va_copy (aq, ap);
661 info.add_printf_va (format, aq);
662 va_end (aq);
b5f47924
SS
663 }
664}
665
4df3629e
DM
666/* Similar to dump_printf, except source location is also printed, and
667 dump location captured. */
b5f47924
SS
668
669void
4df3629e
DM
670dump_context::dump_printf_loc_va (dump_flags_t dump_kind,
671 const dump_location_t &loc,
672 const char *format, va_list ap)
b5f47924 673{
4f5b9c80 674 location_t srcloc = loc.get_location_t ();
4df3629e 675
b5f47924
SS
676 if (dump_file && (dump_kind & pflags))
677 {
4f5b9c80 678 dump_loc (dump_kind, dump_file, srcloc);
4df3629e
DM
679 va_list aq;
680 va_copy (aq, ap);
681 vfprintf (dump_file, format, aq);
682 va_end (aq);
b5f47924
SS
683 }
684
685 if (alt_dump_file && (dump_kind & alt_flags))
686 {
4f5b9c80 687 dump_loc (dump_kind, alt_dump_file, srcloc);
4df3629e
DM
688 va_list aq;
689 va_copy (aq, ap);
690 vfprintf (alt_dump_file, format, aq);
691 va_end (aq);
692 }
693
694 if (optinfo_enabled_p ())
695 {
696 optinfo &info = begin_next_optinfo (loc);
697 info.handle_dump_file_kind (dump_kind);
698 va_list aq;
699 va_copy (aq, ap);
700 info.add_printf_va (format, aq);
701 va_end (aq);
b5f47924
SS
702 }
703}
704
dc3f3805
RS
705/* Output VALUE in decimal to appropriate dump streams. */
706
707template<unsigned int N, typename C>
708void
4df3629e 709dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
dc3f3805
RS
710{
711 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
712 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
713 if (dump_file && (dump_kind & pflags))
714 print_dec (value, dump_file, sgn);
715
716 if (alt_dump_file && (dump_kind & alt_flags))
717 print_dec (value, alt_dump_file, sgn);
4df3629e
DM
718
719 if (optinfo_enabled_p ())
720 {
721 optinfo &info = ensure_pending_optinfo ();
722 info.handle_dump_file_kind (dump_kind);
723 info.add_poly_int<N,C> (value);
724 }
725}
726
727/* Output the name of NODE on appropriate dump streams. */
728
729void
730dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
731{
732 if (dump_file && (dump_kind & pflags))
733 fprintf (dump_file, "%s", node->dump_name ());
734
735 if (alt_dump_file && (dump_kind & alt_flags))
736 fprintf (alt_dump_file, "%s", node->dump_name ());
737
738 if (optinfo_enabled_p ())
739 {
740 optinfo &info = ensure_pending_optinfo ();
741 info.handle_dump_file_kind (dump_kind);
742 info.add_symtab_node (node);
743 }
744}
745
746/* Get the current dump scope-nesting depth.
747 For use by -fopt-info (for showing nesting via indentation). */
748
749unsigned int
750dump_context::get_scope_depth () const
751{
752 return m_scope_depth;
753}
754
755/* Push a nested dump scope.
756 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
757 destination, if any.
758 Emit a "scope" optinfo if optinfos are enabled.
759 Increment the scope depth. */
760
761void
762dump_context::begin_scope (const char *name, const dump_location_t &loc)
763{
764 /* Specialcase, to avoid going through dump_printf_loc,
765 so that we can create a optinfo of kind OPTINFO_KIND_SCOPE. */
766
767 if (dump_file)
768 {
769 dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
770 fprintf (dump_file, "=== %s ===\n", name);
771 }
772
773 if (alt_dump_file)
774 {
775 dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
776 fprintf (alt_dump_file, "=== %s ===\n", name);
777 }
778
779 if (optinfo_enabled_p ())
780 {
781 end_any_optinfo ();
782 optinfo info (loc, OPTINFO_KIND_SCOPE, current_pass);
783 info.add_printf ("=== %s ===", name);
784 info.emit ();
785 }
786
787 m_scope_depth++;
788}
789
790/* Pop a nested dump scope. */
791
792void
793dump_context::end_scope ()
794{
795 end_any_optinfo ();
796 m_scope_depth--;
4a4412b9 797 optimization_records_maybe_pop_dump_scope ();
4df3629e
DM
798}
799
800/* Return the optinfo currently being accumulated, creating one if
801 necessary. */
802
803optinfo &
804dump_context::ensure_pending_optinfo ()
805{
806 if (!m_pending)
807 return begin_next_optinfo (dump_location_t (dump_user_location_t ()));
808 return *m_pending;
809}
810
811/* Start a new optinfo and return it, ending any optinfo that was already
812 accumulated. */
813
814optinfo &
815dump_context::begin_next_optinfo (const dump_location_t &loc)
816{
817 end_any_optinfo ();
818 gcc_assert (m_pending == NULL);
819 m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
820 return *m_pending;
821}
822
823/* End any optinfo that has been accumulated within this context; emitting
4a4412b9 824 it to any destinations as appropriate, such as optimization records. */
4df3629e
DM
825
826void
827dump_context::end_any_optinfo ()
828{
829 if (m_pending)
830 m_pending->emit ();
831 delete m_pending;
832 m_pending = NULL;
833}
834
835/* The current singleton dump_context, and its default. */
836
837dump_context *dump_context::s_current = &dump_context::s_default;
838dump_context dump_context::s_default;
839
840/* Implementation of dump_* API calls, calling into dump_context
841 member functions. */
842
843/* Dump gimple statement GS with SPC indentation spaces and
844 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
845
846void
847dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
848 gimple *gs, int spc)
849{
850 dump_context::get ().dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
851}
852
853/* Similar to dump_gimple_stmt, except additionally print source location. */
854
855void
856dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
857 dump_flags_t extra_dump_flags, gimple *gs, int spc)
858{
859 dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc, extra_dump_flags,
860 gs, spc);
861}
862
863/* Dump gimple statement GS with SPC indentation spaces and
864 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
865 Do not terminate with a newline or semicolon. */
866
867void
868dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
869 gimple *gs, int spc)
870{
871 dump_context::get ().dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
872}
873
874/* Similar to dump_gimple_expr, except additionally print source location. */
875
876void
877dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
878 dump_flags_t extra_dump_flags, gimple *gs, int spc)
879{
880 dump_context::get ().dump_gimple_expr_loc (dump_kind, loc, extra_dump_flags,
881 gs, spc);
882}
883
884/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
885 DUMP_KIND is enabled. */
886
887void
888dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
889 tree t)
890{
891 dump_context::get ().dump_generic_expr (dump_kind, extra_dump_flags, t);
892}
893
894/* Similar to dump_generic_expr, except additionally print the source
895 location. */
896
897void
898dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
899 dump_flags_t extra_dump_flags, tree t)
900{
901 dump_context::get ().dump_generic_expr_loc (dump_kind, loc, extra_dump_flags,
902 t);
903}
904
905/* Output a formatted message using FORMAT on appropriate dump streams. */
906
907void
908dump_printf (dump_flags_t dump_kind, const char *format, ...)
909{
910 va_list ap;
911 va_start (ap, format);
912 dump_context::get ().dump_printf_va (dump_kind, format, ap);
913 va_end (ap);
914}
915
916/* Similar to dump_printf, except source location is also printed, and
917 dump location captured. */
918
919void
920dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
921 const char *format, ...)
922{
923 va_list ap;
924 va_start (ap, format);
925 dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, ap);
926 va_end (ap);
927}
928
929/* Output VALUE in decimal to appropriate dump streams. */
930
931template<unsigned int N, typename C>
932void
933dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
934{
935 dump_context::get ().dump_dec (dump_kind, value);
dc3f3805
RS
936}
937
4af78ef8
DM
938template void dump_dec (dump_flags_t, const poly_uint16 &);
939template void dump_dec (dump_flags_t, const poly_int64 &);
940template void dump_dec (dump_flags_t, const poly_uint64 &);
941template void dump_dec (dump_flags_t, const poly_offset_int &);
942template void dump_dec (dump_flags_t, const poly_widest_int &);
dc3f3805 943
370c2ebe
RS
944void
945dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
946{
947 if (dump_file && (dump_kind & pflags))
948 print_dec (value, dump_file, sgn);
949
950 if (alt_dump_file && (dump_kind & alt_flags))
951 print_dec (value, alt_dump_file, sgn);
952}
953
954/* Output VALUE in hexadecimal to appropriate dump streams. */
955
956void
957dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
958{
959 if (dump_file && (dump_kind & pflags))
960 print_hex (value, dump_file);
961
962 if (alt_dump_file && (dump_kind & alt_flags))
963 print_hex (value, alt_dump_file);
964}
965
4df3629e
DM
966/* Emit and delete the currently pending optinfo, if there is one,
967 without the caller needing to know about class dump_context. */
968
969void
970dumpfile_ensure_any_optinfo_are_flushed ()
971{
972 dump_context::get().end_any_optinfo ();
973}
974
975/* Output the name of NODE on appropriate dump streams. */
6475e077 976
4df3629e
DM
977void
978dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
979{
980 dump_context::get ().dump_symtab_node (dump_kind, node);
981}
6475e077
DM
982
983/* Get the current dump scope-nesting depth.
4df3629e 984 For use by -fopt-info (for showing nesting via indentation). */
6475e077
DM
985
986unsigned int
987get_dump_scope_depth ()
988{
4df3629e 989 return dump_context::get ().get_scope_depth ();
6475e077
DM
990}
991
992/* Push a nested dump scope.
993 Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
994 destination, if any.
4df3629e 995 Emit a "scope" opinfo if optinfos are enabled.
6475e077
DM
996 Increment the scope depth. */
997
998void
999dump_begin_scope (const char *name, const dump_location_t &loc)
1000{
4df3629e 1001 dump_context::get ().begin_scope (name, loc);
6475e077
DM
1002}
1003
1004/* Pop a nested dump scope. */
1005
1006void
1007dump_end_scope ()
1008{
4df3629e 1009 dump_context::get ().end_scope ();
6475e077
DM
1010}
1011
b5f47924
SS
1012/* Start a dump for PHASE. Store user-supplied dump flags in
1013 *FLAG_PTR. Return the number of streams opened. Set globals
1014 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
2b4e6bf1
SS
1015 set dump_flags appropriately for both pass dump stream and
1016 -fopt-info stream. */
b5f47924
SS
1017
1018int
47e0da37 1019gcc::dump_manager::
1a817418 1020dump_start (int phase, dump_flags_t *flag_ptr)
b5f47924
SS
1021{
1022 int count = 0;
1023 char *name;
1024 struct dump_file_info *dfi;
1025 FILE *stream;
74911c3c 1026 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1027 return 0;
1028
1029 dfi = get_dump_file_info (phase);
1030 name = get_dump_file_name (phase);
1031 if (name)
1032 {
5d8b352a
NS
1033 stream = dump_open (name, dfi->pstate < 0);
1034 if (stream)
b5f47924
SS
1035 {
1036 dfi->pstate = 1;
1037 count++;
1038 }
1039 free (name);
1040 dfi->pstream = stream;
29b54a9d 1041 set_dump_file (dfi->pstream);
b5f47924 1042 /* Initialize current dump flags. */
8264c84d 1043 pflags = dfi->pflags;
b5f47924
SS
1044 }
1045
1046 stream = dump_open_alternate_stream (dfi);
1047 if (stream)
1048 {
1049 dfi->alt_stream = stream;
1050 count++;
29b54a9d 1051 set_alt_dump_file (dfi->alt_stream);
2b4e6bf1 1052 /* Initialize current -fopt-info flags. */
8264c84d 1053 alt_flags = dfi->alt_flags;
b5f47924
SS
1054 }
1055
1056 if (flag_ptr)
1057 *flag_ptr = dfi->pflags;
1058
1059 return count;
1060}
1061
1062/* Finish a tree dump for PHASE and close associated dump streams. Also
1063 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
1064
1065void
47e0da37 1066gcc::dump_manager::
b5f47924
SS
1067dump_finish (int phase)
1068{
1069 struct dump_file_info *dfi;
1070
1071 if (phase < 0)
1072 return;
1073 dfi = get_dump_file_info (phase);
5d8b352a 1074 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
b5f47924
SS
1075 fclose (dfi->pstream);
1076
5d8b352a 1077 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
b5f47924
SS
1078 fclose (dfi->alt_stream);
1079
1080 dfi->alt_stream = NULL;
1081 dfi->pstream = NULL;
29b54a9d
DM
1082 set_dump_file (NULL);
1083 set_alt_dump_file (NULL);
4af78ef8
DM
1084 dump_flags = TDF_NONE;
1085 alt_flags = TDF_NONE;
1086 pflags = TDF_NONE;
b5f47924
SS
1087}
1088
1089/* Begin a tree dump for PHASE. Stores any user supplied flag in
1090 *FLAG_PTR and returns a stream to write to. If the dump is not
1091 enabled, returns NULL.
75fdb07e
JH
1092 PART can be used for dump files which should be split to multiple
1093 parts. PART == -1 indicates dump file with no parts.
1094 If PART is -1, multiple calls will reopen and append to the dump file. */
b5f47924
SS
1095
1096FILE *
75fdb07e 1097dump_begin (int phase, dump_flags_t *flag_ptr, int part)
47e0da37 1098{
75fdb07e 1099 return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
47e0da37
DM
1100}
1101
1102FILE *
1103gcc::dump_manager::
75fdb07e 1104dump_begin (int phase, dump_flags_t *flag_ptr, int part)
b5f47924
SS
1105{
1106 char *name;
1107 struct dump_file_info *dfi;
1108 FILE *stream;
1109
74911c3c 1110 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
1111 return NULL;
1112
75fdb07e 1113 name = get_dump_file_name (phase, part);
b5f47924
SS
1114 if (!name)
1115 return NULL;
1116 dfi = get_dump_file_info (phase);
1117
75fdb07e
JH
1118 /* We do not support re-opening of dump files with parts. This would require
1119 tracking pstate per part of the dump file. */
1120 stream = dump_open (name, part != -1 || dfi->pstate < 0);
5d8b352a 1121 if (stream)
b5f47924
SS
1122 dfi->pstate = 1;
1123 free (name);
1124
1125 if (flag_ptr)
1126 *flag_ptr = dfi->pflags;
1127
1128 /* Initialize current flags */
1129 pflags = dfi->pflags;
1130 return stream;
1131}
1132
1133/* Returns nonzero if dump PHASE is enabled for at least one stream.
1134 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
1135 any phase. */
1136
47e0da37
DM
1137int
1138gcc::dump_manager::
1139dump_phase_enabled_p (int phase) const
b5f47924
SS
1140{
1141 if (phase == TDI_tree_all)
1142 {
1143 size_t i;
1144 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1145 if (dump_files[i].pstate || dump_files[i].alt_state)
1146 return 1;
47e0da37
DM
1147 for (i = 0; i < m_extra_dump_files_in_use; i++)
1148 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
b5f47924
SS
1149 return 1;
1150 return 0;
1151 }
1152 else
1153 {
1154 struct dump_file_info *dfi = get_dump_file_info (phase);
1155 return dfi->pstate || dfi->alt_state;
1156 }
1157}
1158
1159/* Returns nonzero if tree dump PHASE has been initialized. */
1160
1161int
47e0da37
DM
1162gcc::dump_manager::
1163dump_initialized_p (int phase) const
b5f47924
SS
1164{
1165 struct dump_file_info *dfi = get_dump_file_info (phase);
1166 return dfi->pstate > 0 || dfi->alt_state > 0;
1167}
1168
1169/* Returns the switch name of PHASE. */
1170
1171const char *
1172dump_flag_name (int phase)
47e0da37
DM
1173{
1174 return g->get_dumps ()->dump_flag_name (phase);
1175}
1176
1177const char *
1178gcc::dump_manager::
1179dump_flag_name (int phase) const
b5f47924
SS
1180{
1181 struct dump_file_info *dfi = get_dump_file_info (phase);
1182 return dfi->swtch;
1183}
1184
1185/* Finish a tree dump for PHASE. STREAM is the stream created by
1186 dump_begin. */
1187
1188void
1189dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
1190{
1191 if (stream != stderr && stream != stdout)
1192 fclose (stream);
1193}
1194
1195/* Enable all tree dumps with FLAGS on FILENAME. Return number of
1196 enabled tree dumps. */
1197
47e0da37
DM
1198int
1199gcc::dump_manager::
8264c84d 1200dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
b5f47924 1201{
b5f47924
SS
1202 int n = 0;
1203 size_t i;
1204
1205 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1206 {
8264c84d 1207 if ((dump_files[i].dkind == dkind))
b5f47924
SS
1208 {
1209 const char *old_filename = dump_files[i].pfilename;
1210 dump_files[i].pstate = -1;
1211 dump_files[i].pflags |= flags;
1212 n++;
1213 /* Override the existing filename. */
1214 if (filename)
1215 {
1216 dump_files[i].pfilename = xstrdup (filename);
1217 /* Since it is a command-line provided file, which is
1218 common to all the phases, use it in append mode. */
1219 dump_files[i].pstate = 1;
1220 }
1221 if (old_filename && filename != old_filename)
1222 free (CONST_CAST (char *, old_filename));
1223 }
1224 }
1225
47e0da37 1226 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 1227 {
8264c84d 1228 if ((m_extra_dump_files[i].dkind == dkind))
b5f47924 1229 {
47e0da37
DM
1230 const char *old_filename = m_extra_dump_files[i].pfilename;
1231 m_extra_dump_files[i].pstate = -1;
1232 m_extra_dump_files[i].pflags |= flags;
b5f47924
SS
1233 n++;
1234 /* Override the existing filename. */
1235 if (filename)
1236 {
47e0da37 1237 m_extra_dump_files[i].pfilename = xstrdup (filename);
b5f47924
SS
1238 /* Since it is a command-line provided file, which is
1239 common to all the phases, use it in append mode. */
47e0da37 1240 m_extra_dump_files[i].pstate = 1;
b5f47924
SS
1241 }
1242 if (old_filename && filename != old_filename)
1243 free (CONST_CAST (char *, old_filename));
1244 }
1245 }
1246
1247 return n;
1248}
1249
2b4e6bf1
SS
1250/* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
1251 Enable dumps with FLAGS on FILENAME. Return the number of enabled
1252 dumps. */
b5f47924 1253
47e0da37
DM
1254int
1255gcc::dump_manager::
4af78ef8 1256opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1a817418 1257 const char *filename)
b5f47924
SS
1258{
1259 int n = 0;
1260 size_t i;
1261
1262 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1263 {
2b4e6bf1 1264 if ((dump_files[i].optgroup_flags & optgroup_flags))
b5f47924
SS
1265 {
1266 const char *old_filename = dump_files[i].alt_filename;
1267 /* Since this file is shared among different passes, it
1268 should be opened in append mode. */
1269 dump_files[i].alt_state = 1;
1270 dump_files[i].alt_flags |= flags;
1271 n++;
1272 /* Override the existing filename. */
1273 if (filename)
1274 dump_files[i].alt_filename = xstrdup (filename);
1275 if (old_filename && filename != old_filename)
1276 free (CONST_CAST (char *, old_filename));
1277 }
1278 }
1279
47e0da37 1280 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 1281 {
47e0da37 1282 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
b5f47924 1283 {
47e0da37 1284 const char *old_filename = m_extra_dump_files[i].alt_filename;
b5f47924
SS
1285 /* Since this file is shared among different passes, it
1286 should be opened in append mode. */
47e0da37
DM
1287 m_extra_dump_files[i].alt_state = 1;
1288 m_extra_dump_files[i].alt_flags |= flags;
b5f47924
SS
1289 n++;
1290 /* Override the existing filename. */
1291 if (filename)
47e0da37 1292 m_extra_dump_files[i].alt_filename = xstrdup (filename);
b5f47924
SS
1293 if (old_filename && filename != old_filename)
1294 free (CONST_CAST (char *, old_filename));
1295 }
1296 }
1297
1298 return n;
1299}
1300
1301/* Parse ARG as a dump switch. Return nonzero if it is, and store the
1302 relevant details in the dump_files array. */
1303
47e0da37
DM
1304int
1305gcc::dump_manager::
b5f47924
SS
1306dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1307{
1308 const char *option_value;
1309 const char *ptr;
1a817418 1310 dump_flags_t flags;
b5f47924
SS
1311
1312 if (doglob && !dfi->glob)
1313 return 0;
1314
1315 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1316 if (!option_value)
1317 return 0;
1318
1319 if (*option_value && *option_value != '-' && *option_value != '=')
1320 return 0;
1321
1322 ptr = option_value;
4af78ef8 1323 flags = TDF_NONE;
b5f47924
SS
1324
1325 while (*ptr)
1326 {
4af78ef8 1327 const struct kv_pair<dump_flags_t> *option_ptr;
b5f47924
SS
1328 const char *end_ptr;
1329 const char *eq_ptr;
1330 unsigned length;
1331
1332 while (*ptr == '-')
1333 ptr++;
1334 end_ptr = strchr (ptr, '-');
1335 eq_ptr = strchr (ptr, '=');
1336
1337 if (eq_ptr && !end_ptr)
1338 end_ptr = eq_ptr;
1339
1340 if (!end_ptr)
1341 end_ptr = ptr + strlen (ptr);
1342 length = end_ptr - ptr;
1343
1344 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1345 if (strlen (option_ptr->name) == length
1346 && !memcmp (option_ptr->name, ptr, length))
1347 {
1348 flags |= option_ptr->value;
1349 goto found;
1350 }
1351
1352 if (*ptr == '=')
1353 {
1354 /* Interpret rest of the argument as a dump filename. This
1355 filename overrides other command line filenames. */
1356 if (dfi->pfilename)
1357 free (CONST_CAST (char *, dfi->pfilename));
1358 dfi->pfilename = xstrdup (ptr + 1);
1359 break;
1360 }
1361 else
1362 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1363 length, ptr, dfi->swtch);
1364 found:;
1365 ptr = end_ptr;
1366 }
1367
1368 dfi->pstate = -1;
1369 dfi->pflags |= flags;
1370
1371 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1372 known dumps. */
1373 if (dfi->suffix == NULL)
8264c84d 1374 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
b5f47924
SS
1375
1376 return 1;
1377}
1378
1379int
47e0da37 1380gcc::dump_manager::
b5f47924
SS
1381dump_switch_p (const char *arg)
1382{
1383 size_t i;
1384 int any = 0;
1385
1386 for (i = TDI_none + 1; i != TDI_end; i++)
1387 any |= dump_switch_p_1 (arg, &dump_files[i], false);
1388
1389 /* Don't glob if we got a hit already */
1390 if (!any)
1391 for (i = TDI_none + 1; i != TDI_end; i++)
1392 any |= dump_switch_p_1 (arg, &dump_files[i], true);
1393
47e0da37
DM
1394 for (i = 0; i < m_extra_dump_files_in_use; i++)
1395 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
b5f47924
SS
1396
1397 if (!any)
47e0da37
DM
1398 for (i = 0; i < m_extra_dump_files_in_use; i++)
1399 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
b5f47924
SS
1400
1401
1402 return any;
1403}
1404
2b4e6bf1
SS
1405/* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
1406 and filename. Return non-zero if it is a recognized switch. */
b5f47924
SS
1407
1408static int
4af78ef8
DM
1409opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
1410 optgroup_flags_t *optgroup_flags, char **filename)
b5f47924
SS
1411{
1412 const char *option_value;
1413 const char *ptr;
1414
1415 option_value = arg;
1416 ptr = option_value;
1417
1418 *filename = NULL;
4af78ef8
DM
1419 *flags = TDF_NONE;
1420 *optgroup_flags = OPTGROUP_NONE;
b5f47924
SS
1421
1422 if (!ptr)
2b4e6bf1 1423 return 1; /* Handle '-fopt-info' without any additional options. */
b5f47924
SS
1424
1425 while (*ptr)
1426 {
b5f47924
SS
1427 const char *end_ptr;
1428 const char *eq_ptr;
1429 unsigned length;
1430
1431 while (*ptr == '-')
1432 ptr++;
1433 end_ptr = strchr (ptr, '-');
1434 eq_ptr = strchr (ptr, '=');
1435
1436 if (eq_ptr && !end_ptr)
1437 end_ptr = eq_ptr;
1438
1439 if (!end_ptr)
1440 end_ptr = ptr + strlen (ptr);
1441 length = end_ptr - ptr;
1442
4af78ef8
DM
1443 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
1444 option_ptr->name; option_ptr++)
b5f47924
SS
1445 if (strlen (option_ptr->name) == length
1446 && !memcmp (option_ptr->name, ptr, length))
1447 {
1448 *flags |= option_ptr->value;
1449 goto found;
1450 }
1451
4af78ef8
DM
1452 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
1453 option_ptr->name; option_ptr++)
2b4e6bf1
SS
1454 if (strlen (option_ptr->name) == length
1455 && !memcmp (option_ptr->name, ptr, length))
1456 {
1457 *optgroup_flags |= option_ptr->value;
1458 goto found;
1459 }
1460
b5f47924
SS
1461 if (*ptr == '=')
1462 {
1463 /* Interpret rest of the argument as a dump filename. This
1464 filename overrides other command line filenames. */
1465 *filename = xstrdup (ptr + 1);
1466 break;
1467 }
1468 else
2b4e6bf1
SS
1469 {
1470 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
1471 length, ptr, arg);
1472 return 0;
1473 }
b5f47924
SS
1474 found:;
1475 ptr = end_ptr;
1476 }
1477
1478 return 1;
1479}
1480
1481/* Return non-zero if ARG is a recognized switch for
1482 -fopt-info. Return zero otherwise. */
1483
1484int
1485opt_info_switch_p (const char *arg)
1486{
1a817418 1487 dump_flags_t flags;
4af78ef8 1488 optgroup_flags_t optgroup_flags;
b5f47924 1489 char *filename;
2b4e6bf1 1490 static char *file_seen = NULL;
47e0da37 1491 gcc::dump_manager *dumps = g->get_dumps ();
b5f47924 1492
2b4e6bf1
SS
1493 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
1494 return 0;
b5f47924
SS
1495
1496 if (!filename)
1497 filename = xstrdup ("stderr");
2b4e6bf1
SS
1498
1499 /* Bail out if a different filename has been specified. */
1500 if (file_seen && strcmp (file_seen, filename))
1501 {
1502 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1503 arg);
1504 return 1;
1505 }
1506
1507 file_seen = xstrdup (filename);
b5f47924 1508 if (!flags)
5d318fd4 1509 flags = MSG_OPTIMIZED_LOCATIONS;
2b4e6bf1
SS
1510 if (!optgroup_flags)
1511 optgroup_flags = OPTGROUP_ALL;
b5f47924 1512
47e0da37 1513 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
b5f47924
SS
1514}
1515
b5f47924
SS
1516/* Print basic block on the dump streams. */
1517
1518void
4af78ef8 1519dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
b5f47924
SS
1520{
1521 if (dump_file && (dump_kind & pflags))
1522 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1523 if (alt_dump_file && (dump_kind & alt_flags))
1524 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1525}
1526
c24e924f
NS
1527/* Dump FUNCTION_DECL FN as tree dump PHASE. */
1528
1529void
1530dump_function (int phase, tree fn)
1531{
1532 FILE *stream;
1a817418 1533 dump_flags_t flags;
c24e924f
NS
1534
1535 stream = dump_begin (phase, &flags);
1536 if (stream)
1537 {
1538 dump_function_to_file (fn, stream, flags);
1539 dump_end (phase, stream);
1540 }
1541}
1542
b5f47924
SS
1543/* Print information from the combine pass on dump_file. */
1544
1545void
1546print_combine_total_stats (void)
1547{
1548 if (dump_file)
1549 dump_combine_total_stats (dump_file);
1550}
1551
1552/* Enable RTL dump for all the RTL passes. */
1553
1554bool
1555enable_rtl_dump_file (void)
1556{
47e0da37
DM
1557 gcc::dump_manager *dumps = g->get_dumps ();
1558 int num_enabled =
8264c84d
ML
1559 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1560 NULL);
47e0da37 1561 return num_enabled > 0;
b5f47924 1562}
4f5b9c80
DM
1563
1564#if CHECKING_P
1565
4df3629e
DM
1566/* temp_dump_context's ctor. Temporarily override the dump_context
1567 (to forcibly enable optinfo-generation). */
1568
1569temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo)
1570: m_context (),
1571 m_saved (&dump_context ().get ())
1572{
1573 dump_context::s_current = &m_context;
1574 m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
1575}
1576
1577/* temp_dump_context's dtor. Restore the saved dump_context. */
1578
1579temp_dump_context::~temp_dump_context ()
1580{
1581 dump_context::s_current = m_saved;
1582}
1583
4f5b9c80
DM
1584namespace selftest {
1585
1586/* Verify that the dump_location_t constructors capture the source location
1587 at which they were called (provided that the build compiler is sufficiently
1588 recent). */
1589
1590static void
1591test_impl_location ()
1592{
1593#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
1594 /* Default ctor. */
1595 {
1596 dump_location_t loc;
1597 const int expected_line = __LINE__ - 1;
1598 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1599 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1600 }
1601
1602 /* Constructing from a gimple. */
1603 {
1604 dump_location_t loc ((gimple *)NULL);
1605 const int expected_line = __LINE__ - 1;
1606 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1607 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1608 }
1609
1610 /* Constructing from an rtx_insn. */
1611 {
1612 dump_location_t loc ((rtx_insn *)NULL);
1613 const int expected_line = __LINE__ - 1;
1614 ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
1615 ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
1616 }
1617#endif
1618}
1619
4df3629e
DM
1620/* Verify that ITEM has the expected values. */
1621
1622static void
1623verify_item (const location &loc,
1624 const optinfo_item *item,
1625 enum optinfo_item_kind expected_kind,
1626 location_t expected_location,
1627 const char *expected_text)
1628{
1629 ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
1630 ASSERT_EQ_AT (loc, item->get_location (), expected_location);
1631 ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
1632}
1633
1634/* Verify that ITEM is a text item, with EXPECTED_TEXT. */
1635
1636#define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
1637 SELFTEST_BEGIN_STMT \
1638 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
1639 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \
1640 SELFTEST_END_STMT
1641
1642/* Verify that ITEM is a tree item, with the expected values. */
1643
1644#define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1645 SELFTEST_BEGIN_STMT \
1646 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
1647 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
1648 SELFTEST_END_STMT
1649
1650/* Verify that ITEM is a gimple item, with the expected values. */
1651
1652#define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
1653 SELFTEST_BEGIN_STMT \
1654 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
1655 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \
1656 SELFTEST_END_STMT
1657
1658/* Verify that calls to the dump_* API are captured and consolidated into
1659 optimization records. */
1660
1661static void
1662test_capture_of_dump_calls (const line_table_case &case_)
1663{
1664 /* Generate a location_t for testing. */
1665 line_table_test ltt (case_);
1666 linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
1667 linemap_line_start (line_table, 5, 100);
1668 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
1669 location_t where = linemap_position_for_column (line_table, 10);
1670
1671 dump_location_t loc = dump_location_t::from_location_t (where);
1672
1673 /* Test of dump_printf. */
1674 {
1675 temp_dump_context tmp (true);
1676 dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
1677
1678 optinfo *info = tmp.get_pending_optinfo ();
1679 ASSERT_TRUE (info != NULL);
1680 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1681 ASSERT_EQ (info->num_items (), 1);
1682 ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
1683 }
1684
1685 /* Tree, via dump_generic_expr. */
1686 {
1687 temp_dump_context tmp (true);
1688 dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
1689 dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
1690
1691 optinfo *info = tmp.get_pending_optinfo ();
1692 ASSERT_TRUE (info != NULL);
1693 ASSERT_EQ (info->get_location_t (), where);
1694 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1695 ASSERT_EQ (info->num_items (), 2);
1696 ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
1697 ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
1698 }
1699
1700 /* Tree, via dump_generic_expr_loc. */
1701 {
1702 temp_dump_context tmp (true);
1703 dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
1704
1705 optinfo *info = tmp.get_pending_optinfo ();
1706 ASSERT_TRUE (info != NULL);
1707 ASSERT_EQ (info->get_location_t (), where);
1708 ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
1709 ASSERT_EQ (info->num_items (), 1);
1710 ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
1711 }
1712
1713 /* Gimple. */
1714 {
1715 greturn *stmt = gimple_build_return (NULL);
1716 gimple_set_location (stmt, where);
1717
1718 /* dump_gimple_stmt_loc. */
1719 {
1720 temp_dump_context tmp (true);
1721 dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
1722
1723 optinfo *info = tmp.get_pending_optinfo ();
1724 ASSERT_TRUE (info != NULL);
1725 ASSERT_EQ (info->num_items (), 1);
1726 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
1727 }
1728
1729 /* dump_gimple_stmt. */
1730 {
1731 temp_dump_context tmp (true);
1732 dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
1733
1734 optinfo *info = tmp.get_pending_optinfo ();
1735 ASSERT_TRUE (info != NULL);
1736 ASSERT_EQ (info->num_items (), 1);
1737 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
1738 }
1739
1740 /* dump_gimple_expr_loc. */
1741 {
1742 temp_dump_context tmp (true);
1743 dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
1744
1745 optinfo *info = tmp.get_pending_optinfo ();
1746 ASSERT_TRUE (info != NULL);
1747 ASSERT_EQ (info->num_items (), 1);
1748 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
1749 }
1750
1751 /* dump_gimple_expr. */
1752 {
1753 temp_dump_context tmp (true);
1754 dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
1755
1756 optinfo *info = tmp.get_pending_optinfo ();
1757 ASSERT_TRUE (info != NULL);
1758 ASSERT_EQ (info->num_items (), 1);
1759 ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
1760 }
1761 }
1762
1763 /* poly_int. */
1764 {
1765 temp_dump_context tmp (true);
1766 dump_dec (MSG_NOTE, poly_int64 (42));
1767
1768 optinfo *info = tmp.get_pending_optinfo ();
1769 ASSERT_TRUE (info != NULL);
1770 ASSERT_EQ (info->num_items (), 1);
1771 ASSERT_IS_TEXT (info->get_item (0), "42");
1772 }
1773
1774 /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
1775 above. */
1776 {
1777 /* MSG_OPTIMIZED_LOCATIONS. */
1778 {
1779 temp_dump_context tmp (true);
1780 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
1781 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
1782 OPTINFO_KIND_SUCCESS);
1783 }
1784
1785 /* MSG_MISSED_OPTIMIZATION. */
1786 {
1787 temp_dump_context tmp (true);
1788 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
1789 ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
1790 OPTINFO_KIND_FAILURE);
1791 }
1792 }
1793}
1794
4f5b9c80
DM
1795/* Run all of the selftests within this file. */
1796
1797void
1798dumpfile_c_tests ()
1799{
1800 test_impl_location ();
4df3629e 1801 for_each_line_table_case (test_capture_of_dump_calls);
4f5b9c80
DM
1802}
1803
1804} // namespace selftest
1805
1806#endif /* CHECKING_P */