OSDN Git Service

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