1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 2010 Free Software Foundation, Inc.
4 Written by Mark Mitchell <mark@codesourcery.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
27 #include "splay-tree.h"
29 #include "tree-dump.h"
30 #include "tree-pass.h"
31 #include "langhooks.h"
32 #include "tree-iterator.h"
34 static unsigned int queue (dump_info_p
, const_tree
, int);
35 static void dump_index (dump_info_p
, unsigned int);
36 static void dequeue_and_dump (dump_info_p
);
37 static void dump_new_line (dump_info_p
);
38 static void dump_maybe_newline (dump_info_p
);
40 /* Add T to the end of the queue of nodes to dump. Returns the index
44 queue (dump_info_p di
, const_tree t
, int flags
)
50 /* Assign the next available index to T. */
53 /* Obtain a new queue node. */
57 di
->free_list
= dq
->next
;
60 dq
= XNEW (struct dump_queue
);
62 /* Create a new entry in the splay-tree. */
63 dni
= XNEW (struct dump_node_info
);
65 dni
->binfo_p
= ((flags
& DUMP_BINFO
) != 0);
66 dq
->node
= splay_tree_insert (di
->nodes
, (splay_tree_key
) t
,
67 (splay_tree_value
) dni
);
69 /* Add it to the end of the queue. */
74 di
->queue_end
->next
= dq
;
77 /* Return the index. */
82 dump_index (dump_info_p di
, unsigned int index
)
84 fprintf (di
->stream
, "@%-6u ", index
);
88 /* If T has not already been output, queue it for subsequent output.
89 FIELD is a string to print before printing the index. Then, the
90 index of T is printed. */
93 queue_and_dump_index (dump_info_p di
, const char *field
, const_tree t
, int flags
)
98 /* If there's no node, just return. This makes for fewer checks in
103 /* See if we've already queued or dumped this node. */
104 n
= splay_tree_lookup (di
->nodes
, (splay_tree_key
) t
);
106 index
= ((dump_node_info_p
) n
->value
)->index
;
108 /* If we haven't, add it to the queue. */
109 index
= queue (di
, t
, flags
);
111 /* Print the index of the node. */
112 dump_maybe_newline (di
);
113 fprintf (di
->stream
, "%-4s: ", field
);
115 dump_index (di
, index
);
118 /* Dump the type of T. */
121 queue_and_dump_type (dump_info_p di
, const_tree t
)
123 queue_and_dump_index (di
, "type", TREE_TYPE (t
), DUMP_NONE
);
126 /* Dump column control */
127 #define SOL_COLUMN 25 /* Start of line column. */
128 #define EOL_COLUMN 55 /* End of line column. */
129 #define COLUMN_ALIGNMENT 15 /* Alignment. */
131 /* Insert a new line in the dump output, and indent to an appropriate
132 place to start printing more fields. */
135 dump_new_line (dump_info_p di
)
137 fprintf (di
->stream
, "\n%*s", SOL_COLUMN
, "");
138 di
->column
= SOL_COLUMN
;
141 /* If necessary, insert a new line. */
144 dump_maybe_newline (dump_info_p di
)
148 /* See if we need a new line. */
149 if (di
->column
> EOL_COLUMN
)
151 /* See if we need any padding. */
152 else if ((extra
= (di
->column
- SOL_COLUMN
) % COLUMN_ALIGNMENT
) != 0)
154 fprintf (di
->stream
, "%*s", COLUMN_ALIGNMENT
- extra
, "");
155 di
->column
+= COLUMN_ALIGNMENT
- extra
;
159 /* Dump pointer PTR using FIELD to identify it. */
162 dump_pointer (dump_info_p di
, const char *field
, void *ptr
)
164 dump_maybe_newline (di
);
165 fprintf (di
->stream
, "%-4s: %-8lx ", field
, (unsigned long) ptr
);
169 /* Dump integer I using FIELD to identify it. */
172 dump_int (dump_info_p di
, const char *field
, int i
)
174 dump_maybe_newline (di
);
175 fprintf (di
->stream
, "%-4s: %-7d ", field
, i
);
179 /* Dump the floating point value R, using FIELD to identify it. */
182 dump_real (dump_info_p di
, const char *field
, const REAL_VALUE_TYPE
*r
)
185 real_to_decimal (buf
, r
, sizeof (buf
), 0, true);
186 dump_maybe_newline (di
);
187 fprintf (di
->stream
, "%-4s: %s ", field
, buf
);
188 di
->column
+= strlen (buf
) + 7;
191 /* Dump the fixed-point value F, using FIELD to identify it. */
194 dump_fixed (dump_info_p di
, const char *field
, const FIXED_VALUE_TYPE
*f
)
197 fixed_to_decimal (buf
, f
, sizeof (buf
));
198 dump_maybe_newline (di
);
199 fprintf (di
->stream
, "%-4s: %s ", field
, buf
);
200 di
->column
+= strlen (buf
) + 7;
204 /* Dump the string S. */
207 dump_string (dump_info_p di
, const char *string
)
209 dump_maybe_newline (di
);
210 fprintf (di
->stream
, "%-13s ", string
);
211 if (strlen (string
) > 13)
212 di
->column
+= strlen (string
) + 1;
217 /* Dump the string field S. */
220 dump_string_field (dump_info_p di
, const char *field
, const char *string
)
222 dump_maybe_newline (di
);
223 fprintf (di
->stream
, "%-4s: %-7s ", field
, string
);
224 if (strlen (string
) > 7)
225 di
->column
+= 6 + strlen (string
) + 1;
230 /* Dump the next node in the queue. */
233 dequeue_and_dump (dump_info_p di
)
237 dump_node_info_p dni
;
241 enum tree_code_class code_class
;
242 const char* code_name
;
244 /* Get the next node from the queue. */
248 dni
= (dump_node_info_p
) stn
->value
;
251 /* Remove the node from the queue, and put it on the free list. */
252 di
->queue
= dq
->next
;
255 dq
->next
= di
->free_list
;
258 /* Print the node index. */
259 dump_index (di
, index
);
260 /* And the type of node this is. */
264 code_name
= tree_code_name
[(int) TREE_CODE (t
)];
265 fprintf (di
->stream
, "%-16s ", code_name
);
268 /* Figure out what kind of node this is. */
269 code
= TREE_CODE (t
);
270 code_class
= TREE_CODE_CLASS (code
);
272 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
278 VEC(tree
,gc
) *accesses
= BINFO_BASE_ACCESSES (t
);
280 dump_child ("type", BINFO_TYPE (t
));
282 if (BINFO_VIRTUAL_P (t
))
283 dump_string_field (di
, "spec", "virt");
285 dump_int (di
, "bases", BINFO_N_BASE_BINFOS (t
));
286 for (ix
= 0; BINFO_BASE_ITERATE (t
, ix
, base
); ix
++)
288 tree access
= (accesses
? VEC_index (tree
, accesses
, ix
)
289 : access_public_node
);
290 const char *string
= NULL
;
292 if (access
== access_public_node
)
294 else if (access
== access_protected_node
)
296 else if (access
== access_private_node
)
301 dump_string_field (di
, "accs", string
);
302 queue_and_dump_index (di
, "binf", base
, DUMP_BINFO
);
308 /* We can knock off a bunch of expression nodes in exactly the same
310 if (IS_EXPR_CODE_CLASS (code_class
))
312 /* If we're dumping children, dump them now. */
313 queue_and_dump_type (di
, t
);
318 dump_child ("op 0", TREE_OPERAND (t
, 0));
323 dump_child ("op 0", TREE_OPERAND (t
, 0));
324 dump_child ("op 1", TREE_OPERAND (t
, 1));
331 /* These nodes are handled explicitly below. */
340 expanded_location xloc
;
341 /* All declarations have names. */
343 dump_child ("name", DECL_NAME (t
));
344 if (DECL_ASSEMBLER_NAME_SET_P (t
)
345 && DECL_ASSEMBLER_NAME (t
) != DECL_NAME (t
))
346 dump_child ("mngl", DECL_ASSEMBLER_NAME (t
));
347 if (DECL_ABSTRACT_ORIGIN (t
))
348 dump_child ("orig", DECL_ABSTRACT_ORIGIN (t
));
350 queue_and_dump_type (di
, t
);
351 dump_child ("scpe", DECL_CONTEXT (t
));
352 /* And a source position. */
353 xloc
= expand_location (DECL_SOURCE_LOCATION (t
));
356 const char *filename
= strrchr (xloc
.file
, '/');
358 filename
= xloc
.file
;
360 /* Skip the slash. */
363 dump_maybe_newline (di
);
364 fprintf (di
->stream
, "srcp: %s:%-6d ", filename
,
366 di
->column
+= 6 + strlen (filename
) + 8;
368 /* And any declaration can be compiler-generated. */
369 if (CODE_CONTAINS_STRUCT (TREE_CODE (t
), TS_DECL_COMMON
)
370 && DECL_ARTIFICIAL (t
))
371 dump_string_field (di
, "note", "artificial");
372 if (TREE_CHAIN (t
) && !dump_flag (di
, TDF_SLIM
, NULL
))
373 dump_child ("chan", TREE_CHAIN (t
));
375 else if (code_class
== tcc_type
)
377 /* All types have qualifiers. */
378 int quals
= lang_hooks
.tree_dump
.type_quals (t
);
380 if (quals
!= TYPE_UNQUALIFIED
)
382 fprintf (di
->stream
, "qual: %c%c%c ",
383 (quals
& TYPE_QUAL_CONST
) ? 'c' : ' ',
384 (quals
& TYPE_QUAL_VOLATILE
) ? 'v' : ' ',
385 (quals
& TYPE_QUAL_RESTRICT
) ? 'r' : ' ');
389 /* All types have associated declarations. */
390 dump_child ("name", TYPE_NAME (t
));
392 /* All types have a main variant. */
393 if (TYPE_MAIN_VARIANT (t
) != t
)
394 dump_child ("unql", TYPE_MAIN_VARIANT (t
));
397 dump_child ("size", TYPE_SIZE (t
));
399 /* All types have alignments. */
400 dump_int (di
, "algn", TYPE_ALIGN (t
));
402 else if (code_class
== tcc_constant
)
403 /* All constants can have types. */
404 queue_and_dump_type (di
, t
);
406 /* Give the language-specific code a chance to print something. If
407 it's completely taken care of things, don't bother printing
408 anything more ourselves. */
409 if (lang_hooks
.tree_dump
.dump_tree (di
, t
))
412 /* Now handle the various kinds of nodes. */
417 case IDENTIFIER_NODE
:
418 dump_string_field (di
, "strg", IDENTIFIER_POINTER (t
));
419 dump_int (di
, "lngt", IDENTIFIER_LENGTH (t
));
423 dump_child ("purp", TREE_PURPOSE (t
));
424 dump_child ("valu", TREE_VALUE (t
));
425 dump_child ("chan", TREE_CHAIN (t
));
430 tree_stmt_iterator it
;
431 for (i
= 0, it
= tsi_start (t
); !tsi_end_p (it
); tsi_next (&it
), i
++)
434 sprintf (buffer
, "%u", i
);
435 dump_child (buffer
, tsi_stmt (it
));
441 dump_int (di
, "lngt", TREE_VEC_LENGTH (t
));
442 for (i
= 0; i
< TREE_VEC_LENGTH (t
); ++i
)
445 sprintf (buffer
, "%u", i
);
446 dump_child (buffer
, TREE_VEC_ELT (t
, i
));
452 dump_int (di
, "prec", TYPE_PRECISION (t
));
453 dump_string_field (di
, "sign", TYPE_UNSIGNED (t
) ? "unsigned": "signed");
454 dump_child ("min", TYPE_MIN_VALUE (t
));
455 dump_child ("max", TYPE_MAX_VALUE (t
));
457 if (code
== ENUMERAL_TYPE
)
458 dump_child ("csts", TYPE_VALUES (t
));
462 dump_int (di
, "prec", TYPE_PRECISION (t
));
465 case FIXED_POINT_TYPE
:
466 dump_int (di
, "prec", TYPE_PRECISION (t
));
467 dump_string_field (di
, "sign", TYPE_UNSIGNED (t
) ? "unsigned": "signed");
468 dump_string_field (di
, "saturating",
469 TYPE_SATURATING (t
) ? "saturating": "non-saturating");
473 dump_child ("ptd", TREE_TYPE (t
));
477 dump_child ("refd", TREE_TYPE (t
));
481 dump_child ("clas", TYPE_METHOD_BASETYPE (t
));
485 dump_child ("retn", TREE_TYPE (t
));
486 dump_child ("prms", TYPE_ARG_TYPES (t
));
490 dump_child ("elts", TREE_TYPE (t
));
491 dump_child ("domn", TYPE_DOMAIN (t
));
496 if (TREE_CODE (t
) == RECORD_TYPE
)
497 dump_string_field (di
, "tag", "struct");
499 dump_string_field (di
, "tag", "union");
501 dump_child ("flds", TYPE_FIELDS (t
));
502 dump_child ("fncs", TYPE_METHODS (t
));
503 queue_and_dump_index (di
, "binf", TYPE_BINFO (t
),
508 dump_child ("cnst", DECL_INITIAL (t
));
511 case DEBUG_EXPR_DECL
:
512 dump_int (di
, "-uid", DEBUG_TEMP_UID (t
));
519 if (TREE_CODE (t
) == PARM_DECL
)
520 dump_child ("argt", DECL_ARG_TYPE (t
));
522 dump_child ("init", DECL_INITIAL (t
));
523 dump_child ("size", DECL_SIZE (t
));
524 dump_int (di
, "algn", DECL_ALIGN (t
));
526 if (TREE_CODE (t
) == FIELD_DECL
)
528 if (DECL_FIELD_OFFSET (t
))
529 dump_child ("bpos", bit_position (t
));
531 else if (TREE_CODE (t
) == VAR_DECL
532 || TREE_CODE (t
) == PARM_DECL
)
534 dump_int (di
, "used", TREE_USED (t
));
535 if (DECL_REGISTER (t
))
536 dump_string_field (di
, "spec", "register");
541 dump_child ("args", DECL_ARGUMENTS (t
));
542 if (DECL_EXTERNAL (t
))
543 dump_string_field (di
, "body", "undefined");
545 dump_string_field (di
, "link", "extern");
547 dump_string_field (di
, "link", "static");
548 if (DECL_SAVED_TREE (t
) && !dump_flag (di
, TDF_SLIM
, t
))
549 dump_child ("body", DECL_SAVED_TREE (t
));
553 if (TREE_INT_CST_HIGH (t
))
554 dump_int (di
, "high", TREE_INT_CST_HIGH (t
));
555 dump_int (di
, "low", TREE_INT_CST_LOW (t
));
559 fprintf (di
->stream
, "strg: %-7s ", TREE_STRING_POINTER (t
));
560 dump_int (di
, "lngt", TREE_STRING_LENGTH (t
));
564 dump_real (di
, "valu", TREE_REAL_CST_PTR (t
));
568 dump_fixed (di
, "valu", TREE_FIXED_CST_PTR (t
));
574 case MISALIGNED_INDIRECT_REF
:
575 case CLEANUP_POINT_EXPR
:
579 /* These nodes are unary, but do not have code class `1'. */
580 dump_child ("op 0", TREE_OPERAND (t
, 0));
583 case TRUTH_ANDIF_EXPR
:
584 case TRUTH_ORIF_EXPR
:
588 case PREDECREMENT_EXPR
:
589 case PREINCREMENT_EXPR
:
590 case POSTDECREMENT_EXPR
:
591 case POSTINCREMENT_EXPR
:
592 /* These nodes are binary, but do not have code class `2'. */
593 dump_child ("op 0", TREE_OPERAND (t
, 0));
594 dump_child ("op 1", TREE_OPERAND (t
, 1));
598 dump_child ("op 0", TREE_OPERAND (t
, 0));
599 dump_child ("op 1", TREE_OPERAND (t
, 1));
600 dump_child ("op 2", TREE_OPERAND (t
, 2));
604 case ARRAY_RANGE_REF
:
605 dump_child ("op 0", TREE_OPERAND (t
, 0));
606 dump_child ("op 1", TREE_OPERAND (t
, 1));
607 dump_child ("op 2", TREE_OPERAND (t
, 2));
608 dump_child ("op 3", TREE_OPERAND (t
, 3));
612 dump_child ("op 0", TREE_OPERAND (t
, 0));
613 dump_child ("op 1", TREE_OPERAND (t
, 1));
614 dump_child ("op 2", TREE_OPERAND (t
, 2));
617 case TRY_FINALLY_EXPR
:
618 dump_child ("op 0", TREE_OPERAND (t
, 0));
619 dump_child ("op 1", TREE_OPERAND (t
, 1));
626 call_expr_arg_iterator iter
;
627 dump_child ("fn", CALL_EXPR_FN (t
));
628 FOR_EACH_CALL_EXPR_ARG (arg
, iter
, t
)
631 sprintf (buffer
, "%u", i
);
632 dump_child (buffer
, arg
);
640 unsigned HOST_WIDE_INT cnt
;
642 dump_int (di
, "lngt", VEC_length (constructor_elt
,
643 CONSTRUCTOR_ELTS (t
)));
644 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t
), cnt
, index
, value
)
646 dump_child ("idx", index
);
647 dump_child ("val", value
);
653 dump_child ("vars", TREE_OPERAND (t
, 0));
654 dump_child ("body", TREE_OPERAND (t
, 1));
658 dump_child ("body", TREE_OPERAND (t
, 0));
662 dump_child ("cond", TREE_OPERAND (t
, 0));
666 dump_child ("expr", TREE_OPERAND (t
, 0));
670 dump_child ("decl", TREE_OPERAND (t
, 0));
671 dump_child ("init", TREE_OPERAND (t
, 1));
672 dump_child ("clnp", TREE_OPERAND (t
, 2));
673 /* There really are two possible places the initializer can be.
674 After RTL expansion, the second operand is moved to the
675 position of the fourth operand, and the second operand
677 dump_child ("init", TREE_OPERAND (t
, 3));
680 case CASE_LABEL_EXPR
:
681 dump_child ("name", CASE_LABEL (t
));
684 dump_child ("low ", CASE_LOW (t
));
686 dump_child ("high", CASE_HIGH (t
));
690 dump_child ("name", TREE_OPERAND (t
,0));
693 dump_child ("labl", TREE_OPERAND (t
, 0));
696 dump_child ("cond", TREE_OPERAND (t
, 0));
697 dump_child ("body", TREE_OPERAND (t
, 1));
698 if (TREE_OPERAND (t
, 2))
700 dump_child ("labl", TREE_OPERAND (t
,2));
706 fprintf (di
->stream
, "%s\n", omp_clause_code_name
[OMP_CLAUSE_CODE (t
)]);
707 for (i
= 0; i
< omp_clause_num_ops
[OMP_CLAUSE_CODE (t
)]; i
++)
708 dump_child ("op: ", OMP_CLAUSE_OPERAND (t
, i
));
712 /* There are no additional fields to print. */
717 if (dump_flag (di
, TDF_ADDRESS
, NULL
))
718 dump_pointer (di
, "addr", (void *)t
);
720 /* Terminate the line. */
721 fprintf (di
->stream
, "\n");
724 /* Return nonzero if FLAG has been specified for the dump, and NODE
725 is not the root node of the dump. */
727 int dump_flag (dump_info_p di
, int flag
, const_tree node
)
729 return (di
->flags
& flag
) && (node
!= di
->node
);
732 /* Dump T, and all its children, on STREAM. */
735 dump_node (const_tree t
, int flags
, FILE *stream
)
739 dump_queue_p next_dq
;
741 /* Initialize the dump-information structure. */
750 di
.nodes
= splay_tree_new (splay_tree_compare_pointers
, 0,
751 (splay_tree_delete_value_fn
) &free
);
753 /* Queue up the first node. */
754 queue (&di
, t
, DUMP_NONE
);
756 /* Until the queue is empty, keep dumping nodes. */
758 dequeue_and_dump (&di
);
761 for (dq
= di
.free_list
; dq
; dq
= next_dq
)
766 splay_tree_delete (di
.nodes
);
770 /* Table of tree dump switches. This must be consistent with the
771 tree_dump_index enumeration in tree-pass.h. */
772 static struct dump_file_info dump_files
[TDI_end
] =
774 {NULL
, NULL
, NULL
, 0, 0, 0},
775 {".cgraph", "ipa-cgraph", NULL
, TDF_IPA
, 0, 0},
776 {".tu", "translation-unit", NULL
, TDF_TREE
, 0, 1},
777 {".class", "class-hierarchy", NULL
, TDF_TREE
, 0, 2},
778 {".original", "tree-original", NULL
, TDF_TREE
, 0, 3},
779 {".gimple", "tree-gimple", NULL
, TDF_TREE
, 0, 4},
780 {".nested", "tree-nested", NULL
, TDF_TREE
, 0, 5},
781 {".vcg", "tree-vcg", NULL
, TDF_TREE
, 0, 6},
782 {".ads", "ada-spec", NULL
, 0, 0, 7},
783 #define FIRST_AUTO_NUMBERED_DUMP 8
785 {NULL
, "tree-all", NULL
, TDF_TREE
, 0, 0},
786 {NULL
, "rtl-all", NULL
, TDF_RTL
, 0, 0},
787 {NULL
, "ipa-all", NULL
, TDF_IPA
, 0, 0},
790 /* Dynamically registered tree dump files and switches. */
791 static struct dump_file_info
*extra_dump_files
;
792 static size_t extra_dump_files_in_use
;
793 static size_t extra_dump_files_alloced
;
795 /* Define a name->number mapping for a dump flag value. */
796 struct dump_option_value_info
798 const char *const name
; /* the name of the value */
799 const int value
; /* the value of the name */
802 /* Table of dump options. This must be consistent with the TDF_* flags
804 static const struct dump_option_value_info dump_options
[] =
806 {"address", TDF_ADDRESS
},
807 {"asmname", TDF_ASMNAME
},
810 {"graph", TDF_GRAPH
},
811 {"details", TDF_DETAILS
},
812 {"stats", TDF_STATS
},
813 {"blocks", TDF_BLOCKS
},
815 {"lineno", TDF_LINENO
},
817 {"stmtaddr", TDF_STMTADDR
},
818 {"memsyms", TDF_MEMSYMS
},
819 {"verbose", TDF_VERBOSE
},
821 {"alias", TDF_ALIAS
},
822 {"nouid", TDF_NOUID
},
823 {"all", ~(TDF_RAW
| TDF_SLIM
| TDF_LINENO
| TDF_TREE
| TDF_RTL
| TDF_IPA
824 | TDF_STMTADDR
| TDF_GRAPH
| TDF_DIAGNOSTIC
| TDF_VERBOSE
825 | TDF_RHS_ONLY
| TDF_NOUID
)},
830 dump_register (const char *suffix
, const char *swtch
, const char *glob
,
833 static int next_dump
= FIRST_AUTO_NUMBERED_DUMP
;
834 int num
= next_dump
++;
836 size_t count
= extra_dump_files_in_use
++;
838 if (count
>= extra_dump_files_alloced
)
840 if (extra_dump_files_alloced
== 0)
841 extra_dump_files_alloced
= 32;
843 extra_dump_files_alloced
*= 2;
844 extra_dump_files
= XRESIZEVEC (struct dump_file_info
,
846 extra_dump_files_alloced
);
849 memset (&extra_dump_files
[count
], 0, sizeof (struct dump_file_info
));
850 extra_dump_files
[count
].suffix
= suffix
;
851 extra_dump_files
[count
].swtch
= swtch
;
852 extra_dump_files
[count
].glob
= glob
;
853 extra_dump_files
[count
].flags
= flags
;
854 extra_dump_files
[count
].num
= num
;
856 return count
+ TDI_end
;
860 /* Return the dump_file_info for the given phase. */
862 struct dump_file_info
*
863 get_dump_file_info (int phase
)
866 return &dump_files
[phase
];
867 else if ((size_t) (phase
- TDI_end
) >= extra_dump_files_in_use
)
870 return extra_dump_files
+ (phase
- TDI_end
);
874 /* Return the name of the dump file for the given phase.
875 If the dump is not enabled, returns NULL. */
878 get_dump_file_name (int phase
)
881 struct dump_file_info
*dfi
;
883 if (phase
== TDI_none
)
886 dfi
= get_dump_file_info (phase
);
895 if (dfi
->flags
& TDF_TREE
)
897 else if (dfi
->flags
& TDF_IPA
)
902 if (snprintf (dump_id
, sizeof (dump_id
), ".%03d%c", dfi
->num
, suffix
) < 0)
906 return concat (dump_base_name
, dump_id
, dfi
->suffix
, NULL
);
909 /* Begin a tree dump for PHASE. Stores any user supplied flag in
910 *FLAG_PTR and returns a stream to write to. If the dump is not
911 enabled, returns NULL.
912 Multiple calls will reopen and append to the dump file. */
915 dump_begin (int phase
, int *flag_ptr
)
918 struct dump_file_info
*dfi
;
921 if (phase
== TDI_none
|| !dump_enabled_p (phase
))
924 name
= get_dump_file_name (phase
);
925 dfi
= get_dump_file_info (phase
);
926 stream
= fopen (name
, dfi
->state
< 0 ? "w" : "a");
928 error ("could not open dump file %qs: %m", name
);
934 *flag_ptr
= dfi
->flags
;
939 /* Returns nonzero if tree dump PHASE is enabled. If PHASE is
940 TDI_tree_all, return nonzero if any dump is enabled. */
943 dump_enabled_p (int phase
)
945 if (phase
== TDI_tree_all
)
948 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
949 if (dump_files
[i
].state
)
951 for (i
= 0; i
< extra_dump_files_in_use
; i
++)
952 if (extra_dump_files
[i
].state
)
958 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
963 /* Returns nonzero if tree dump PHASE has been initialized. */
966 dump_initialized_p (int phase
)
968 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
969 return dfi
->state
> 0;
972 /* Returns the switch name of PHASE. */
975 dump_flag_name (int phase
)
977 struct dump_file_info
*dfi
= get_dump_file_info (phase
);
981 /* Finish a tree dump for PHASE. STREAM is the stream created by
985 dump_end (int phase ATTRIBUTE_UNUSED
, FILE *stream
)
990 /* Enable all tree dumps. Return number of enabled tree dumps. */
993 dump_enable_all (int flags
)
995 int ir_dump_type
= (flags
& (TDF_TREE
| TDF_RTL
| TDF_IPA
));
999 for (i
= TDI_none
+ 1; i
< (size_t) TDI_end
; i
++)
1000 if ((dump_files
[i
].flags
& ir_dump_type
))
1002 dump_files
[i
].state
= -1;
1003 dump_files
[i
].flags
|= flags
;
1007 for (i
= 0; i
< extra_dump_files_in_use
; i
++)
1008 if ((extra_dump_files
[i
].flags
& ir_dump_type
))
1010 extra_dump_files
[i
].state
= -1;
1011 extra_dump_files
[i
].flags
|= flags
;
1018 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1019 relevant details in the dump_files array. */
1022 dump_switch_p_1 (const char *arg
, struct dump_file_info
*dfi
, bool doglob
)
1024 const char *option_value
;
1028 if (doglob
&& !dfi
->glob
)
1031 option_value
= skip_leading_substring (arg
, doglob
? dfi
->glob
: dfi
->swtch
);
1035 if (*option_value
&& *option_value
!= '-')
1043 const struct dump_option_value_info
*option_ptr
;
1044 const char *end_ptr
;
1049 end_ptr
= strchr (ptr
, '-');
1051 end_ptr
= ptr
+ strlen (ptr
);
1052 length
= end_ptr
- ptr
;
1054 for (option_ptr
= dump_options
; option_ptr
->name
; option_ptr
++)
1055 if (strlen (option_ptr
->name
) == length
1056 && !memcmp (option_ptr
->name
, ptr
, length
))
1058 flags
|= option_ptr
->value
;
1061 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1062 length
, ptr
, dfi
->swtch
);
1068 dfi
->flags
|= flags
;
1070 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1072 if (dfi
->suffix
== NULL
)
1073 dump_enable_all (dfi
->flags
);
1079 dump_switch_p (const char *arg
)
1084 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1085 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], false);
1087 /* Don't glob if we got a hit already */
1089 for (i
= TDI_none
+ 1; i
!= TDI_end
; i
++)
1090 any
|= dump_switch_p_1 (arg
, &dump_files
[i
], true);
1092 for (i
= 0; i
< extra_dump_files_in_use
; i
++)
1093 any
|= dump_switch_p_1 (arg
, &extra_dump_files
[i
], false);
1096 for (i
= 0; i
< extra_dump_files_in_use
; i
++)
1097 any
|= dump_switch_p_1 (arg
, &extra_dump_files
[i
], true);
1103 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1106 dump_function (int phase
, tree fn
)
1111 stream
= dump_begin (phase
, &flags
);
1114 dump_function_to_file (fn
, stream
, flags
);
1115 dump_end (phase
, stream
);
1120 enable_rtl_dump_file (void)
1122 return dump_enable_all (TDF_RTL
| TDF_DETAILS
| TDF_BLOCKS
) > 0;