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