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