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));
446 else if (code_class == 'c' && dump_children_p)
447 /* All constants can have types. */
448 queue_and_dump_type (di, t, 1);
450 /* Now handle the various kinds of nodes. */
455 case IDENTIFIER_NODE:
456 if (IDENTIFIER_OPNAME_P (t))
457 dump_string (di, "operator");
458 else if (IDENTIFIER_TYPENAME_P (t))
459 queue_and_dump_index (di, "tynm", TREE_TYPE (t), 0);
460 else if (t == anonymous_namespace_name)
461 dump_string (di, "unnamed");
464 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
465 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
472 dump_child ("purp", TREE_PURPOSE (t));
473 dump_child ("valu", TREE_VALUE (t));
474 dump_child ("chan", TREE_CHAIN (t));
479 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
481 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
484 sprintf (buffer, "%u", i);
485 queue_and_dump_index (di, buffer, TREE_VEC_ELT (t, i), 1);
491 dump_int (di, "prec", TYPE_PRECISION (t));
492 if (TREE_UNSIGNED (t))
493 dump_string (di, "unsigned");
496 dump_child ("min", TYPE_MIN_VALUE (t));
497 dump_child ("max", TYPE_MAX_VALUE (t));
500 if (code == ENUMERAL_TYPE && dump_children_p)
501 dump_child ("csts", TYPE_VALUES (t));
505 dump_int (di, "prec", TYPE_PRECISION (t));
511 if (TYPE_PTRMEM_P (t))
513 dump_string (di, "ptrmem");
514 queue_and_dump_index (di, "ptd",
515 TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
516 queue_and_dump_index (di, "cls",
517 TYPE_PTRMEM_CLASS_TYPE (t), 1);
520 dump_child ("ptd", TREE_TYPE (t));
526 dump_child ("refd", TREE_TYPE (t));
531 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
537 dump_child ("retn", TREE_TYPE (t));
538 dump_child ("prms", TYPE_ARG_TYPES (t));
545 dump_child ("elts", TREE_TYPE (t));
546 dump_child ("domn", TYPE_DOMAIN (t));
552 if (TYPE_PTRMEMFUNC_P (t))
554 dump_string (di, "ptrmem");
555 queue_and_dump_index (di, "ptd",
556 TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
557 queue_and_dump_index (di, "cls",
558 TYPE_PTRMEM_CLASS_TYPE (t), 1);
562 if (CLASSTYPE_DECLARED_CLASS (t))
563 dump_string (di, "class");
564 else if (TREE_CODE (t) == RECORD_TYPE)
565 dump_string (di, "struct");
567 dump_string (di, "union");
571 dump_child ("flds", TYPE_FIELDS (t));
572 dump_child ("fncs", TYPE_METHODS (t));
573 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
574 DUMP_CHILDREN | DUMP_BINFO);
581 dump_child ("cnst", DECL_INITIAL (t));
589 if (TREE_CODE (t) == PARM_DECL)
590 dump_child ("argt", DECL_ARG_TYPE (t));
592 dump_child ("init", DECL_INITIAL (t));
593 dump_child ("size", DECL_SIZE (t));
595 dump_int (di, "algn", DECL_ALIGN (t));
597 if (TREE_CODE (t) == FIELD_DECL && dump_children_p)
598 dump_child ("bpos", DECL_FIELD_BITPOS (t));
604 queue_and_dump_index (di, "scpe", DECL_REAL_CONTEXT (t), 0);
605 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
606 dump_child ("args", DECL_ARGUMENTS (t));
609 dump_string(di, "extern");
611 dump_string (di, "static");
612 if (DECL_FUNCTION_MEMBER_P (t))
613 dump_string (di, "member");
614 if (DECL_CONSTRUCTOR_P (t))
615 dump_string (di, "constructor");
616 if (DECL_DESTRUCTOR_P (t))
617 dump_string (di, "destructor");
618 if (DECL_OVERLOADED_OPERATOR_P (t))
619 dump_string (di, "operator");
620 if (DECL_CONV_FN_P (t))
621 dump_string (di, "conversion");
623 dump_child ("body", DECL_SAVED_TREE (t));
627 /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
628 and therefore many other macros do not work on it. */
632 dump_child ("dcls", cp_namespace_decls (t));
637 dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t));
643 dump_child ("crnt", OVL_CURRENT (t));
644 dump_child ("chan", OVL_CHAIN (t));
650 if (ASM_VOLATILE_P (t))
651 dump_string (di, "volatile");
654 dump_child ("strg", ASM_STRING (t));
655 dump_child ("outs", ASM_OUTPUTS (t));
656 dump_child ("ins", ASM_INPUTS (t));
657 dump_child ("clbr", ASM_CLOBBERS (t));
659 dump_next_stmt (di, t);
665 dump_next_stmt (di, t);
669 /* Note that a case label is not like other statments; there is
670 no way to get the line-number of a case label. */
673 dump_child ("low", CASE_LOW (t));
674 dump_child ("high", CASE_HIGH (t));
676 dump_next_stmt (di, t);
682 dump_child ("body", COMPOUND_BODY (t));
683 dump_next_stmt (di, t);
689 dump_child ("decl", DECL_STMT_DECL (t));
690 dump_next_stmt (di, t);
697 dump_child ("body", DO_BODY (t));
698 dump_child ("cond", DO_COND (t));
700 dump_next_stmt (di, t);
706 dump_child ("expr", EXPR_STMT_EXPR (t));
707 dump_next_stmt (di, t);
714 dump_child ("init", FOR_INIT_STMT (t));
715 dump_child ("cond", FOR_COND (t));
716 dump_child ("expr", FOR_EXPR (t));
717 dump_child ("body", FOR_BODY (t));
719 dump_next_stmt (di, t);
725 dump_child ("dest", GOTO_DESTINATION (t));
726 dump_next_stmt (di, t);
733 dump_child ("cond", IF_COND (t));
734 dump_child ("then", THEN_CLAUSE (t));
735 dump_child ("else", ELSE_CLAUSE (t));
737 dump_next_stmt (di, t);
743 dump_child ("labl", LABEL_STMT_LABEL (t));
744 dump_next_stmt (di, t);
750 dump_child ("expr", RETURN_EXPR (t));
751 dump_next_stmt (di, t);
758 dump_child ("cond", SWITCH_COND (t));
759 dump_child ("body", SWITCH_BODY (t));
761 dump_next_stmt (di, t);
768 dump_child ("body", TRY_STMTS (t));
769 dump_child ("hdlr", TRY_HANDLERS (t));
771 dump_next_stmt (di, t);
778 dump_child ("cond", WHILE_COND (t));
779 dump_child ("body", WHILE_BODY (t));
781 dump_next_stmt (di, t);
787 dump_child ("clnp", TREE_OPERAND (t, 0));
788 dump_next_stmt (di, t);
792 if (TREE_INT_CST_HIGH (t))
793 dump_int (di, "high", TREE_INT_CST_HIGH (t));
794 dump_int (di, "low", TREE_INT_CST_LOW (t));
798 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
799 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
805 dump_child ("clas", PTRMEM_CST_CLASS (t));
806 dump_child ("mbr", PTRMEM_CST_MEMBER (t));
814 /* These nodes are unary, but do not have code class `1'. */
816 dump_child ("op 0", TREE_OPERAND (t, 0));
819 case TRUTH_ANDIF_EXPR:
820 case TRUTH_ORIF_EXPR:
827 /* These nodes are binary, but do not have code class `2'. */
830 dump_child ("op 0", TREE_OPERAND (t, 0));
831 dump_child ("op 1", TREE_OPERAND (t, 1));
838 dump_child ("fn", TREE_OPERAND (t, 0));
839 dump_child ("args", TREE_OPERAND (t, 1));
845 dump_child ("elts", TREE_OPERAND (t, 1));
850 dump_child ("stmt", STMT_EXPR_STMT (t));
856 dump_child ("decl", TREE_OPERAND (t, 0));
857 dump_child ("init", TREE_OPERAND (t, 1));
858 dump_child ("clnp", TREE_OPERAND (t, 2));
859 /* There really are two possible places the initializer can
860 be. After RTL expansion, the second operand is moved to
861 the position of the fourth operand, and the second
862 operand becomes NULL. */
863 dump_child ("init", TREE_OPERAND (t, 3));
868 dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
871 dump_child ("fn", TREE_OPERAND (t, 0));
872 dump_child ("args", TREE_OPERAND (t, 1));
873 dump_child ("decl", TREE_OPERAND (t, 2));
878 /* There are no additional fields to print. */
883 /* Terminate the line. */
884 fprintf (di->stream, "\n");
887 /* Dump T, and all its children, on STREAM. */
890 dump_node (t, stream)
896 dump_queue_p next_dq;
898 /* Initialize the dump-information structure. */
905 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
906 (splay_tree_delete_value_fn) &free);
908 /* Queue up the first node. */
909 queue (&di, t, DUMP_CHILDREN);
911 /* Until the queue is empty, keep dumping nodes. */
913 dequeue_and_dump (&di);
916 for (dq = di.free_list; dq; dq = next_dq)
921 splay_tree_delete (di.nodes);
924 /* Dump T, and all its children, to FILE. */
927 dump_node_to_file (t, file)
933 f = fopen (file, "w");
935 cp_error ("could not open `%s'", file);