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