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