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