1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
3 Written by Mark Mitchell <mark@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 #include "splay-tree.h"
27 #include "diagnostic.h"
29 #include "tree-dump.h"
30 #include "langhooks.h"
32 static unsigned int queue
PARAMS ((dump_info_p
, tree
, int));
33 static void dump_index
PARAMS ((dump_info_p
, unsigned int));
34 static void dequeue_and_dump
PARAMS ((dump_info_p
));
35 static void dump_new_line
PARAMS ((dump_info_p
));
36 static void dump_maybe_newline
PARAMS ((dump_info_p
));
37 static void dump_string_field
PARAMS ((dump_info_p
, const char *, const char *));
39 /* Add T to the end of the queue of nodes to dump. Returns the index
52 /* Assign the next available index to T. */
55 /* Obtain a new queue node. */
59 di
->free_list
= dq
->next
;
62 dq
= (dump_queue_p
) xmalloc (sizeof (struct dump_queue
));
64 /* Create a new entry in the splay-tree. */
65 dni
= (dump_node_info_p
) xmalloc (sizeof (struct dump_node_info
));
67 dni
->binfo_p
= ((flags
& DUMP_BINFO
) != 0);
68 dq
->node
= splay_tree_insert (di
->nodes
, (splay_tree_key
) t
,
69 (splay_tree_value
) dni
);
71 /* Add it to the end of the queue. */
76 di
->queue_end
->next
= dq
;
79 /* Return the index. */
84 dump_index (di
, index
)
88 fprintf (di
->stream
, "@%-6u ", index
);
92 /* If T has not already been output, queue it for subsequent output.
93 FIELD is a string to print before printing the index. Then, the
94 index of T is printed. */
97 queue_and_dump_index (di
, field
, t
, flags
)
106 /* If there's no node, just return. This makes for fewer checks in
111 /* See if we've already queued or dumped this node. */
112 n
= splay_tree_lookup (di
->nodes
, (splay_tree_key
) t
);
114 index
= ((dump_node_info_p
) n
->value
)->index
;
116 /* If we haven't, add it to the queue. */
117 index
= queue (di
, t
, flags
);
119 /* Print the index of the node. */
120 dump_maybe_newline (di
);
121 fprintf (di
->stream
, "%-4s: ", field
);
123 dump_index (di
, index
);
126 /* Dump the type of T. */
129 queue_and_dump_type (di
, t
)
133 queue_and_dump_index (di
, "type", TREE_TYPE (t
), DUMP_NONE
);
136 /* Dump column control */
137 #define SOL_COLUMN 25 /* Start of line column. */
138 #define EOL_COLUMN 55 /* End of line column. */
139 #define COLUMN_ALIGNMENT 15 /* Alignment. */
141 /* Insert a new line in the dump output, and indent to an appropriate
142 place to start printing more fields. */
148 fprintf (di
->stream
, "\n%*s", SOL_COLUMN
, "");
149 di
->column
= SOL_COLUMN
;
152 /* If necessary, insert a new line. */
155 dump_maybe_newline (di
)
160 /* See if we need a new line. */
161 if (di
->column
> EOL_COLUMN
)
163 /* See if we need any padding. */
164 else if ((extra
= (di
->column
- SOL_COLUMN
) % COLUMN_ALIGNMENT
) != 0)
166 fprintf (di
->stream
, "%*s", COLUMN_ALIGNMENT
- extra
, "");
167 di
->column
+= COLUMN_ALIGNMENT
- extra
;
171 /* Dump pointer PTR using FIELD to identify it. */
174 dump_pointer (di
, field
, ptr
)
179 dump_maybe_newline (di
);
180 fprintf (di
->stream
, "%-4s: %-8lx ", field
, (long) ptr
);
184 /* Dump integer I using FIELD to identify it. */
187 dump_int (di
, field
, i
)
192 dump_maybe_newline (di
);
193 fprintf (di
->stream
, "%-4s: %-7d ", field
, i
);
197 /* Dump the string S. */
200 dump_string (di
, string
)
204 dump_maybe_newline (di
);
205 fprintf (di
->stream
, "%-13s ", string
);
206 if (strlen (string
) > 13)
207 di
->column
+= strlen (string
) + 1;
212 /* Dump the string field S. */
215 dump_string_field (di
, field
, string
)
220 dump_maybe_newline (di
);
221 fprintf (di
->stream
, "%-4s: %-7s ", field
, string
);
222 if (strlen (string
) > 7)
223 di
->column
+= 6 + strlen (string
) + 1;
228 /* Dump information common to statements from STMT. */
235 dump_int (di
, "line", STMT_LINENO (t
));
238 /* Dump the next statement after STMT. */
241 dump_next_stmt (di
, t
)
245 dump_child ("next", TREE_CHAIN (t
));
248 /* Dump the next node in the queue. */
251 dequeue_and_dump (di
)
256 dump_node_info_p dni
;
261 const char* code_name
;
263 /* Get the next node from the queue. */
267 dni
= (dump_node_info_p
) stn
->value
;
270 /* Remove the node from the queue, and put it on the free list. */
271 di
->queue
= dq
->next
;
274 dq
->next
= di
->free_list
;
277 /* Print the node index. */
278 dump_index (di
, index
);
279 /* And the type of node this is. */
283 code_name
= tree_code_name
[(int) TREE_CODE (t
)];
284 fprintf (di
->stream
, "%-16s ", code_name
);
287 /* Figure out what kind of node this is. */
288 code
= TREE_CODE (t
);
289 code_class
= TREE_CODE_CLASS (code
);
291 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
295 if (TREE_VIA_PUBLIC (t
))
296 dump_string (di
, "pub");
297 else if (TREE_VIA_PROTECTED (t
))
298 dump_string (di
, "prot");
299 else if (TREE_VIA_PRIVATE (t
))
300 dump_string (di
, "priv");
301 if (TREE_VIA_VIRTUAL (t
))
302 dump_string (di
, "virt");
304 dump_child ("type", BINFO_TYPE (t
));
305 dump_child ("base", BINFO_BASETYPES (t
));
310 /* We can knock off a bunch of expression nodes in exactly the same
312 if (IS_EXPR_CODE_CLASS (code_class
))
314 /* If we're dumping children, dump them now. */
315 queue_and_dump_type (di
, t
);
320 dump_child ("op 0", TREE_OPERAND (t
, 0));
325 dump_child ("op 0", TREE_OPERAND (t
, 0));
326 dump_child ("op 1", TREE_OPERAND (t
, 1));
330 /* These nodes are handled explicitly below. */
339 /* All declarations have names. */
341 dump_child ("name", DECL_NAME (t
));
342 if (DECL_ASSEMBLER_NAME_SET_P (t
)
343 && DECL_ASSEMBLER_NAME (t
) != DECL_NAME (t
))
344 dump_child ("mngl", DECL_ASSEMBLER_NAME (t
));
346 queue_and_dump_type (di
, t
);
347 dump_child ("scpe", DECL_CONTEXT (t
));
348 /* And a source position. */
349 if (DECL_SOURCE_FILE (t
))
351 const char *filename
= strrchr (DECL_SOURCE_FILE (t
), '/');
353 filename
= DECL_SOURCE_FILE (t
);
355 /* Skip the slash. */
358 dump_maybe_newline (di
);
359 fprintf (di
->stream
, "srcp: %s:%-6d ", filename
,
360 DECL_SOURCE_LINE (t
));
361 di
->column
+= 6 + strlen (filename
) + 8;
363 /* And any declaration can be compiler-generated. */
364 if (DECL_ARTIFICIAL (t
))
365 dump_string (di
, "artificial");
366 if (TREE_CHAIN (t
) && !dump_flag (di
, TDF_SLIM
, NULL
))
367 dump_child ("chan", TREE_CHAIN (t
));
369 else if (code_class
== 't')
371 /* All types have qualifiers. */
372 int quals
= (*lang_hooks
.tree_dump
.type_quals
) (t
);
374 if (quals
!= TYPE_UNQUALIFIED
)
376 fprintf (di
->stream
, "qual: %c%c%c ",
377 (quals
& TYPE_QUAL_CONST
) ? 'c' : ' ',
378 (quals
& TYPE_QUAL_VOLATILE
) ? 'v' : ' ',
379 (quals
& TYPE_QUAL_RESTRICT
) ? 'r' : ' ');
383 /* All types have associated declarations. */
384 dump_child ("name", TYPE_NAME (t
));
386 /* All types have a main variant. */
387 if (TYPE_MAIN_VARIANT (t
) != t
)
388 dump_child ("unql", TYPE_MAIN_VARIANT (t
));
391 dump_child ("size", TYPE_SIZE (t
));
393 /* All types have alignments. */
394 dump_int (di
, "algn", TYPE_ALIGN (t
));
396 else if (code_class
== 'c')
397 /* All constants can have types. */
398 queue_and_dump_type (di
, t
);
400 /* Give the language-specific code a chance to print something. If
401 it's completely taken care of things, don't bother printing
402 anything more ourselves. */
403 if ((*lang_hooks
.tree_dump
.dump_tree
) (di
, t
))
406 /* Now handle the various kinds of nodes. */
411 case IDENTIFIER_NODE
:
412 dump_string_field (di
, "strg", IDENTIFIER_POINTER (t
));
413 dump_int (di
, "lngt", IDENTIFIER_LENGTH (t
));
417 dump_child ("purp", TREE_PURPOSE (t
));
418 dump_child ("valu", TREE_VALUE (t
));
419 dump_child ("chan", TREE_CHAIN (t
));
423 dump_int (di
, "lngt", TREE_VEC_LENGTH (t
));
424 for (i
= 0; i
< TREE_VEC_LENGTH (t
); ++i
)
427 sprintf (buffer
, "%u", i
);
428 dump_child (buffer
, TREE_VEC_ELT (t
, i
));
434 dump_int (di
, "prec", TYPE_PRECISION (t
));
435 if (TREE_UNSIGNED (t
))
436 dump_string (di
, "unsigned");
437 dump_child ("min", TYPE_MIN_VALUE (t
));
438 dump_child ("max", TYPE_MAX_VALUE (t
));
440 if (code
== ENUMERAL_TYPE
)
441 dump_child ("csts", TYPE_VALUES (t
));
445 dump_int (di
, "prec", TYPE_PRECISION (t
));
449 dump_child ("ptd", TREE_TYPE (t
));
453 dump_child ("refd", TREE_TYPE (t
));
457 dump_child ("clas", TYPE_METHOD_BASETYPE (t
));
461 dump_child ("retn", TREE_TYPE (t
));
462 dump_child ("prms", TYPE_ARG_TYPES (t
));
466 dump_child ("elts", TREE_TYPE (t
));
467 dump_child ("domn", TYPE_DOMAIN (t
));
472 if (TREE_CODE (t
) == RECORD_TYPE
)
473 dump_string (di
, "struct");
475 dump_string (di
, "union");
477 dump_child ("flds", TYPE_FIELDS (t
));
478 dump_child ("fncs", TYPE_METHODS (t
));
479 queue_and_dump_index (di
, "binf", TYPE_BINFO (t
),
484 dump_child ("cnst", DECL_INITIAL (t
));
491 if (TREE_CODE (t
) == PARM_DECL
)
492 dump_child ("argt", DECL_ARG_TYPE (t
));
494 dump_child ("init", DECL_INITIAL (t
));
495 dump_child ("size", DECL_SIZE (t
));
496 dump_int (di
, "algn", DECL_ALIGN (t
));
498 if (TREE_CODE (t
) == FIELD_DECL
)
500 if (DECL_C_BIT_FIELD (t
))
501 dump_string (di
, "bitfield");
502 if (DECL_FIELD_OFFSET (t
))
503 dump_child ("bpos", bit_position (t
));
505 else if (TREE_CODE (t
) == VAR_DECL
506 || TREE_CODE (t
) == PARM_DECL
)
508 dump_int (di
, "used", TREE_USED (t
));
509 if (DECL_REGISTER (t
))
510 dump_string (di
, "register");
515 dump_child ("args", DECL_ARGUMENTS (t
));
516 if (DECL_EXTERNAL (t
))
517 dump_string (di
, "undefined");
519 dump_string (di
, "extern");
521 dump_string (di
, "static");
522 if (DECL_LANG_SPECIFIC (t
) && !dump_flag (di
, TDF_SLIM
, t
))
523 dump_child ("body", DECL_SAVED_TREE (t
));
528 if (ASM_VOLATILE_P (t
))
529 dump_string (di
, "volatile");
530 dump_child ("strg", ASM_STRING (t
));
531 dump_child ("outs", ASM_OUTPUTS (t
));
532 dump_child ("ins", ASM_INPUTS (t
));
533 dump_child ("clbr", ASM_CLOBBERS (t
));
534 dump_next_stmt (di
, t
);
540 dump_next_stmt (di
, t
);
544 /* Note that a case label is not like other statements; there is
545 no way to get the line-number of a case label. */
546 dump_child ("low", CASE_LOW (t
));
547 dump_child ("high", CASE_HIGH (t
));
548 dump_next_stmt (di
, t
);
553 dump_child ("decl", CLEANUP_DECL (t
));
554 dump_child ("expr", CLEANUP_EXPR (t
));
555 dump_next_stmt (di
, t
);
560 dump_child ("body", COMPOUND_BODY (t
));
561 dump_next_stmt (di
, t
);
566 dump_child ("decl", DECL_STMT_DECL (t
));
567 dump_next_stmt (di
, t
);
572 dump_child ("body", DO_BODY (t
));
573 dump_child ("cond", DO_COND (t
));
574 dump_next_stmt (di
, t
);
579 dump_child ("expr", EXPR_STMT_EXPR (t
));
580 dump_next_stmt (di
, t
);
585 dump_child ("init", FOR_INIT_STMT (t
));
586 dump_child ("cond", FOR_COND (t
));
587 dump_child ("expr", FOR_EXPR (t
));
588 dump_child ("body", FOR_BODY (t
));
589 dump_next_stmt (di
, t
);
594 dump_child ("dest", GOTO_DESTINATION (t
));
595 dump_next_stmt (di
, t
);
600 dump_child ("cond", IF_COND (t
));
601 dump_child ("then", THEN_CLAUSE (t
));
602 dump_child ("else", ELSE_CLAUSE (t
));
603 dump_next_stmt (di
, t
);
608 dump_child ("labl", LABEL_STMT_LABEL (t
));
609 dump_next_stmt (di
, t
);
614 dump_child ("expr", RETURN_EXPR (t
));
615 dump_next_stmt (di
, t
);
620 dump_child ("cond", SWITCH_COND (t
));
621 dump_child ("body", SWITCH_BODY (t
));
622 dump_next_stmt (di
, t
);
627 dump_child ("cond", WHILE_COND (t
));
628 dump_child ("body", WHILE_BODY (t
));
629 dump_next_stmt (di
, t
);
634 if (SCOPE_BEGIN_P (t
))
635 dump_string (di
, "begn");
637 dump_string (di
, "end");
638 if (SCOPE_NULLIFIED_P (t
))
639 dump_string (di
, "null");
640 if (!SCOPE_NO_CLEANUPS_P (t
))
641 dump_string (di
, "clnp");
642 dump_next_stmt (di
, t
);
646 if (TREE_INT_CST_HIGH (t
))
647 dump_int (di
, "high", TREE_INT_CST_HIGH (t
));
648 dump_int (di
, "low", TREE_INT_CST_LOW (t
));
652 fprintf (di
->stream
, "strg: %-7s ", TREE_STRING_POINTER (t
));
653 dump_int (di
, "lngt", TREE_STRING_LENGTH (t
));
659 case CLEANUP_POINT_EXPR
:
661 /* These nodes are unary, but do not have code class `1'. */
662 dump_child ("op 0", TREE_OPERAND (t
, 0));
665 case TRUTH_ANDIF_EXPR
:
666 case TRUTH_ORIF_EXPR
:
672 case PREDECREMENT_EXPR
:
673 case PREINCREMENT_EXPR
:
674 case POSTDECREMENT_EXPR
:
675 case POSTINCREMENT_EXPR
:
676 /* These nodes are binary, but do not have code class `2'. */
677 dump_child ("op 0", TREE_OPERAND (t
, 0));
678 dump_child ("op 1", TREE_OPERAND (t
, 1));
682 dump_child ("op 0", TREE_OPERAND (t
, 0));
683 dump_child ("op 1", TREE_OPERAND (t
, 1));
684 dump_child ("op 2", TREE_OPERAND (t
, 2));
688 dump_child ("fn", TREE_OPERAND (t
, 0));
689 dump_child ("args", TREE_OPERAND (t
, 1));
693 dump_child ("elts", TREE_OPERAND (t
, 1));
697 dump_child ("stmt", STMT_EXPR_STMT (t
));
701 dump_child ("vars", TREE_OPERAND (t
, 0));
702 dump_child ("body", TREE_OPERAND (t
, 1));
706 dump_child ("body", TREE_OPERAND (t
, 0));
710 dump_child ("cond", TREE_OPERAND (t
, 0));
714 dump_child ("decl", TREE_OPERAND (t
, 0));
715 dump_child ("init", TREE_OPERAND (t
, 1));
716 dump_child ("clnp", TREE_OPERAND (t
, 2));
717 /* There really are two possible places the initializer can be.
718 After RTL expansion, the second operand is moved to the
719 position of the fourth operand, and the second operand
721 dump_child ("init", TREE_OPERAND (t
, 3));
724 case EXPR_WITH_FILE_LOCATION
:
725 dump_child ("expr", EXPR_WFL_NODE (t
));
729 /* There are no additional fields to print. */
734 if (dump_flag (di
, TDF_ADDRESS
, NULL
))
735 dump_pointer (di
, "addr", (void *)t
);
737 /* Terminate the line. */
738 fprintf (di
->stream
, "\n");
741 /* Return non-zero if FLAG has been specified for the dump, and NODE
742 is not the root node of the dump. */
744 int dump_flag (di
, flag
, node
)
749 return (di
->flags
& flag
) && (node
!= di
->node
);
752 /* Dump T, and all its children, on STREAM. */
755 dump_node (t
, flags
, stream
)
762 dump_queue_p next_dq
;
764 /* Initialize the dump-information structure. */
773 di
.nodes
= splay_tree_new (splay_tree_compare_pointers
, 0,
774 (splay_tree_delete_value_fn
) &free
);
776 /* Queue up the first node. */
777 queue (&di
, t
, DUMP_NONE
);
779 /* Until the queue is empty, keep dumping nodes. */
781 dequeue_and_dump (&di
);
784 for (dq
= di
.free_list
; dq
; dq
= next_dq
)
789 splay_tree_delete (di
.nodes
);
792 /* Define a tree dump switch. */
793 struct dump_file_info
795 const char *const suffix
; /* suffix to give output file. */
796 const char *const swtch
; /* command line switch */
797 int flags
; /* user flags */
798 int state
; /* state of play */
801 /* Table of tree dump switches. This must be consistent with the
802 TREE_DUMP_INDEX enumeration in tree.h */
803 static struct dump_file_info dump_files
[TDI_end
] =
805 {".tu", "dump-translation-unit", 0, 0},
806 {".class", "dump-class-hierarchy", 0, 0},
807 {".original", "dump-tree-original", 0, 0},
808 {".optimized", "dump-tree-optimized", 0, 0},
809 {".inlined", "dump-tree-inlined", 0, 0},
812 /* Define a name->number mapping for a dump flag value. */
813 struct dump_option_value_info
815 const char *const name
; /* the name of the value */
816 const int value
; /* the value of the name */
819 /* Table of dump options. This must be consistent with the TDF_* flags
821 static const struct dump_option_value_info dump_options
[] =
823 {"address", TDF_ADDRESS
},
829 /* Begin a tree dump for PHASE. Stores any user supplied flag in
830 *FLAG_PTR and returns a stream to write to. If the dump is not
831 enabled, returns NULL.
832 Multiple calls will reopen and append to the dump file. */
835 dump_begin (phase
, flag_ptr
)
836 enum tree_dump_index phase
;
842 if (!dump_files
[phase
].state
)
845 name
= concat (dump_base_name
, dump_files
[phase
].suffix
, NULL
);
846 stream
= fopen (name
, dump_files
[phase
].state
< 0 ? "w" : "a");
848 error ("could not open dump file `%s'", name
);
850 dump_files
[phase
].state
= 1;
853 *flag_ptr
= dump_files
[phase
].flags
;
858 /* Returns non-zero if tree dump PHASE is enabled. */
861 dump_enabled_p (phase
)
862 enum tree_dump_index phase
;
864 return dump_files
[phase
].state
;
867 /* Returns the switch name of PHASE. */
870 dump_flag_name (phase
)
871 enum tree_dump_index phase
;
873 return dump_files
[phase
].swtch
;
876 /* Finish a tree dump for PHASE. STREAM is the stream created by
880 dump_end (phase
, stream
)
881 enum tree_dump_index phase ATTRIBUTE_UNUSED
;
887 /* Parse ARG as a dump switch. Return non-zero if it is, and store the
888 relevant details in the dump_files array. */
895 const char *option_value
;
897 for (ix
= 0; ix
!= TDI_end
; ix
++)
898 if ((option_value
= skip_leading_substring (arg
, dump_files
[ix
].swtch
)))
900 const char *ptr
= option_value
;
905 const struct dump_option_value_info
*option_ptr
;
911 end_ptr
= strchr (ptr
, '-');
913 end_ptr
= ptr
+ strlen (ptr
);
914 length
= end_ptr
- ptr
;
916 for (option_ptr
= dump_options
; option_ptr
->name
;
918 if (strlen (option_ptr
->name
) == length
919 && !memcmp (option_ptr
->name
, ptr
, length
))
921 flags
|= option_ptr
->value
;
924 warning ("ignoring unknown option `%.*s' in `-f%s'",
925 length
, ptr
, dump_files
[ix
].swtch
);
930 dump_files
[ix
].state
= -1;
931 dump_files
[ix
].flags
= flags
;