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