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