OSDN Git Service

* dump.c (dequeue_and_dump): Improve support for dumping THUNK_DECLs.
[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     case RESULT_DECL:
588       if (dump_children_p)
589         {
590           if (TREE_CODE (t) == PARM_DECL)
591             dump_child ("argt", DECL_ARG_TYPE (t));
592           else
593             dump_child ("init", DECL_INITIAL (t));
594           dump_child ("size", DECL_SIZE (t));
595         }
596       dump_int (di, "algn", DECL_ALIGN (t));
597
598       if (TREE_CODE (t) == FIELD_DECL && dump_children_p)
599         dump_child ("bpos", DECL_FIELD_BITPOS (t));
600       break;
601
602     case FUNCTION_DECL:
603     case THUNK_DECL:
604       if (dump_children_p)
605         {
606           queue_and_dump_index (di, "scpe", DECL_REAL_CONTEXT (t), 0);
607           dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
608           dump_child ("args", DECL_ARGUMENTS (t));
609         }
610       if (TREE_PUBLIC (t))
611         dump_string(di, "extern");
612       else
613         dump_string (di, "static");
614       if (TREE_CODE (t) == FUNCTION_DECL)
615         {
616           if (DECL_FUNCTION_MEMBER_P (t))
617             dump_string (di, "member");
618           if (DECL_CONSTRUCTOR_P (t))
619             dump_string (di, "constructor");
620           if (DECL_DESTRUCTOR_P (t))
621             dump_string (di, "destructor");
622           if (DECL_OVERLOADED_OPERATOR_P (t))
623             dump_string (di, "operator");
624           if (DECL_CONV_FN_P (t))
625             dump_string (di, "conversion");
626           if (dump_children_p)
627             dump_child ("body", DECL_SAVED_TREE (t));
628         }
629       else
630         {
631           dump_int (di, "dlta", THUNK_DELTA (t));
632           dump_child ("init", DECL_INITIAL (t));
633         }
634       break;
635
636     case NAMESPACE_DECL:
637       /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
638          and therefore many other macros do not work on it.  */
639       if (t == std_node)
640         break;
641       if (dump_children_p)
642         dump_child ("dcls", cp_namespace_decls (t));
643       break;
644
645     case TEMPLATE_DECL:
646       if (dump_children_p)
647         dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t));
648       break;
649
650     case OVERLOAD:
651       if (dump_children_p)
652         {
653           dump_child ("crnt", OVL_CURRENT (t));
654           dump_child ("chan", OVL_CHAIN (t));
655         }
656       break;
657
658     case ASM_STMT:
659       dump_stmt (di, t);
660       if (ASM_VOLATILE_P (t))
661         dump_string (di, "volatile");
662       if (dump_children_p)
663         {
664           dump_child ("strg", ASM_STRING (t));
665           dump_child ("outs", ASM_OUTPUTS (t));
666           dump_child ("ins", ASM_INPUTS (t));
667           dump_child ("clbr", ASM_CLOBBERS (t));
668         }
669       dump_next_stmt (di, t);
670       break;
671
672     case BREAK_STMT:
673     case CONTINUE_STMT:
674       dump_stmt (di, t);
675       dump_next_stmt (di, t);
676       break;
677
678     case CASE_LABEL:
679       /* Note that a case label is not like other statments; there is
680          no way to get the line-number of a case label.  */
681       if (dump_children_p)
682         {
683           dump_child ("low", CASE_LOW (t));
684           dump_child ("high", CASE_HIGH (t));
685         }
686       dump_next_stmt (di, t);
687       break;
688
689     case COMPOUND_STMT:
690       dump_stmt (di, t);
691       if (dump_children_p)
692         dump_child ("body", COMPOUND_BODY (t));
693       dump_next_stmt (di, t);
694       break;
695
696     case DECL_STMT:
697       dump_stmt (di, t);
698       if (dump_children_p)
699         dump_child ("decl", DECL_STMT_DECL (t));
700       dump_next_stmt (di, t);
701       break;
702       
703     case DO_STMT:
704       dump_stmt (di, t);
705       if (dump_children_p)
706         {
707           dump_child ("body", DO_BODY (t));
708           dump_child ("cond", DO_COND (t));
709         }
710       dump_next_stmt (di, t);
711       break;
712
713     case EXPR_STMT:
714       dump_stmt (di, t);
715       if (dump_children_p)
716         dump_child ("expr", EXPR_STMT_EXPR (t));
717       dump_next_stmt (di, t);
718       break;
719
720     case FOR_STMT:
721       dump_stmt (di, t);
722       if (dump_children_p)
723         {
724           dump_child ("init", FOR_INIT_STMT (t));
725           dump_child ("cond", FOR_COND (t));
726           dump_child ("expr", FOR_EXPR (t));
727           dump_child ("body", FOR_BODY (t));
728         }
729       dump_next_stmt (di, t);
730       break;
731
732     case GOTO_STMT:
733       dump_stmt (di, t);
734       if (dump_children_p)
735         dump_child ("dest", GOTO_DESTINATION (t));
736       dump_next_stmt (di, t);
737       break;
738
739     case IF_STMT:
740       dump_stmt (di, t);
741       if (dump_children_p)
742         {
743           dump_child ("cond", IF_COND (t));
744           dump_child ("then", THEN_CLAUSE (t));
745           dump_child ("else", ELSE_CLAUSE (t));
746         }
747       dump_next_stmt (di, t);
748       break;
749
750     case LABEL_STMT:
751       dump_stmt (di, t);
752       if (dump_children_p)
753         dump_child ("labl", LABEL_STMT_LABEL (t));
754       dump_next_stmt (di, t);
755       break;
756
757     case RETURN_STMT:
758       dump_stmt (di, t);
759       if (dump_children_p)
760         dump_child ("expr", RETURN_EXPR (t));
761       dump_next_stmt (di, t);
762       break;
763
764     case SWITCH_STMT:
765       dump_stmt (di, t);
766       if (dump_children_p)
767         {
768           dump_child ("cond", SWITCH_COND (t));
769           dump_child ("body", SWITCH_BODY (t));
770         }
771       dump_next_stmt (di, t);
772       break;
773
774     case TRY_BLOCK:
775       dump_stmt (di, t);
776       if (dump_children_p)
777         {
778           dump_child ("body", TRY_STMTS (t));
779           dump_child ("hdlr", TRY_HANDLERS (t));
780         }
781       dump_next_stmt (di, t);
782       break;
783
784     case WHILE_STMT:
785       dump_stmt (di, t);
786       if (dump_children_p)
787         {
788           dump_child ("cond", WHILE_COND (t));
789           dump_child ("body", WHILE_BODY (t));
790         }
791       dump_next_stmt (di, t);
792       break;
793
794     case SUBOBJECT:
795       dump_stmt (di, t);
796       if (dump_children_p)
797         dump_child ("clnp", TREE_OPERAND (t, 0));
798       dump_next_stmt (di, t);
799       break;
800
801     case START_CATCH_STMT:
802       dump_stmt (di, t);
803       if (dump_children_p)
804         queue_and_dump_type (di, TREE_TYPE (t), /*dump_children_p=*/1);
805       dump_next_stmt (di, t);
806       break;
807
808     case CLEANUP_STMT:
809       dump_stmt (di, t);
810       if (dump_children_p)
811         {
812           dump_child ("decl", CLEANUP_DECL (t));
813           dump_child ("expr", CLEANUP_EXPR (t));
814         }
815       dump_next_stmt (di, t);
816       break;
817
818     case SCOPE_STMT:
819       dump_stmt (di, t);
820       if (SCOPE_BEGIN_P (t))
821         dump_string (di, "begn");
822       else
823         dump_string (di, "end");
824       if (SCOPE_NULLIFIED_P (t))
825         dump_string (di, "null");
826       dump_next_stmt (di, t);
827       break;
828
829     case INTEGER_CST:
830       if (TREE_INT_CST_HIGH (t))
831         dump_int (di, "high", TREE_INT_CST_HIGH (t));
832       dump_int (di, "low", TREE_INT_CST_LOW (t));
833       break;
834
835     case STRING_CST:
836       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
837       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
838       break;
839
840     case PTRMEM_CST:
841       if (dump_children_p)
842         {
843           dump_child ("clas", PTRMEM_CST_CLASS (t));
844           dump_child ("mbr", PTRMEM_CST_MEMBER (t));
845         }
846       break;
847
848     case TRUTH_NOT_EXPR:
849     case ADDR_EXPR:
850     case INDIRECT_REF:
851     case THROW_EXPR:
852       /* These nodes are unary, but do not have code class `1'.  */
853       if (dump_children_p)
854         dump_child ("op 0", TREE_OPERAND (t, 0));
855       break;
856
857     case TRUTH_ANDIF_EXPR:
858     case TRUTH_ORIF_EXPR:
859     case INIT_EXPR:
860     case MODIFY_EXPR:
861     case COMPONENT_REF:
862     case COMPOUND_EXPR:
863     case COND_EXPR:
864     case ARRAY_REF:
865       /* These nodes are binary, but do not have code class `2'.  */
866       if (dump_children_p)
867         {
868           dump_child ("op 0", TREE_OPERAND (t, 0));
869           dump_child ("op 1", TREE_OPERAND (t, 1));
870         }
871       break;
872
873     case CALL_EXPR:
874       if (dump_children_p)
875         {
876           dump_child ("fn", TREE_OPERAND (t, 0));
877           dump_child ("args", TREE_OPERAND (t, 1));
878         }
879       break;
880
881     case CONSTRUCTOR:
882       if (dump_children_p)
883         dump_child ("elts", TREE_OPERAND (t, 1));
884       break;
885
886     case STMT_EXPR:
887       if (dump_children_p)
888         dump_child ("stmt", STMT_EXPR_STMT (t));
889       break;
890
891     case TARGET_EXPR:
892       if (dump_children_p)
893         {
894           dump_child ("decl", TREE_OPERAND (t, 0));
895           dump_child ("init", TREE_OPERAND (t, 1));
896           dump_child ("clnp", TREE_OPERAND (t, 2));
897           /* There really are two possible places the initializer can
898              be.  After RTL expansion, the second operand is moved to
899              the position of the fourth operand, and the second
900              operand becomes NULL.  */
901           dump_child ("init", TREE_OPERAND (t, 3));
902         }
903       break;
904       
905     case AGGR_INIT_EXPR:
906       dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
907       if (dump_children_p)
908         {
909           dump_child ("fn", TREE_OPERAND (t, 0));
910           dump_child ("args", TREE_OPERAND (t, 1));
911           dump_child ("decl", TREE_OPERAND (t, 2));
912         }
913       break;
914
915     default:
916       /* There are no additional fields to print.  */
917       break;
918     }
919
920  done:
921   /* Terminate the line.  */
922   fprintf (di->stream, "\n");
923 }
924
925 /* Dump T, and all its children, on STREAM.  */
926
927 static void
928 dump_node (t, stream)
929      tree t;
930      FILE *stream;
931 {
932   struct dump_info di;
933   dump_queue_p dq;
934   dump_queue_p next_dq;
935
936   /* Initialize the dump-information structure.  */
937   di.stream = stream;
938   di.index = 0;
939   di.column = 0;
940   di.queue = 0;
941   di.queue_end = 0;
942   di.free_list = 0;
943   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
944                              (splay_tree_delete_value_fn) &free);
945
946   /* Queue up the first node.  */
947   queue (&di, t, DUMP_CHILDREN);
948
949   /* Until the queue is empty, keep dumping nodes.  */
950   while (di.queue)
951     dequeue_and_dump (&di);
952
953   /* Now, clean up.  */
954   for (dq = di.free_list; dq; dq = next_dq)
955     {
956       next_dq = dq->next;
957       free (dq);
958     }
959   splay_tree_delete (di.nodes);
960 }
961
962 /* Dump T, and all its children, to FILE.  */
963
964 void
965 dump_node_to_file (t, file)
966      tree t;
967      const char *file;
968 {
969   FILE *f;
970
971   f = fopen (file, "w");
972   if (!f)
973     cp_error ("could not open `%s'", file);
974   else
975     {
976       dump_node (t, f);
977       fclose (f);
978     }
979 }