OSDN Git Service

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