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