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