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