]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dumpfile.c
Add missing noexcept on definition to match declaration
[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"
b5f47924
SS
32
33/* If non-NULL, return one past-the-end of the matching SUBPART of
34 the WHOLE string. */
35#define skip_leading_substring(whole, part) \
36 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
37
1a817418
ML
38static dump_flags_t pflags; /* current dump_flags */
39static dump_flags_t alt_flags; /* current opt_info flags */
b5f47924 40
1a817418 41static void dump_loc (dump_flags_t, FILE *, source_location);
b5f47924
SS
42static FILE *dump_open_alternate_stream (struct dump_file_info *);
43
73fbfcad
SS
44/* These are currently used for communicating between passes.
45 However, instead of accessing them directly, the passes can use
46 dump_printf () for dumps. */
47FILE *dump_file = NULL;
48FILE *alt_dump_file = NULL;
49const char *dump_file_name;
1a817418 50dump_flags_t dump_flags;
73fbfcad 51
63523736 52#define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
4af78ef8
DM
53 {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
54 OPTGROUP_NONE, 0, 0, num, false, false}
8264c84d 55
b5f47924
SS
56/* Table of tree dump switches. This must be consistent with the
57 TREE_DUMP_INDEX enumeration in dumpfile.h. */
58static struct dump_file_info dump_files[TDI_end] =
59{
63523736
ML
60 DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
61 DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
62 DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
63 DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
363dc72c
JJ
64 DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
65 DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
66 DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
b4da704c 67 DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
363dc72c 68#define FIRST_AUTO_NUMBERED_DUMP 1
29a50dfb 69#define FIRST_ME_AUTO_NUMBERED_DUMP 4
b5f47924 70
63523736
ML
71 DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
72 DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
73 DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
74 DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
b5f47924
SS
75};
76
b5f47924 77/* Define a name->number mapping for a dump flag value. */
4af78ef8
DM
78template <typename ValueType>
79struct kv_pair
b5f47924
SS
80{
81 const char *const name; /* the name of the value */
4af78ef8 82 const ValueType value; /* the value of the name */
b5f47924
SS
83};
84
85/* Table of dump options. This must be consistent with the TDF_* flags
86 in dumpfile.h and opt_info_options below. */
4af78ef8 87static const kv_pair<dump_flags_t> dump_options[] =
b5f47924
SS
88{
89 {"address", TDF_ADDRESS},
90 {"asmname", TDF_ASMNAME},
91 {"slim", TDF_SLIM},
92 {"raw", TDF_RAW},
93 {"graph", TDF_GRAPH},
94 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
95 | MSG_MISSED_OPTIMIZATION
96 | MSG_NOTE)},
97 {"cselib", TDF_CSELIB},
98 {"stats", TDF_STATS},
99 {"blocks", TDF_BLOCKS},
100 {"vops", TDF_VOPS},
101 {"lineno", TDF_LINENO},
102 {"uid", TDF_UID},
103 {"stmtaddr", TDF_STMTADDR},
104 {"memsyms", TDF_MEMSYMS},
b5f47924
SS
105 {"eh", TDF_EH},
106 {"alias", TDF_ALIAS},
107 {"nouid", TDF_NOUID},
108 {"enumerate_locals", TDF_ENUMERATE_LOCALS},
109 {"scev", TDF_SCEV},
1ee62b92 110 {"gimple", TDF_GIMPLE},
56af751e 111 {"folding", TDF_FOLDING},
f14726bd
TJ
112 {"optimized", MSG_OPTIMIZED_LOCATIONS},
113 {"missed", MSG_MISSED_OPTIMIZATION},
114 {"note", MSG_NOTE},
115 {"optall", MSG_ALL},
f6b3ca5a
JJ
116 {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
117 | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
118 | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
4af78ef8 119 {NULL, TDF_NONE}
b5f47924
SS
120};
121
2b4e6bf1
SS
122/* A subset of the dump_options table which is used for -fopt-info
123 types. This must be consistent with the MSG_* flags in dumpfile.h.
b5f47924 124 */
4af78ef8 125static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
b5f47924
SS
126{
127 {"optimized", MSG_OPTIMIZED_LOCATIONS},
128 {"missed", MSG_MISSED_OPTIMIZATION},
129 {"note", MSG_NOTE},
2b4e6bf1 130 {"all", MSG_ALL},
4af78ef8 131 {NULL, TDF_NONE}
2b4e6bf1
SS
132};
133
134/* Flags used for -fopt-info groups. */
4af78ef8 135static const kv_pair<optgroup_flags_t> optgroup_options[] =
2b4e6bf1
SS
136{
137 {"ipa", OPTGROUP_IPA},
138 {"loop", OPTGROUP_LOOP},
139 {"inline", OPTGROUP_INLINE},
fd2b8c8b 140 {"omp", OPTGROUP_OMP},
2b4e6bf1
SS
141 {"vec", OPTGROUP_VEC},
142 {"optall", OPTGROUP_ALL},
4af78ef8 143 {NULL, OPTGROUP_NONE}
b5f47924
SS
144};
145
47e0da37
DM
146gcc::dump_manager::dump_manager ():
147 m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
148 m_extra_dump_files (NULL),
149 m_extra_dump_files_in_use (0),
150 m_extra_dump_files_alloced (0)
151{
152}
153
10fdd6e9
DM
154gcc::dump_manager::~dump_manager ()
155{
156 for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
157 {
158 dump_file_info *dfi = &m_extra_dump_files[i];
159 /* suffix, swtch, glob are statically allocated for the entries
160 in dump_files, and for statistics, but are dynamically allocated
161 for those for passes. */
162 if (dfi->owns_strings)
163 {
164 XDELETEVEC (const_cast <char *> (dfi->suffix));
165 XDELETEVEC (const_cast <char *> (dfi->swtch));
166 XDELETEVEC (const_cast <char *> (dfi->glob));
167 }
168 /* These, if non-NULL, are always dynamically allocated. */
169 XDELETEVEC (const_cast <char *> (dfi->pfilename));
170 XDELETEVEC (const_cast <char *> (dfi->alt_filename));
171 }
172 XDELETEVEC (m_extra_dump_files);
173}
174
b5f47924 175unsigned int
47e0da37 176gcc::dump_manager::
b5f47924 177dump_register (const char *suffix, const char *swtch, const char *glob,
4af78ef8
DM
178 dump_kind dkind, optgroup_flags_t optgroup_flags,
179 bool take_ownership)
b5f47924 180{
47e0da37 181 int num = m_next_dump++;
b5f47924 182
47e0da37 183 size_t count = m_extra_dump_files_in_use++;
b5f47924 184
47e0da37 185 if (count >= m_extra_dump_files_alloced)
b5f47924 186 {
47e0da37 187 if (m_extra_dump_files_alloced == 0)
363dc72c 188 m_extra_dump_files_alloced = 512;
b5f47924 189 else
47e0da37
DM
190 m_extra_dump_files_alloced *= 2;
191 m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
192 m_extra_dump_files,
193 m_extra_dump_files_alloced);
c3684b7b
MS
194
195 /* Construct a new object in the space allocated above. */
196 new (m_extra_dump_files + count) dump_file_info ();
197 }
198 else
199 {
200 /* Zero out the already constructed object. */
201 m_extra_dump_files[count] = dump_file_info ();
b5f47924
SS
202 }
203
47e0da37
DM
204 m_extra_dump_files[count].suffix = suffix;
205 m_extra_dump_files[count].swtch = swtch;
206 m_extra_dump_files[count].glob = glob;
8264c84d 207 m_extra_dump_files[count].dkind = dkind;
47e0da37
DM
208 m_extra_dump_files[count].optgroup_flags = optgroup_flags;
209 m_extra_dump_files[count].num = num;
10fdd6e9 210 m_extra_dump_files[count].owns_strings = take_ownership;
b5f47924
SS
211
212 return count + TDI_end;
213}
214
215
363dc72c
JJ
216/* Allow languages and middle-end to register their dumps before the
217 optimization passes. */
218
219void
220gcc::dump_manager::
221register_dumps ()
222{
223 lang_hooks.register_dumps (this);
224 /* If this assert fails, some FE registered more than
225 FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
226 dump files. Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly. */
227 gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
228 m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
229 dump_files[TDI_original].num = m_next_dump++;
230 dump_files[TDI_gimple].num = m_next_dump++;
231 dump_files[TDI_nested].num = m_next_dump++;
232}
233
234
b5f47924
SS
235/* Return the dump_file_info for the given phase. */
236
237struct dump_file_info *
47e0da37
DM
238gcc::dump_manager::
239get_dump_file_info (int phase) const
b5f47924
SS
240{
241 if (phase < TDI_end)
242 return &dump_files[phase];
47e0da37 243 else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
b5f47924
SS
244 return NULL;
245 else
47e0da37 246 return m_extra_dump_files + (phase - TDI_end);
b5f47924
SS
247}
248
799505ae
DM
249/* Locate the dump_file_info with swtch equal to SWTCH,
250 or return NULL if no such dump_file_info exists. */
251
252struct dump_file_info *
253gcc::dump_manager::
254get_dump_file_info_by_switch (const char *swtch) const
255{
256 for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
01512446 257 if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
799505ae
DM
258 return &m_extra_dump_files[i];
259
260 /* Not found. */
261 return NULL;
262}
263
b5f47924
SS
264
265/* Return the name of the dump file for the given phase.
799505ae
DM
266 The caller is responsible for calling free on the returned
267 buffer.
b5f47924
SS
268 If the dump is not enabled, returns NULL. */
269
270char *
47e0da37
DM
271gcc::dump_manager::
272get_dump_file_name (int phase) const
b5f47924 273{
b5f47924
SS
274 struct dump_file_info *dfi;
275
276 if (phase == TDI_none)
277 return NULL;
278
279 dfi = get_dump_file_info (phase);
799505ae
DM
280
281 return get_dump_file_name (dfi);
282}
283
284/* Return the name of the dump file for the given dump_file_info.
285 The caller is responsible for calling free on the returned
286 buffer.
287 If the dump is not enabled, returns NULL. */
288
289char *
290gcc::dump_manager::
291get_dump_file_name (struct dump_file_info *dfi) const
292{
293 char dump_id[10];
294
295 gcc_assert (dfi);
296
b5f47924
SS
297 if (dfi->pstate == 0)
298 return NULL;
299
300 /* If available, use the command line dump filename. */
301 if (dfi->pfilename)
302 return xstrdup (dfi->pfilename);
303
304 if (dfi->num < 0)
305 dump_id[0] = '\0';
306 else
307 {
8264c84d
ML
308 /* (null), LANG, TREE, RTL, IPA. */
309 char suffix = " ltri"[dfi->dkind];
a529e0a6 310
8264c84d 311 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
b5f47924
SS
312 dump_id[0] = '\0';
313 }
314
315 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
316}
317
5d8b352a
NS
318/* Open a dump file called FILENAME. Some filenames are special and
319 refer to the standard streams. TRUNC indicates whether this is the
320 first open (so the file should be truncated, rather than appended).
321 An error message is emitted in the event of failure. */
322
323static FILE *
324dump_open (const char *filename, bool trunc)
325{
326 if (strcmp ("stderr", filename) == 0)
327 return stderr;
328
bd9918c4
NS
329 if (strcmp ("stdout", filename) == 0
330 || strcmp ("-", filename) == 0)
5d8b352a
NS
331 return stdout;
332
333 FILE *stream = fopen (filename, trunc ? "w" : "a");
334
335 if (!stream)
336 error ("could not open dump file %qs: %m", filename);
337 return stream;
338}
339
b5f47924
SS
340/* For a given DFI, open an alternate dump filename (which could also
341 be a standard stream such as stdout/stderr). If the alternate dump
342 file cannot be opened, return NULL. */
343
344static FILE *
345dump_open_alternate_stream (struct dump_file_info *dfi)
346{
b5f47924
SS
347 if (!dfi->alt_filename)
348 return NULL;
349
350 if (dfi->alt_stream)
351 return dfi->alt_stream;
352
5d8b352a 353 FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
b5f47924 354
5d8b352a 355 if (stream)
b5f47924
SS
356 dfi->alt_state = 1;
357
358 return stream;
359}
360
361/* Print source location on DFILE if enabled. */
362
363void
1a817418 364dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
b5f47924 365{
b5f47924
SS
366 if (dump_kind)
367 {
502498d5 368 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
e645e942 369 fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc),
103ff0d6 370 LOCATION_LINE (loc), LOCATION_COLUMN (loc));
a3d7af04 371 else if (current_function_decl)
e645e942 372 fprintf (dfile, "%s:%d:%d: note: ",
b5f47924 373 DECL_SOURCE_FILE (current_function_decl),
103ff0d6
TJ
374 DECL_SOURCE_LINE (current_function_decl),
375 DECL_SOURCE_COLUMN (current_function_decl));
b5f47924
SS
376 }
377}
378
379/* Dump gimple statement GS with SPC indentation spaces and
380 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
381
382void
1a817418
ML
383dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
384 gimple *gs, int spc)
b5f47924
SS
385{
386 if (dump_file && (dump_kind & pflags))
387 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
388
389 if (alt_dump_file && (dump_kind & alt_flags))
390 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
391}
392
393/* Similar to dump_gimple_stmt, except additionally print source location. */
394
395void
1a817418
ML
396dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
397 dump_flags_t extra_dump_flags, gimple *gs, int spc)
b5f47924
SS
398{
399 if (dump_file && (dump_kind & pflags))
400 {
401 dump_loc (dump_kind, dump_file, loc);
402 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
403 }
404
405 if (alt_dump_file && (dump_kind & alt_flags))
406 {
407 dump_loc (dump_kind, alt_dump_file, loc);
408 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
409 }
410}
411
412/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
413 DUMP_KIND is enabled. */
414
415void
1a817418
ML
416dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
417 tree t)
b5f47924
SS
418{
419 if (dump_file && (dump_kind & pflags))
420 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
421
422 if (alt_dump_file && (dump_kind & alt_flags))
423 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
424}
425
426
427/* Similar to dump_generic_expr, except additionally print the source
428 location. */
429
430void
4af78ef8 431dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
1a817418 432 dump_flags_t extra_dump_flags, tree t)
b5f47924
SS
433{
434 if (dump_file && (dump_kind & pflags))
435 {
436 dump_loc (dump_kind, dump_file, loc);
437 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
438 }
439
440 if (alt_dump_file && (dump_kind & alt_flags))
441 {
442 dump_loc (dump_kind, alt_dump_file, loc);
443 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
444 }
445}
446
447/* Output a formatted message using FORMAT on appropriate dump streams. */
448
449void
1a817418 450dump_printf (dump_flags_t dump_kind, const char *format, ...)
b5f47924
SS
451{
452 if (dump_file && (dump_kind & pflags))
453 {
454 va_list ap;
455 va_start (ap, format);
456 vfprintf (dump_file, format, ap);
457 va_end (ap);
458 }
459
460 if (alt_dump_file && (dump_kind & alt_flags))
461 {
462 va_list ap;
463 va_start (ap, format);
464 vfprintf (alt_dump_file, format, ap);
465 va_end (ap);
466 }
467}
468
469/* Similar to dump_printf, except source location is also printed. */
470
471void
1a817418
ML
472dump_printf_loc (dump_flags_t dump_kind, source_location loc,
473 const char *format, ...)
b5f47924
SS
474{
475 if (dump_file && (dump_kind & pflags))
476 {
477 va_list ap;
478 dump_loc (dump_kind, dump_file, loc);
479 va_start (ap, format);
480 vfprintf (dump_file, format, ap);
481 va_end (ap);
482 }
483
484 if (alt_dump_file && (dump_kind & alt_flags))
485 {
486 va_list ap;
487 dump_loc (dump_kind, alt_dump_file, loc);
488 va_start (ap, format);
489 vfprintf (alt_dump_file, format, ap);
490 va_end (ap);
491 }
492}
493
dc3f3805
RS
494/* Output VALUE in decimal to appropriate dump streams. */
495
496template<unsigned int N, typename C>
497void
4af78ef8 498dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
dc3f3805
RS
499{
500 STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
501 signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
502 if (dump_file && (dump_kind & pflags))
503 print_dec (value, dump_file, sgn);
504
505 if (alt_dump_file && (dump_kind & alt_flags))
506 print_dec (value, alt_dump_file, sgn);
507}
508
4af78ef8
DM
509template void dump_dec (dump_flags_t, const poly_uint16 &);
510template void dump_dec (dump_flags_t, const poly_int64 &);
511template void dump_dec (dump_flags_t, const poly_uint64 &);
512template void dump_dec (dump_flags_t, const poly_offset_int &);
513template void dump_dec (dump_flags_t, const poly_widest_int &);
dc3f3805 514
b5f47924
SS
515/* Start a dump for PHASE. Store user-supplied dump flags in
516 *FLAG_PTR. Return the number of streams opened. Set globals
517 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
2b4e6bf1
SS
518 set dump_flags appropriately for both pass dump stream and
519 -fopt-info stream. */
b5f47924
SS
520
521int
47e0da37 522gcc::dump_manager::
1a817418 523dump_start (int phase, dump_flags_t *flag_ptr)
b5f47924
SS
524{
525 int count = 0;
526 char *name;
527 struct dump_file_info *dfi;
528 FILE *stream;
74911c3c 529 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
530 return 0;
531
532 dfi = get_dump_file_info (phase);
533 name = get_dump_file_name (phase);
534 if (name)
535 {
5d8b352a
NS
536 stream = dump_open (name, dfi->pstate < 0);
537 if (stream)
b5f47924
SS
538 {
539 dfi->pstate = 1;
540 count++;
541 }
542 free (name);
543 dfi->pstream = stream;
544 dump_file = dfi->pstream;
545 /* Initialize current dump flags. */
8264c84d 546 pflags = dfi->pflags;
b5f47924
SS
547 }
548
549 stream = dump_open_alternate_stream (dfi);
550 if (stream)
551 {
552 dfi->alt_stream = stream;
553 count++;
554 alt_dump_file = dfi->alt_stream;
2b4e6bf1 555 /* Initialize current -fopt-info flags. */
8264c84d 556 alt_flags = dfi->alt_flags;
b5f47924
SS
557 }
558
559 if (flag_ptr)
560 *flag_ptr = dfi->pflags;
561
562 return count;
563}
564
565/* Finish a tree dump for PHASE and close associated dump streams. Also
566 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
567
568void
47e0da37 569gcc::dump_manager::
b5f47924
SS
570dump_finish (int phase)
571{
572 struct dump_file_info *dfi;
573
574 if (phase < 0)
575 return;
576 dfi = get_dump_file_info (phase);
5d8b352a 577 if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
b5f47924
SS
578 fclose (dfi->pstream);
579
5d8b352a 580 if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
b5f47924
SS
581 fclose (dfi->alt_stream);
582
583 dfi->alt_stream = NULL;
584 dfi->pstream = NULL;
585 dump_file = NULL;
586 alt_dump_file = NULL;
4af78ef8
DM
587 dump_flags = TDF_NONE;
588 alt_flags = TDF_NONE;
589 pflags = TDF_NONE;
b5f47924
SS
590}
591
592/* Begin a tree dump for PHASE. Stores any user supplied flag in
593 *FLAG_PTR and returns a stream to write to. If the dump is not
594 enabled, returns NULL.
595 Multiple calls will reopen and append to the dump file. */
596
597FILE *
1a817418 598dump_begin (int phase, dump_flags_t *flag_ptr)
47e0da37
DM
599{
600 return g->get_dumps ()->dump_begin (phase, flag_ptr);
601}
602
603FILE *
604gcc::dump_manager::
1a817418 605dump_begin (int phase, dump_flags_t *flag_ptr)
b5f47924
SS
606{
607 char *name;
608 struct dump_file_info *dfi;
609 FILE *stream;
610
74911c3c 611 if (phase == TDI_none || !dump_phase_enabled_p (phase))
b5f47924
SS
612 return NULL;
613
614 name = get_dump_file_name (phase);
615 if (!name)
616 return NULL;
617 dfi = get_dump_file_info (phase);
618
5d8b352a
NS
619 stream = dump_open (name, dfi->pstate < 0);
620 if (stream)
b5f47924
SS
621 dfi->pstate = 1;
622 free (name);
623
624 if (flag_ptr)
625 *flag_ptr = dfi->pflags;
626
627 /* Initialize current flags */
628 pflags = dfi->pflags;
629 return stream;
630}
631
632/* Returns nonzero if dump PHASE is enabled for at least one stream.
633 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
634 any phase. */
635
47e0da37
DM
636int
637gcc::dump_manager::
638dump_phase_enabled_p (int phase) const
b5f47924
SS
639{
640 if (phase == TDI_tree_all)
641 {
642 size_t i;
643 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
644 if (dump_files[i].pstate || dump_files[i].alt_state)
645 return 1;
47e0da37
DM
646 for (i = 0; i < m_extra_dump_files_in_use; i++)
647 if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
b5f47924
SS
648 return 1;
649 return 0;
650 }
651 else
652 {
653 struct dump_file_info *dfi = get_dump_file_info (phase);
654 return dfi->pstate || dfi->alt_state;
655 }
656}
657
658/* Returns nonzero if tree dump PHASE has been initialized. */
659
660int
47e0da37
DM
661gcc::dump_manager::
662dump_initialized_p (int phase) const
b5f47924
SS
663{
664 struct dump_file_info *dfi = get_dump_file_info (phase);
665 return dfi->pstate > 0 || dfi->alt_state > 0;
666}
667
668/* Returns the switch name of PHASE. */
669
670const char *
671dump_flag_name (int phase)
47e0da37
DM
672{
673 return g->get_dumps ()->dump_flag_name (phase);
674}
675
676const char *
677gcc::dump_manager::
678dump_flag_name (int phase) const
b5f47924
SS
679{
680 struct dump_file_info *dfi = get_dump_file_info (phase);
681 return dfi->swtch;
682}
683
684/* Finish a tree dump for PHASE. STREAM is the stream created by
685 dump_begin. */
686
687void
688dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
689{
690 if (stream != stderr && stream != stdout)
691 fclose (stream);
692}
693
694/* Enable all tree dumps with FLAGS on FILENAME. Return number of
695 enabled tree dumps. */
696
47e0da37
DM
697int
698gcc::dump_manager::
8264c84d 699dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
b5f47924 700{
b5f47924
SS
701 int n = 0;
702 size_t i;
703
704 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
705 {
8264c84d 706 if ((dump_files[i].dkind == dkind))
b5f47924
SS
707 {
708 const char *old_filename = dump_files[i].pfilename;
709 dump_files[i].pstate = -1;
710 dump_files[i].pflags |= flags;
711 n++;
712 /* Override the existing filename. */
713 if (filename)
714 {
715 dump_files[i].pfilename = xstrdup (filename);
716 /* Since it is a command-line provided file, which is
717 common to all the phases, use it in append mode. */
718 dump_files[i].pstate = 1;
719 }
720 if (old_filename && filename != old_filename)
721 free (CONST_CAST (char *, old_filename));
722 }
723 }
724
47e0da37 725 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 726 {
8264c84d 727 if ((m_extra_dump_files[i].dkind == dkind))
b5f47924 728 {
47e0da37
DM
729 const char *old_filename = m_extra_dump_files[i].pfilename;
730 m_extra_dump_files[i].pstate = -1;
731 m_extra_dump_files[i].pflags |= flags;
b5f47924
SS
732 n++;
733 /* Override the existing filename. */
734 if (filename)
735 {
47e0da37 736 m_extra_dump_files[i].pfilename = xstrdup (filename);
b5f47924
SS
737 /* Since it is a command-line provided file, which is
738 common to all the phases, use it in append mode. */
47e0da37 739 m_extra_dump_files[i].pstate = 1;
b5f47924
SS
740 }
741 if (old_filename && filename != old_filename)
742 free (CONST_CAST (char *, old_filename));
743 }
744 }
745
746 return n;
747}
748
2b4e6bf1
SS
749/* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
750 Enable dumps with FLAGS on FILENAME. Return the number of enabled
751 dumps. */
b5f47924 752
47e0da37
DM
753int
754gcc::dump_manager::
4af78ef8 755opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
1a817418 756 const char *filename)
b5f47924
SS
757{
758 int n = 0;
759 size_t i;
760
761 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
762 {
2b4e6bf1 763 if ((dump_files[i].optgroup_flags & optgroup_flags))
b5f47924
SS
764 {
765 const char *old_filename = dump_files[i].alt_filename;
766 /* Since this file is shared among different passes, it
767 should be opened in append mode. */
768 dump_files[i].alt_state = 1;
769 dump_files[i].alt_flags |= flags;
770 n++;
771 /* Override the existing filename. */
772 if (filename)
773 dump_files[i].alt_filename = xstrdup (filename);
774 if (old_filename && filename != old_filename)
775 free (CONST_CAST (char *, old_filename));
776 }
777 }
778
47e0da37 779 for (i = 0; i < m_extra_dump_files_in_use; i++)
b5f47924 780 {
47e0da37 781 if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
b5f47924 782 {
47e0da37 783 const char *old_filename = m_extra_dump_files[i].alt_filename;
b5f47924
SS
784 /* Since this file is shared among different passes, it
785 should be opened in append mode. */
47e0da37
DM
786 m_extra_dump_files[i].alt_state = 1;
787 m_extra_dump_files[i].alt_flags |= flags;
b5f47924
SS
788 n++;
789 /* Override the existing filename. */
790 if (filename)
47e0da37 791 m_extra_dump_files[i].alt_filename = xstrdup (filename);
b5f47924
SS
792 if (old_filename && filename != old_filename)
793 free (CONST_CAST (char *, old_filename));
794 }
795 }
796
797 return n;
798}
799
800/* Parse ARG as a dump switch. Return nonzero if it is, and store the
801 relevant details in the dump_files array. */
802
47e0da37
DM
803int
804gcc::dump_manager::
b5f47924
SS
805dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
806{
807 const char *option_value;
808 const char *ptr;
1a817418 809 dump_flags_t flags;
b5f47924
SS
810
811 if (doglob && !dfi->glob)
812 return 0;
813
814 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
815 if (!option_value)
816 return 0;
817
818 if (*option_value && *option_value != '-' && *option_value != '=')
819 return 0;
820
821 ptr = option_value;
4af78ef8 822 flags = TDF_NONE;
b5f47924
SS
823
824 while (*ptr)
825 {
4af78ef8 826 const struct kv_pair<dump_flags_t> *option_ptr;
b5f47924
SS
827 const char *end_ptr;
828 const char *eq_ptr;
829 unsigned length;
830
831 while (*ptr == '-')
832 ptr++;
833 end_ptr = strchr (ptr, '-');
834 eq_ptr = strchr (ptr, '=');
835
836 if (eq_ptr && !end_ptr)
837 end_ptr = eq_ptr;
838
839 if (!end_ptr)
840 end_ptr = ptr + strlen (ptr);
841 length = end_ptr - ptr;
842
843 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
844 if (strlen (option_ptr->name) == length
845 && !memcmp (option_ptr->name, ptr, length))
846 {
847 flags |= option_ptr->value;
848 goto found;
849 }
850
851 if (*ptr == '=')
852 {
853 /* Interpret rest of the argument as a dump filename. This
854 filename overrides other command line filenames. */
855 if (dfi->pfilename)
856 free (CONST_CAST (char *, dfi->pfilename));
857 dfi->pfilename = xstrdup (ptr + 1);
858 break;
859 }
860 else
861 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
862 length, ptr, dfi->swtch);
863 found:;
864 ptr = end_ptr;
865 }
866
867 dfi->pstate = -1;
868 dfi->pflags |= flags;
869
870 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
871 known dumps. */
872 if (dfi->suffix == NULL)
8264c84d 873 dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
b5f47924
SS
874
875 return 1;
876}
877
878int
47e0da37 879gcc::dump_manager::
b5f47924
SS
880dump_switch_p (const char *arg)
881{
882 size_t i;
883 int any = 0;
884
885 for (i = TDI_none + 1; i != TDI_end; i++)
886 any |= dump_switch_p_1 (arg, &dump_files[i], false);
887
888 /* Don't glob if we got a hit already */
889 if (!any)
890 for (i = TDI_none + 1; i != TDI_end; i++)
891 any |= dump_switch_p_1 (arg, &dump_files[i], true);
892
47e0da37
DM
893 for (i = 0; i < m_extra_dump_files_in_use; i++)
894 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
b5f47924
SS
895
896 if (!any)
47e0da37
DM
897 for (i = 0; i < m_extra_dump_files_in_use; i++)
898 any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
b5f47924
SS
899
900
901 return any;
902}
903
2b4e6bf1
SS
904/* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
905 and filename. Return non-zero if it is a recognized switch. */
b5f47924
SS
906
907static int
4af78ef8
DM
908opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
909 optgroup_flags_t *optgroup_flags, char **filename)
b5f47924
SS
910{
911 const char *option_value;
912 const char *ptr;
913
914 option_value = arg;
915 ptr = option_value;
916
917 *filename = NULL;
4af78ef8
DM
918 *flags = TDF_NONE;
919 *optgroup_flags = OPTGROUP_NONE;
b5f47924
SS
920
921 if (!ptr)
2b4e6bf1 922 return 1; /* Handle '-fopt-info' without any additional options. */
b5f47924
SS
923
924 while (*ptr)
925 {
b5f47924
SS
926 const char *end_ptr;
927 const char *eq_ptr;
928 unsigned length;
929
930 while (*ptr == '-')
931 ptr++;
932 end_ptr = strchr (ptr, '-');
933 eq_ptr = strchr (ptr, '=');
934
935 if (eq_ptr && !end_ptr)
936 end_ptr = eq_ptr;
937
938 if (!end_ptr)
939 end_ptr = ptr + strlen (ptr);
940 length = end_ptr - ptr;
941
4af78ef8
DM
942 for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
943 option_ptr->name; option_ptr++)
b5f47924
SS
944 if (strlen (option_ptr->name) == length
945 && !memcmp (option_ptr->name, ptr, length))
946 {
947 *flags |= option_ptr->value;
948 goto found;
949 }
950
4af78ef8
DM
951 for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
952 option_ptr->name; option_ptr++)
2b4e6bf1
SS
953 if (strlen (option_ptr->name) == length
954 && !memcmp (option_ptr->name, ptr, length))
955 {
956 *optgroup_flags |= option_ptr->value;
957 goto found;
958 }
959
b5f47924
SS
960 if (*ptr == '=')
961 {
962 /* Interpret rest of the argument as a dump filename. This
963 filename overrides other command line filenames. */
964 *filename = xstrdup (ptr + 1);
965 break;
966 }
967 else
2b4e6bf1
SS
968 {
969 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
970 length, ptr, arg);
971 return 0;
972 }
b5f47924
SS
973 found:;
974 ptr = end_ptr;
975 }
976
977 return 1;
978}
979
980/* Return non-zero if ARG is a recognized switch for
981 -fopt-info. Return zero otherwise. */
982
983int
984opt_info_switch_p (const char *arg)
985{
1a817418 986 dump_flags_t flags;
4af78ef8 987 optgroup_flags_t optgroup_flags;
b5f47924 988 char *filename;
2b4e6bf1 989 static char *file_seen = NULL;
47e0da37 990 gcc::dump_manager *dumps = g->get_dumps ();
b5f47924 991
2b4e6bf1
SS
992 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
993 return 0;
b5f47924
SS
994
995 if (!filename)
996 filename = xstrdup ("stderr");
2b4e6bf1
SS
997
998 /* Bail out if a different filename has been specified. */
999 if (file_seen && strcmp (file_seen, filename))
1000 {
1001 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
1002 arg);
1003 return 1;
1004 }
1005
1006 file_seen = xstrdup (filename);
b5f47924 1007 if (!flags)
5d318fd4 1008 flags = MSG_OPTIMIZED_LOCATIONS;
2b4e6bf1
SS
1009 if (!optgroup_flags)
1010 optgroup_flags = OPTGROUP_ALL;
b5f47924 1011
47e0da37 1012 return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
b5f47924
SS
1013}
1014
b5f47924
SS
1015/* Print basic block on the dump streams. */
1016
1017void
4af78ef8 1018dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
b5f47924
SS
1019{
1020 if (dump_file && (dump_kind & pflags))
1021 dump_bb (dump_file, bb, indent, TDF_DETAILS);
1022 if (alt_dump_file && (dump_kind & alt_flags))
1023 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
1024}
1025
c24e924f
NS
1026/* Dump FUNCTION_DECL FN as tree dump PHASE. */
1027
1028void
1029dump_function (int phase, tree fn)
1030{
1031 FILE *stream;
1a817418 1032 dump_flags_t flags;
c24e924f
NS
1033
1034 stream = dump_begin (phase, &flags);
1035 if (stream)
1036 {
1037 dump_function_to_file (fn, stream, flags);
1038 dump_end (phase, stream);
1039 }
1040}
1041
b5f47924
SS
1042/* Print information from the combine pass on dump_file. */
1043
1044void
1045print_combine_total_stats (void)
1046{
1047 if (dump_file)
1048 dump_combine_total_stats (dump_file);
1049}
1050
1051/* Enable RTL dump for all the RTL passes. */
1052
1053bool
1054enable_rtl_dump_file (void)
1055{
47e0da37
DM
1056 gcc::dump_manager *dumps = g->get_dumps ();
1057 int num_enabled =
8264c84d
ML
1058 dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
1059 NULL);
47e0da37 1060 return num_enabled > 0;
b5f47924 1061}