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