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