1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999 Free Software Foundation, Inc.
3 Written by Mark Mitchell <mark@codesourcery.com>
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "splay-tree.h"
28 /* Flags used with queue functions. */
30 #define DUMP_CHILDREN 1
33 /* Information about a node to be dumped. */
35 typedef struct dump_node_info
37 /* The index for the node. */
39 /* Nonzero if we should dump the children of the node. */
40 unsigned int dump_children_p
: 1;
41 /* Nonzero if the node is a binfo. */
42 unsigned int binfo_p
: 1;
45 /* A dump_queue is a link in the queue of things to be dumped. */
47 typedef struct dump_queue
49 /* The queued tree node. */
51 /* The next node in the queue. */
52 struct dump_queue
*next
;
55 /* A dump_info gives information about how we should perform the dump
56 and about the current state of the dump. */
58 typedef struct dump_info
60 /* The stream on which to dump the information. */
62 /* The next unused node index. */
64 /* The next column. */
66 /* The first node in the queue of nodes to be written out. */
68 /* The last node in the queue. */
69 dump_queue_p queue_end
;
70 /* Free queue nodes. */
71 dump_queue_p free_list
;
72 /* The tree nodes which we have already written out. The
73 keys are the addresses of the nodes; the values are the integer
74 indices we assigned them. */
78 static unsigned int queue
PROTO ((dump_info_p
, tree
, int));
79 static void dump_index
PROTO ((dump_info_p
, unsigned int));
80 static void queue_and_dump_index
PROTO ((dump_info_p
, const char *, tree
, int));
81 static void queue_and_dump_type
PROTO ((dump_info_p
, tree
, int));
82 static void dequeue_and_dump
PROTO ((dump_info_p
));
83 static void dump_new_line
PROTO ((dump_info_p
));
84 static void dump_maybe_newline
PROTO ((dump_info_p
));
85 static void dump_int
PROTO ((dump_info_p
, const char *, int));
86 static void dump_string
PROTO ((dump_info_p
, const char *));
87 static void dump_string_field
PROTO ((dump_info_p
, const char *, const char *));
88 static void dump_node
PROTO ((tree
, FILE *));
89 static void dump_stmt
PROTO ((dump_info_p
, tree
));
90 static void dump_next_stmt
PROTO ((dump_info_p
, tree
));
92 /* Add T to the end of the queue of nodes to dump. If DUMP_CHILDREN_P
93 is non-zero, then its children should be dumped as well. Returns
94 the index assigned to T. */
103 dump_node_info_p dni
;
106 /* Assign the next available index to T. */
109 /* Obtain a new queue node. */
113 di
->free_list
= dq
->next
;
116 dq
= (dump_queue_p
) xmalloc (sizeof (struct dump_queue
));
118 /* Create a new entry in the splay-tree. */
119 dni
= (dump_node_info_p
) xmalloc (sizeof (struct dump_node_info
));
121 dni
->dump_children_p
= ((flags
& DUMP_CHILDREN
) != 0);
122 dni
->binfo_p
= ((flags
& DUMP_BINFO
) != 0);
123 dq
->node
= splay_tree_insert (di
->nodes
, (splay_tree_key
) t
,
124 (splay_tree_value
) dni
);
126 /* Add it to the end of the queue. */
131 di
->queue_end
->next
= dq
;
134 /* Return the index. */
139 dump_index (di
, index
)
143 fprintf (di
->stream
, "@%-6u ", index
);
147 /* If T has not already been output, queue it for subsequent output.
148 FIELD is a string to print before printing the index. Then, the
149 index of T is printed. */
152 queue_and_dump_index (di
, field
, t
, flags
)
161 /* If there's no node, just return. This makes for fewer checks in
166 /* See if we've already queued or dumped this node. */
167 n
= splay_tree_lookup (di
->nodes
, (splay_tree_key
) t
);
169 index
= ((dump_node_info_p
) n
->value
)->index
;
171 /* If we haven't, add it to the queue. */
172 index
= queue (di
, t
, flags
);
174 /* Print the index of the node. */
175 dump_maybe_newline (di
);
176 fprintf (di
->stream
, "%-4s: ", field
);
178 dump_index (di
, index
);
181 /* Dump the type of T. */
184 queue_and_dump_type (di
, t
, dump_children_p
)
189 queue_and_dump_index (di
, "type", TREE_TYPE (t
), dump_children_p
);
192 /* Insert a new line in the dump output, and indent to an appropriate
193 place to start printing more fields. */
199 fprintf (di
->stream
, "\n%25s", "");
203 /* If necessary, insert a new line. */
206 dump_maybe_newline (di
)
209 /* See if we need a new line. */
212 /* See if we need any padding. */
213 else if ((di
->column
- 25) % 14 != 0)
215 fprintf (di
->stream
, "%*s", 14 - ((di
->column
- 25) % 14), "");
216 di
->column
+= 14 - (di
->column
- 25) % 14;
220 /* Dump I using FIELD to identity it. */
223 dump_int (di
, field
, i
)
228 dump_maybe_newline (di
);
229 fprintf (di
->stream
, "%-4s: %-7d ", field
, i
);
233 /* Dump the string S. */
236 dump_string (di
, string
)
240 dump_maybe_newline (di
);
241 fprintf (di
->stream
, "%-13s ", string
);
242 if (strlen (string
) > 13)
243 di
->column
+= strlen (string
) + 1;
248 /* Dump the string field S. */
251 dump_string_field (di
, field
, string
)
256 dump_maybe_newline (di
);
257 fprintf (di
->stream
, "%-4s: %-7s ", field
, string
);
258 if (strlen (string
) > 7)
259 di
->column
+= 6 + strlen (string
) + 1;
264 /* Dump information common to statements from STMT. */
271 dump_int (di
, "line", STMT_LINENO (t
));
274 /* Dump the CHILD and its children. */
275 #define dump_child(field, child) \
276 queue_and_dump_index (di, field, child, DUMP_CHILDREN)
278 /* Dump the next statement after STMT. */
281 dump_next_stmt (di
, t
)
285 dump_child ("next", TREE_CHAIN (t
));
288 /* Dump the next node in the queue. */
291 dequeue_and_dump (di
)
296 dump_node_info_p dni
;
302 const char* code_name
;
304 /* Get the next node from the queue. */
308 dni
= (dump_node_info_p
) stn
->value
;
310 dump_children_p
= dni
->dump_children_p
;
312 /* Remove the node from the queue, and put it on the free list. */
313 di
->queue
= dq
->next
;
316 dq
->next
= di
->free_list
;
319 /* Print the node index. */
320 dump_index (di
, index
);
321 /* And the type of node this is. */
325 code_name
= tree_code_name
[(int) TREE_CODE (t
)];
326 fprintf (di
->stream
, "%-16s ", code_name
);
329 /* Figure out what kind of node this is. */
330 code
= TREE_CODE (t
);
331 code_class
= TREE_CODE_CLASS (code
);
333 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
337 if (TREE_VIA_PUBLIC (t
))
338 dump_string (di
, "pub");
339 else if (TREE_VIA_PROTECTED (t
))
340 dump_string (di
, "prot");
341 else if (TREE_VIA_PRIVATE (t
))
342 dump_string (di
, "priv");
343 if (TREE_VIA_VIRTUAL (t
))
344 dump_string (di
, "virt");
348 dump_child ("type", BINFO_TYPE (t
));
349 dump_child ("base", BINFO_BASETYPES (t
));
355 /* We can knock off a bunch of expression nodes in exactly the same
357 if (IS_EXPR_CODE_CLASS (code_class
))
359 /* If we're dumping children, dump them now. */
362 queue_and_dump_type (di
, t
, 1);
367 dump_child ("op 0", TREE_OPERAND (t
, 0));
372 dump_child ("op 0", TREE_OPERAND (t
, 0));
373 dump_child ("op 1", TREE_OPERAND (t
, 1));
377 /* These nodes are handled explicitly below. */
381 my_friendly_abort (19990726);
385 else if (code_class
== 'd')
387 /* All declarations have names. */
389 dump_child ("name", DECL_NAME (t
));
393 queue_and_dump_type (di
, t
, 1);
394 queue_and_dump_index (di
, "scpe", DECL_CONTEXT (t
), 0);
396 /* And a source position. */
397 if (DECL_SOURCE_FILE (t
))
399 const char *filename
= rindex (DECL_SOURCE_FILE (t
), '/');
401 filename
= DECL_SOURCE_FILE (t
);
403 /* Skip the slash. */
406 dump_maybe_newline (di
);
407 fprintf (di
->stream
, "srcp: %s:%-6d ", filename
,
408 DECL_SOURCE_LINE (t
));
409 di
->column
+= 6 + strlen (filename
) + 8;
411 /* And any declaration can be compiler-generated. */
412 if (DECL_ARTIFICIAL (t
))
413 dump_string (di
, "artificial");
415 dump_child ("chan", TREE_CHAIN (t
));
417 else if (code_class
== 't')
419 /* All types have qualifiers. */
420 int quals
= CP_TYPE_QUALS (t
);
421 if (quals
!= TYPE_UNQUALIFIED
)
423 fprintf (di
->stream
, "qual: %c%c%c ",
424 (quals
& TYPE_QUAL_CONST
) ? 'c' : ' ',
425 (quals
& TYPE_QUAL_VOLATILE
) ? 'v' : ' ',
426 (quals
& TYPE_QUAL_RESTRICT
) ? 'r' : ' ');
430 /* All types have associated declarations. */
431 dump_child ("name", TYPE_NAME (t
));
435 /* All types have a main variant. */
436 if (TYPE_MAIN_VARIANT (t
) != t
)
437 dump_child ("unql", TYPE_MAIN_VARIANT (t
));
440 dump_child ("size", TYPE_SIZE (t
));
443 /* All types have alignments. */
444 dump_int (di
, "algn", TYPE_ALIGN (t
));
447 /* Now handle the various kinds of nodes. */
452 case IDENTIFIER_NODE
:
453 if (IDENTIFIER_OPNAME_P (t
))
454 dump_string (di
, "operator");
455 else if (IDENTIFIER_TYPENAME_P (t
))
456 queue_and_dump_index (di
, "tynm", TREE_TYPE (t
), 0);
457 else if (t
== anonymous_namespace_name
)
458 dump_string (di
, "unnamed");
461 dump_string_field (di
, "strg", IDENTIFIER_POINTER (t
));
462 dump_int (di
, "lngt", IDENTIFIER_LENGTH (t
));
469 dump_child ("purp", TREE_PURPOSE (t
));
470 dump_child ("valu", TREE_VALUE (t
));
471 dump_child ("chan", TREE_CHAIN (t
));
476 dump_int (di
, "lngt", IDENTIFIER_LENGTH (t
));
478 for (i
= 0; i
< TREE_VEC_LENGTH (t
); ++i
)
481 sprintf (buffer
, "%u", i
);
482 queue_and_dump_index (di
, buffer
, TREE_VEC_ELT (t
, i
), 1);
488 dump_int (di
, "prec", TYPE_PRECISION (t
));
489 if (TREE_UNSIGNED (t
))
490 dump_string (di
, "unsigned");
493 dump_child ("min", TYPE_MIN_VALUE (t
));
494 dump_child ("max", TYPE_MAX_VALUE (t
));
497 if (code
== ENUMERAL_TYPE
&& dump_children_p
)
498 dump_child ("csts", TYPE_VALUES (t
));
502 dump_int (di
, "prec", TYPE_PRECISION (t
));
508 if (TYPE_PTRMEM_P (t
))
510 dump_string (di
, "ptrmem");
511 queue_and_dump_index (di
, "ptd",
512 TYPE_PTRMEM_POINTED_TO_TYPE (t
), 1);
513 queue_and_dump_index (di
, "cls",
514 TYPE_PTRMEM_CLASS_TYPE (t
), 1);
517 dump_child ("ptd", TREE_TYPE (t
));
523 dump_child ("refd", TREE_TYPE (t
));
528 dump_child ("clas", TYPE_METHOD_BASETYPE (t
));
534 dump_child ("retn", TREE_TYPE (t
));
535 dump_child ("prms", TYPE_ARG_TYPES (t
));
542 dump_child ("elts", TREE_TYPE (t
));
543 dump_child ("domn", TYPE_DOMAIN (t
));
549 if (TYPE_PTRMEMFUNC_P (t
))
551 dump_string (di
, "ptrmem");
552 queue_and_dump_index (di
, "ptd",
553 TYPE_PTRMEM_POINTED_TO_TYPE (t
), 1);
554 queue_and_dump_index (di
, "cls",
555 TYPE_PTRMEM_CLASS_TYPE (t
), 1);
559 if (CLASSTYPE_DECLARED_CLASS (t
))
560 dump_string (di
, "class");
561 else if (TREE_CODE (t
) == RECORD_TYPE
)
562 dump_string (di
, "struct");
564 dump_string (di
, "union");
568 dump_child ("flds", TYPE_FIELDS (t
));
569 dump_child ("fncs", TYPE_METHODS (t
));
570 queue_and_dump_index (di
, "binf", TYPE_BINFO (t
),
571 DUMP_CHILDREN
| DUMP_BINFO
);
578 dump_child ("cnst", DECL_INITIAL (t
));
586 dump_child ("init", DECL_INITIAL (t
));
587 dump_child ("size", DECL_SIZE (t
));
589 dump_int (di
, "algn", DECL_ALIGN (t
));
591 if (TREE_CODE (t
) == FIELD_DECL
&& dump_children_p
)
592 dump_child ("bpos", DECL_FIELD_BITPOS (t
));
598 queue_and_dump_index (di
, "scpe", DECL_REAL_CONTEXT (t
), 0);
599 dump_child ("mngl", DECL_ASSEMBLER_NAME (t
));
600 dump_child ("args", DECL_ARGUMENTS (t
));
603 dump_string(di
, "extern");
605 dump_string (di
, "static");
606 if (DECL_FUNCTION_MEMBER_P (t
))
607 dump_string (di
, "member");
608 if (DECL_CONSTRUCTOR_P (t
))
609 dump_string (di
, "constructor");
610 if (DECL_DESTRUCTOR_P (t
))
611 dump_string (di
, "destructor");
612 if (DECL_OVERLOADED_OPERATOR_P (t
))
613 dump_string (di
, "operator");
614 if (DECL_CONV_FN_P (t
))
615 dump_string (di
, "conversion");
617 dump_child ("body", DECL_SAVED_TREE (t
));
621 /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
622 and therefore many other macros do not work on it. */
626 dump_child ("dcls", cp_namespace_decls (t
));
631 dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t
));
637 dump_child ("crnt", OVL_CURRENT (t
));
638 dump_child ("chan", OVL_CHAIN (t
));
644 if (ASM_VOLATILE_P (t
))
645 dump_string (di
, "volatile");
648 dump_child ("strg", ASM_STRING (t
));
649 dump_child ("outs", ASM_OUTPUTS (t
));
650 dump_child ("ins", ASM_INPUTS (t
));
651 dump_child ("clbr", ASM_CLOBBERS (t
));
653 dump_next_stmt (di
, t
);
659 dump_next_stmt (di
, t
);
663 /* Note that a case label is not like other statments; there is
664 no way to get the line-number of a case label. */
667 dump_child ("low", CASE_LOW (t
));
668 dump_child ("high", CASE_HIGH (t
));
670 dump_next_stmt (di
, t
);
676 dump_child ("body", COMPOUND_BODY (t
));
677 dump_next_stmt (di
, t
);
683 dump_child ("decl", DECL_STMT_DECL (t
));
684 dump_next_stmt (di
, t
);
691 dump_child ("body", DO_BODY (t
));
692 dump_child ("cond", DO_COND (t
));
694 dump_next_stmt (di
, t
);
700 dump_child ("expr", EXPR_STMT_EXPR (t
));
701 dump_next_stmt (di
, t
);
708 dump_child ("init", FOR_INIT_STMT (t
));
709 dump_child ("cond", FOR_COND (t
));
710 dump_child ("expr", FOR_EXPR (t
));
711 dump_child ("body", FOR_BODY (t
));
713 dump_next_stmt (di
, t
);
719 dump_child ("dest", GOTO_DESTINATION (t
));
720 dump_next_stmt (di
, t
);
727 dump_child ("cond", IF_COND (t
));
728 dump_child ("then", THEN_CLAUSE (t
));
729 dump_child ("else", ELSE_CLAUSE (t
));
731 dump_next_stmt (di
, t
);
737 dump_child ("expr", RETURN_EXPR (t
));
738 dump_next_stmt (di
, t
);
745 dump_child ("cond", SWITCH_COND (t
));
746 dump_child ("body", SWITCH_BODY (t
));
748 dump_next_stmt (di
, t
);
755 dump_child ("body", TRY_STMTS (t
));
756 dump_child ("hdlr", TRY_HANDLERS (t
));
758 dump_next_stmt (di
, t
);
765 dump_child ("cond", WHILE_COND (t
));
766 dump_child ("body", WHILE_BODY (t
));
768 dump_next_stmt (di
, t
);
772 if (TREE_INT_CST_HIGH (t
))
773 dump_int (di
, "high", TREE_INT_CST_HIGH (t
));
774 dump_int (di
, "low", TREE_INT_CST_LOW (t
));
778 fprintf (di
->stream
, "strg: %-7s ", TREE_STRING_POINTER (t
));
779 dump_int (di
, "lngt", TREE_STRING_LENGTH (t
));
785 dump_child ("clas", PTRMEM_CST_CLASS (t
));
786 dump_child ("mbr", PTRMEM_CST_MEMBER (t
));
794 /* These nodes are unary, but do not have code class `1'. */
796 dump_child ("op 0", TREE_OPERAND (t
, 0));
799 case TRUTH_ANDIF_EXPR
:
800 case TRUTH_ORIF_EXPR
:
805 /* These nodes are binary, but do not have code class `2'. */
808 dump_child ("op 0", TREE_OPERAND (t
, 0));
809 dump_child ("op 1", TREE_OPERAND (t
, 1));
816 dump_child ("fn", TREE_OPERAND (t
, 0));
817 dump_child ("args", TREE_OPERAND (t
, 1));
823 dump_child ("elts", TREE_OPERAND (t
, 1));
828 dump_child ("stmt", STMT_EXPR_STMT (t
));
834 dump_child ("decl", TREE_OPERAND (t
, 0));
835 dump_child ("init", TREE_OPERAND (t
, 1));
836 dump_child ("clnp", TREE_OPERAND (t
, 2));
837 /* There really are two possible places the initializer can
838 be. After RTL expansion, the second operand is moved to
839 the position of the fourth operand, and the second
840 operand becomes NULL. */
841 dump_child ("init", TREE_OPERAND (t
, 3));
846 /* There are no additional fields to print. */
851 /* Terminate the line. */
852 fprintf (di
->stream
, "\n");
855 /* Dump T, and all its children, on STREAM. */
858 dump_node (t
, stream
)
864 dump_queue_p next_dq
;
866 /* Initialize the dump-information structure. */
873 di
.nodes
= splay_tree_new (splay_tree_compare_pointers
, 0,
874 (splay_tree_delete_value_fn
) &free
);
876 /* Queue up the first node. */
877 queue (&di
, t
, DUMP_CHILDREN
);
879 /* Until the queue is empty, keep dumping nodes. */
881 dequeue_and_dump (&di
);
884 for (dq
= di
.free_list
; dq
; dq
= next_dq
)
889 splay_tree_delete (di
.nodes
);
892 /* Dump T, and all its children, to FILE. */
895 dump_node_to_file (t
, file
)
901 f
= fopen (file
, "w");
903 cp_error ("could not open `%s'", file
);