* cp-tree.h (CLASSTYPE_VFIELD): Remove.
[official-gcc.git] / gcc / cp / dump.c
blobdc767bc8fa77847fd20766034b32869a8ad349a3
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)
10 any later version.
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. */
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "cp-tree.h"
26 #include "splay-tree.h"
28 /* Flags used with queue functions. */
29 #define DUMP_NONE 0
30 #define DUMP_BINFO 1
32 /* Information about a node to be dumped. */
34 typedef struct dump_node_info
36 /* The index for the node. */
37 unsigned int index;
38 /* Nonzero if the node is a binfo. */
39 unsigned int binfo_p : 1;
40 } *dump_node_info_p;
42 /* A dump_queue is a link in the queue of things to be dumped. */
44 typedef struct dump_queue
46 /* The queued tree node. */
47 splay_tree_node node;
48 /* The next node in the queue. */
49 struct dump_queue *next;
50 } *dump_queue_p;
52 /* A dump_info gives information about how we should perform the dump
53 and about the current state of the dump. */
55 typedef struct dump_info
57 /* The stream on which to dump the information. */
58 FILE *stream;
59 /* The next unused node index. */
60 unsigned int index;
61 /* The next column. */
62 unsigned int column;
63 /* The first node in the queue of nodes to be written out. */
64 dump_queue_p queue;
65 /* The last node in the queue. */
66 dump_queue_p queue_end;
67 /* Free queue nodes. */
68 dump_queue_p free_list;
69 /* The tree nodes which we have already written out. The
70 keys are the addresses of the nodes; the values are the integer
71 indices we assigned them. */
72 splay_tree nodes;
73 } *dump_info_p;
75 static unsigned int queue PROTO ((dump_info_p, tree, int));
76 static void dump_index PROTO ((dump_info_p, unsigned int));
77 static void queue_and_dump_index PROTO ((dump_info_p, const char *, tree, int));
78 static void queue_and_dump_type PROTO ((dump_info_p, tree));
79 static void dequeue_and_dump PROTO ((dump_info_p));
80 static void dump_new_line PROTO ((dump_info_p));
81 static void dump_maybe_newline PROTO ((dump_info_p));
82 static void dump_int PROTO ((dump_info_p, const char *, int));
83 static void dump_string PROTO ((dump_info_p, const char *));
84 static void dump_string_field PROTO ((dump_info_p, const char *, const char *));
85 static void dump_node PROTO ((tree, FILE *));
86 static void dump_stmt PROTO ((dump_info_p, tree));
87 static void dump_next_stmt PROTO ((dump_info_p, tree));
89 /* Add T to the end of the queue of nodes to dump. Returns the index
90 assigned to T. */
92 static unsigned int
93 queue (di, t, flags)
94 dump_info_p di;
95 tree t;
96 int flags;
98 dump_queue_p dq;
99 dump_node_info_p dni;
100 unsigned int index;
102 /* Assign the next available index to T. */
103 index = ++di->index;
105 /* Obtain a new queue node. */
106 if (di->free_list)
108 dq = di->free_list;
109 di->free_list = dq->next;
111 else
112 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
114 /* Create a new entry in the splay-tree. */
115 dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
116 dni->index = index;
117 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
118 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
119 (splay_tree_value) dni);
121 /* Add it to the end of the queue. */
122 dq->next = 0;
123 if (!di->queue_end)
124 di->queue = dq;
125 else
126 di->queue_end->next = dq;
127 di->queue_end = dq;
129 /* Return the index. */
130 return index;
133 static void
134 dump_index (di, index)
135 dump_info_p di;
136 unsigned int index;
138 fprintf (di->stream, "@%-6u ", index);
139 di->column += 8;
142 /* If T has not already been output, queue it for subsequent output.
143 FIELD is a string to print before printing the index. Then, the
144 index of T is printed. */
146 static void
147 queue_and_dump_index (di, field, t, flags)
148 dump_info_p di;
149 const char *field;
150 tree t;
151 int flags;
153 unsigned int index;
154 splay_tree_node n;
156 /* If there's no node, just return. This makes for fewer checks in
157 our callers. */
158 if (!t)
159 return;
161 /* See if we've already queued or dumped this node. */
162 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
163 if (n)
164 index = ((dump_node_info_p) n->value)->index;
165 else
166 /* If we haven't, add it to the queue. */
167 index = queue (di, t, flags);
169 /* Print the index of the node. */
170 dump_maybe_newline (di);
171 fprintf (di->stream, "%-4s: ", field);
172 di->column += 6;
173 dump_index (di, index);
176 /* Dump the type of T. */
178 static void
179 queue_and_dump_type (di, t)
180 dump_info_p di;
181 tree t;
183 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
186 /* Insert a new line in the dump output, and indent to an appropriate
187 place to start printing more fields. */
189 static void
190 dump_new_line (di)
191 dump_info_p di;
193 fprintf (di->stream, "\n%25s", "");
194 di->column = 25;
197 /* If necessary, insert a new line. */
199 static void
200 dump_maybe_newline (di)
201 dump_info_p di;
203 /* See if we need a new line. */
204 if (di->column > 53)
205 dump_new_line (di);
206 /* See if we need any padding. */
207 else if ((di->column - 25) % 14 != 0)
209 fprintf (di->stream, "%*s", 14 - ((di->column - 25) % 14), "");
210 di->column += 14 - (di->column - 25) % 14;
214 /* Dump I using FIELD to identity it. */
216 static void
217 dump_int (di, field, i)
218 dump_info_p di;
219 const char *field;
220 int i;
222 dump_maybe_newline (di);
223 fprintf (di->stream, "%-4s: %-7d ", field, i);
224 di->column += 14;
227 /* Dump the string S. */
229 static void
230 dump_string (di, string)
231 dump_info_p di;
232 const char *string;
234 dump_maybe_newline (di);
235 fprintf (di->stream, "%-13s ", string);
236 if (strlen (string) > 13)
237 di->column += strlen (string) + 1;
238 else
239 di->column += 14;
242 /* Dump the string field S. */
244 static void
245 dump_string_field (di, field, string)
246 dump_info_p di;
247 const char *field;
248 const char *string;
250 dump_maybe_newline (di);
251 fprintf (di->stream, "%-4s: %-7s ", field, string);
252 if (strlen (string) > 7)
253 di->column += 6 + strlen (string) + 1;
254 else
255 di->column += 14;
258 /* Dump information common to statements from STMT. */
260 static void
261 dump_stmt (di, t)
262 dump_info_p di;
263 tree t;
265 dump_int (di, "line", STMT_LINENO (t));
268 /* Dump the CHILD and its children. */
269 #define dump_child(field, child) \
270 queue_and_dump_index (di, field, child, DUMP_NONE)
272 /* Dump the next statement after STMT. */
274 static void
275 dump_next_stmt (di, t)
276 dump_info_p di;
277 tree t;
279 dump_child ("next", TREE_CHAIN (t));
282 /* Dump the next node in the queue. */
284 static void
285 dequeue_and_dump (di)
286 dump_info_p di;
288 dump_queue_p dq;
289 splay_tree_node stn;
290 dump_node_info_p dni;
291 tree t;
292 unsigned int index;
293 enum tree_code code;
294 char code_class;
295 const char* code_name;
297 /* Get the next node from the queue. */
298 dq = di->queue;
299 stn = dq->node;
300 t = (tree) stn->key;
301 dni = (dump_node_info_p) stn->value;
302 index = dni->index;
304 /* Remove the node from the queue, and put it on the free list. */
305 di->queue = dq->next;
306 if (!di->queue)
307 di->queue_end = 0;
308 dq->next = di->free_list;
309 di->free_list = dq;
311 /* Print the node index. */
312 dump_index (di, index);
313 /* And the type of node this is. */
314 if (dni->binfo_p)
315 code_name = "binfo";
316 else
317 code_name = tree_code_name[(int) TREE_CODE (t)];
318 fprintf (di->stream, "%-16s ", code_name);
319 di->column = 25;
321 /* Figure out what kind of node this is. */
322 code = TREE_CODE (t);
323 code_class = TREE_CODE_CLASS (code);
325 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
326 more informative. */
327 if (dni->binfo_p)
329 if (TREE_VIA_PUBLIC (t))
330 dump_string (di, "pub");
331 else if (TREE_VIA_PROTECTED (t))
332 dump_string (di, "prot");
333 else if (TREE_VIA_PRIVATE (t))
334 dump_string (di, "priv");
335 if (TREE_VIA_VIRTUAL (t))
336 dump_string (di, "virt");
338 dump_child ("type", BINFO_TYPE (t));
339 dump_child ("base", BINFO_BASETYPES (t));
341 goto done;
344 /* We can knock off a bunch of expression nodes in exactly the same
345 way. */
346 if (IS_EXPR_CODE_CLASS (code_class))
348 /* If we're dumping children, dump them now. */
349 queue_and_dump_type (di, t);
351 switch (code_class)
353 case '1':
354 dump_child ("op 0", TREE_OPERAND (t, 0));
355 break;
357 case '2':
358 case '<':
359 dump_child ("op 0", TREE_OPERAND (t, 0));
360 dump_child ("op 1", TREE_OPERAND (t, 1));
361 break;
363 case 'e':
364 /* These nodes are handled explicitly below. */
365 break;
367 default:
368 my_friendly_abort (19990726);
371 else if (code_class == 'd')
373 /* All declarations have names. */
374 if (DECL_NAME (t))
375 dump_child ("name", DECL_NAME (t));
376 /* And types. */
377 queue_and_dump_type (di, t);
378 queue_and_dump_index (di, "scpe", DECL_CONTEXT (t), 0);
379 /* And a source position. */
380 if (DECL_SOURCE_FILE (t))
382 const char *filename = rindex (DECL_SOURCE_FILE (t), '/');
383 if (!filename)
384 filename = DECL_SOURCE_FILE (t);
385 else
386 /* Skip the slash. */
387 ++filename;
389 dump_maybe_newline (di);
390 fprintf (di->stream, "srcp: %s:%-6d ", filename,
391 DECL_SOURCE_LINE (t));
392 di->column += 6 + strlen (filename) + 8;
394 /* And any declaration can be compiler-generated. */
395 if (DECL_ARTIFICIAL (t))
396 dump_string (di, "artificial");
397 if (TREE_CHAIN (t))
398 dump_child ("chan", TREE_CHAIN (t));
400 else if (code_class == 't')
402 /* All types have qualifiers. */
403 int quals = CP_TYPE_QUALS (t);
404 if (quals != TYPE_UNQUALIFIED)
406 fprintf (di->stream, "qual: %c%c%c ",
407 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
408 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
409 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
410 di->column += 14;
413 /* All types have associated declarations. */
414 dump_child ("name", TYPE_NAME (t));
416 /* All types have a main variant. */
417 if (TYPE_MAIN_VARIANT (t) != t)
418 dump_child ("unql", TYPE_MAIN_VARIANT (t));
420 /* And sizes. */
421 dump_child ("size", TYPE_SIZE (t));
423 /* All types have alignments. */
424 dump_int (di, "algn", TYPE_ALIGN (t));
426 else if (code_class == 'c')
427 /* All constants can have types. */
428 queue_and_dump_type (di, t);
430 /* Now handle the various kinds of nodes. */
431 switch (code)
433 int i;
435 case IDENTIFIER_NODE:
436 if (IDENTIFIER_OPNAME_P (t))
437 dump_string (di, "operator");
438 else if (IDENTIFIER_TYPENAME_P (t))
439 queue_and_dump_index (di, "tynm", TREE_TYPE (t), 0);
440 else if (t == anonymous_namespace_name)
441 dump_string (di, "unnamed");
442 else
444 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
445 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
447 break;
449 case TREE_LIST:
450 dump_child ("purp", TREE_PURPOSE (t));
451 dump_child ("valu", TREE_VALUE (t));
452 dump_child ("chan", TREE_CHAIN (t));
453 break;
455 case TREE_VEC:
456 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
457 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
459 char buffer[32];
460 sprintf (buffer, "%u", i);
461 queue_and_dump_index (di, buffer, TREE_VEC_ELT (t, i), 1);
463 break;
465 case INTEGER_TYPE:
466 case ENUMERAL_TYPE:
467 dump_int (di, "prec", TYPE_PRECISION (t));
468 if (TREE_UNSIGNED (t))
469 dump_string (di, "unsigned");
470 dump_child ("min", TYPE_MIN_VALUE (t));
471 dump_child ("max", TYPE_MAX_VALUE (t));
473 if (code == ENUMERAL_TYPE)
474 dump_child ("csts", TYPE_VALUES (t));
475 break;
477 case REAL_TYPE:
478 dump_int (di, "prec", TYPE_PRECISION (t));
479 break;
481 case POINTER_TYPE:
482 if (TYPE_PTRMEM_P (t))
484 dump_string (di, "ptrmem");
485 queue_and_dump_index (di, "ptd",
486 TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
487 queue_and_dump_index (di, "cls",
488 TYPE_PTRMEM_CLASS_TYPE (t), 1);
490 else
491 dump_child ("ptd", TREE_TYPE (t));
492 break;
494 case REFERENCE_TYPE:
495 dump_child ("refd", TREE_TYPE (t));
496 break;
498 case METHOD_TYPE:
499 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
500 /* Fall through. */
502 case FUNCTION_TYPE:
503 dump_child ("retn", TREE_TYPE (t));
504 dump_child ("prms", TYPE_ARG_TYPES (t));
505 break;
507 case ARRAY_TYPE:
508 dump_child ("elts", TREE_TYPE (t));
509 dump_child ("domn", TYPE_DOMAIN (t));
510 break;
512 case RECORD_TYPE:
513 case UNION_TYPE:
514 if (TYPE_PTRMEMFUNC_P (t))
516 dump_string (di, "ptrmem");
517 queue_and_dump_index (di, "ptd",
518 TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
519 queue_and_dump_index (di, "cls",
520 TYPE_PTRMEM_CLASS_TYPE (t), 1);
522 else
524 if (CLASSTYPE_DECLARED_CLASS (t))
525 dump_string (di, "class");
526 else if (TREE_CODE (t) == RECORD_TYPE)
527 dump_string (di, "struct");
528 else
529 dump_string (di, "union");
531 dump_child ("flds", TYPE_FIELDS (t));
532 dump_child ("fncs", TYPE_METHODS (t));
533 dump_child ("vfld", TYPE_VFIELD (t));
534 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
535 DUMP_BINFO);
537 break;
539 case CONST_DECL:
540 dump_child ("cnst", DECL_INITIAL (t));
541 break;
543 case VAR_DECL:
544 case PARM_DECL:
545 case FIELD_DECL:
546 case RESULT_DECL:
547 if (TREE_CODE (t) == PARM_DECL)
548 dump_child ("argt", DECL_ARG_TYPE (t));
549 else
550 dump_child ("init", DECL_INITIAL (t));
551 dump_child ("size", DECL_SIZE (t));
552 dump_int (di, "algn", DECL_ALIGN (t));
554 if (TREE_CODE (t) == FIELD_DECL)
556 if (DECL_C_BIT_FIELD (t))
557 dump_string (di, "bitfield");
558 dump_child ("bpos", DECL_FIELD_BITPOS (t));
560 break;
562 case FUNCTION_DECL:
563 case THUNK_DECL:
564 queue_and_dump_index (di, "scpe", DECL_REAL_CONTEXT (t), 0);
565 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
566 dump_child ("args", DECL_ARGUMENTS (t));
567 if (DECL_EXTERNAL (t))
568 dump_string (di, "undefined");
569 if (TREE_PUBLIC (t))
570 dump_string(di, "extern");
571 else
572 dump_string (di, "static");
573 if (TREE_CODE (t) == FUNCTION_DECL)
575 if (DECL_FUNCTION_MEMBER_P (t))
576 dump_string (di, "member");
577 if (DECL_CONSTRUCTOR_P (t))
578 dump_string (di, "constructor");
579 if (DECL_DESTRUCTOR_P (t))
580 dump_string (di, "destructor");
581 if (DECL_OVERLOADED_OPERATOR_P (t))
582 dump_string (di, "operator");
583 if (DECL_CONV_FN_P (t))
584 dump_string (di, "conversion");
585 if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
587 if (DECL_GLOBAL_CTOR_P (t))
588 dump_string (di, "global init");
589 if (DECL_GLOBAL_DTOR_P (t))
590 dump_string (di, "global fini");
591 dump_int (di, "prio", GLOBAL_INIT_PRIORITY (t));
594 dump_child ("body", DECL_SAVED_TREE (t));
596 else
598 dump_int (di, "dlta", THUNK_DELTA (t));
599 dump_child ("init", DECL_INITIAL (t));
601 break;
603 case NAMESPACE_DECL:
604 /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
605 and therefore many other macros do not work on it. */
606 if (t == std_node)
607 break;
608 dump_child ("dcls", cp_namespace_decls (t));
609 break;
611 case TEMPLATE_DECL:
612 dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t));
613 break;
615 case OVERLOAD:
616 dump_child ("crnt", OVL_CURRENT (t));
617 dump_child ("chan", OVL_CHAIN (t));
618 break;
620 case ASM_STMT:
621 dump_stmt (di, t);
622 if (ASM_VOLATILE_P (t))
623 dump_string (di, "volatile");
624 dump_child ("strg", ASM_STRING (t));
625 dump_child ("outs", ASM_OUTPUTS (t));
626 dump_child ("ins", ASM_INPUTS (t));
627 dump_child ("clbr", ASM_CLOBBERS (t));
628 dump_next_stmt (di, t);
629 break;
631 case BREAK_STMT:
632 case CONTINUE_STMT:
633 dump_stmt (di, t);
634 dump_next_stmt (di, t);
635 break;
637 case CASE_LABEL:
638 /* Note that a case label is not like other statments; there is
639 no way to get the line-number of a case label. */
640 dump_child ("low", CASE_LOW (t));
641 dump_child ("high", CASE_HIGH (t));
642 dump_next_stmt (di, t);
643 break;
645 case COMPOUND_STMT:
646 dump_stmt (di, t);
647 dump_child ("body", COMPOUND_BODY (t));
648 dump_next_stmt (di, t);
649 break;
651 case DECL_STMT:
652 dump_stmt (di, t);
653 dump_child ("decl", DECL_STMT_DECL (t));
654 dump_next_stmt (di, t);
655 break;
657 case DO_STMT:
658 dump_stmt (di, t);
659 dump_child ("body", DO_BODY (t));
660 dump_child ("cond", DO_COND (t));
661 dump_next_stmt (di, t);
662 break;
664 case EXPR_STMT:
665 dump_stmt (di, t);
666 dump_child ("expr", EXPR_STMT_EXPR (t));
667 dump_next_stmt (di, t);
668 break;
670 case FOR_STMT:
671 dump_stmt (di, t);
672 dump_child ("init", FOR_INIT_STMT (t));
673 dump_child ("cond", FOR_COND (t));
674 dump_child ("expr", FOR_EXPR (t));
675 dump_child ("body", FOR_BODY (t));
676 dump_next_stmt (di, t);
677 break;
679 case GOTO_STMT:
680 dump_stmt (di, t);
681 dump_child ("dest", GOTO_DESTINATION (t));
682 dump_next_stmt (di, t);
683 break;
685 case IF_STMT:
686 dump_stmt (di, t);
687 dump_child ("cond", IF_COND (t));
688 dump_child ("then", THEN_CLAUSE (t));
689 dump_child ("else", ELSE_CLAUSE (t));
690 dump_next_stmt (di, t);
691 break;
693 case LABEL_STMT:
694 dump_stmt (di, t);
695 dump_child ("labl", LABEL_STMT_LABEL (t));
696 dump_next_stmt (di, t);
697 break;
699 case RETURN_STMT:
700 dump_stmt (di, t);
701 dump_child ("expr", RETURN_EXPR (t));
702 dump_next_stmt (di, t);
703 break;
705 case SWITCH_STMT:
706 dump_stmt (di, t);
707 dump_child ("cond", SWITCH_COND (t));
708 dump_child ("body", SWITCH_BODY (t));
709 dump_next_stmt (di, t);
710 break;
712 case TRY_BLOCK:
713 dump_stmt (di, t);
714 dump_child ("body", TRY_STMTS (t));
715 dump_child ("hdlr", TRY_HANDLERS (t));
716 dump_next_stmt (di, t);
717 break;
719 case WHILE_STMT:
720 dump_stmt (di, t);
721 dump_child ("cond", WHILE_COND (t));
722 dump_child ("body", WHILE_BODY (t));
723 dump_next_stmt (di, t);
724 break;
726 case SUBOBJECT:
727 dump_stmt (di, t);
728 dump_child ("clnp", TREE_OPERAND (t, 0));
729 dump_next_stmt (di, t);
730 break;
732 case START_CATCH_STMT:
733 dump_stmt (di, t);
734 queue_and_dump_type (di, TREE_TYPE (t));
735 dump_next_stmt (di, t);
736 break;
738 case CLEANUP_STMT:
739 dump_stmt (di, t);
740 dump_child ("decl", CLEANUP_DECL (t));
741 dump_child ("expr", CLEANUP_EXPR (t));
742 dump_next_stmt (di, t);
743 break;
745 case SCOPE_STMT:
746 dump_stmt (di, t);
747 if (SCOPE_BEGIN_P (t))
748 dump_string (di, "begn");
749 else
750 dump_string (di, "end");
751 if (SCOPE_NULLIFIED_P (t))
752 dump_string (di, "null");
753 dump_next_stmt (di, t);
754 break;
756 case INTEGER_CST:
757 if (TREE_INT_CST_HIGH (t))
758 dump_int (di, "high", TREE_INT_CST_HIGH (t));
759 dump_int (di, "low", TREE_INT_CST_LOW (t));
760 break;
762 case STRING_CST:
763 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
764 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
765 break;
767 case PTRMEM_CST:
768 dump_child ("clas", PTRMEM_CST_CLASS (t));
769 dump_child ("mbr", PTRMEM_CST_MEMBER (t));
770 break;
772 case TRUTH_NOT_EXPR:
773 case ADDR_EXPR:
774 case INDIRECT_REF:
775 case THROW_EXPR:
776 /* These nodes are unary, but do not have code class `1'. */
777 dump_child ("op 0", TREE_OPERAND (t, 0));
778 break;
780 case TRUTH_ANDIF_EXPR:
781 case TRUTH_ORIF_EXPR:
782 case INIT_EXPR:
783 case MODIFY_EXPR:
784 case COMPONENT_REF:
785 case COMPOUND_EXPR:
786 case COND_EXPR:
787 case ARRAY_REF:
788 /* These nodes are binary, but do not have code class `2'. */
789 dump_child ("op 0", TREE_OPERAND (t, 0));
790 dump_child ("op 1", TREE_OPERAND (t, 1));
791 break;
793 case CALL_EXPR:
794 dump_child ("fn", TREE_OPERAND (t, 0));
795 dump_child ("args", TREE_OPERAND (t, 1));
796 break;
798 case CONSTRUCTOR:
799 dump_child ("elts", TREE_OPERAND (t, 1));
800 break;
802 case STMT_EXPR:
803 dump_child ("stmt", STMT_EXPR_STMT (t));
804 break;
806 case BIND_EXPR:
807 dump_child ("vars", TREE_OPERAND (t, 0));
808 dump_child ("body", TREE_OPERAND (t, 1));
809 break;
811 case LOOP_EXPR:
812 dump_child ("body", TREE_OPERAND (t, 0));
813 break;
815 case EXIT_EXPR:
816 dump_child ("cond", TREE_OPERAND (t, 0));
817 break;
819 case TARGET_EXPR:
820 dump_child ("decl", TREE_OPERAND (t, 0));
821 dump_child ("init", TREE_OPERAND (t, 1));
822 dump_child ("clnp", TREE_OPERAND (t, 2));
823 /* There really are two possible places the initializer can be.
824 After RTL expansion, the second operand is moved to the
825 position of the fourth operand, and the second operand
826 becomes NULL. */
827 dump_child ("init", TREE_OPERAND (t, 3));
828 break;
830 case AGGR_INIT_EXPR:
831 dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
832 dump_child ("fn", TREE_OPERAND (t, 0));
833 dump_child ("args", TREE_OPERAND (t, 1));
834 dump_child ("decl", TREE_OPERAND (t, 2));
835 break;
837 default:
838 /* There are no additional fields to print. */
839 break;
842 done:
843 /* Terminate the line. */
844 fprintf (di->stream, "\n");
847 /* Dump T, and all its children, on STREAM. */
849 static void
850 dump_node (t, stream)
851 tree t;
852 FILE *stream;
854 struct dump_info di;
855 dump_queue_p dq;
856 dump_queue_p next_dq;
858 /* Initialize the dump-information structure. */
859 di.stream = stream;
860 di.index = 0;
861 di.column = 0;
862 di.queue = 0;
863 di.queue_end = 0;
864 di.free_list = 0;
865 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
866 (splay_tree_delete_value_fn) &free);
868 /* Queue up the first node. */
869 queue (&di, t, DUMP_NONE);
871 /* Until the queue is empty, keep dumping nodes. */
872 while (di.queue)
873 dequeue_and_dump (&di);
875 /* Now, clean up. */
876 for (dq = di.free_list; dq; dq = next_dq)
878 next_dq = dq->next;
879 free (dq);
881 splay_tree_delete (di.nodes);
884 /* Dump T, and all its children, to FILE. */
886 void
887 dump_node_to_file (t, file)
888 tree t;
889 const char *file;
891 FILE *f;
893 f = fopen (file, "w");
894 if (!f)
895 cp_error ("could not open `%s'", file);
896 else
898 dump_node (t, f);
899 fclose (f);