OSDN Git Service

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