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