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