OSDN Git Service

* cp-tree.h (IDENTIFIER_TYPENAME_P): Use a flag, not strncmp.
[pf3gnuchains/gcc-fork.git] / gcc / cp / dump.c
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999, 2000 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 PARAMS ((dump_info_p, tree, int));
75 static void dump_index PARAMS ((dump_info_p, unsigned int));
76 static void queue_and_dump_index PARAMS ((dump_info_p, const char *, tree, int));
77 static void queue_and_dump_type PARAMS ((dump_info_p, tree));
78 static void dequeue_and_dump PARAMS ((dump_info_p));
79 static void dump_new_line PARAMS ((dump_info_p));
80 static void dump_maybe_newline PARAMS ((dump_info_p));
81 static void dump_int PARAMS ((dump_info_p, const char *, int));
82 static void dump_string PARAMS ((dump_info_p, const char *));
83 static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
84 static void dump_node PARAMS ((tree, FILE *));
85 static void dump_stmt PARAMS ((dump_info_p, tree));
86 static void dump_next_stmt PARAMS ((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       if (DECL_LANG_SPECIFIC (t) && DECL_LANGUAGE (t) != lang_cplusplus)
399         dump_string (di, language_to_string (DECL_LANGUAGE (t), 0));
400     }
401   else if (code_class == 't')
402     {
403       /* All types have qualifiers.  */
404       int quals = CP_TYPE_QUALS (t);
405       if (quals != TYPE_UNQUALIFIED)
406         {
407           fprintf (di->stream, "qual: %c%c%c     ",
408                    (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
409                    (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
410                    (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
411           di->column += 14;
412         }
413
414       /* All types have associated declarations.  */
415       dump_child ("name", TYPE_NAME (t));
416
417       /* All types have a main variant.  */
418       if (TYPE_MAIN_VARIANT (t) != t)
419         dump_child ("unql", TYPE_MAIN_VARIANT (t));
420       
421       /* And sizes.  */
422       dump_child ("size", TYPE_SIZE (t));
423
424       /* All types have alignments.  */
425       dump_int (di, "algn", TYPE_ALIGN (t));
426     }
427   else if (code_class == 'c')
428     /* All constants can have types.  */
429     queue_and_dump_type (di, t);
430
431   /* Now handle the various kinds of nodes.  */
432   switch (code)
433     {
434       int i;
435
436     case IDENTIFIER_NODE:
437       if (IDENTIFIER_OPNAME_P (t))
438         dump_string (di, "operator");
439       else if (IDENTIFIER_TYPENAME_P (t))
440         dump_child ("tynm", TREE_TYPE (t));
441       else if (t == anonymous_namespace_name)
442         dump_string (di, "unnamed");
443       else
444         {
445           dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
446           dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
447         }
448       break;
449
450     case TREE_LIST:
451       dump_child ("purp", TREE_PURPOSE (t));
452       dump_child ("valu", TREE_VALUE (t));
453       dump_child ("chan", TREE_CHAIN (t));
454       break;
455
456     case TREE_VEC:
457       dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
458       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
459         {
460           char buffer[32];
461           sprintf (buffer, "%u", i);
462           dump_child (buffer, TREE_VEC_ELT (t, i));
463         }
464       break;
465
466     case INTEGER_TYPE:
467     case ENUMERAL_TYPE:
468       dump_int (di, "prec", TYPE_PRECISION (t));
469       if (TREE_UNSIGNED (t))
470         dump_string (di, "unsigned");
471       dump_child ("min", TYPE_MIN_VALUE (t));
472       dump_child ("max", TYPE_MAX_VALUE (t));
473
474       if (code == ENUMERAL_TYPE)
475         dump_child ("csts", TYPE_VALUES (t));
476       break;
477
478     case REAL_TYPE:
479       dump_int (di, "prec", TYPE_PRECISION (t));
480       break;
481
482     case POINTER_TYPE:
483       if (TYPE_PTRMEM_P (t))
484         {
485           dump_string (di, "ptrmem");
486           dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
487           dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
488         }
489       else
490         dump_child ("ptd", TREE_TYPE (t));
491       break;
492
493     case REFERENCE_TYPE:
494       dump_child ("refd", TREE_TYPE (t));
495       break;
496
497     case METHOD_TYPE:
498       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
499       /* Fall through.  */
500
501     case FUNCTION_TYPE:
502       dump_child ("retn", TREE_TYPE (t));
503       dump_child ("prms", TYPE_ARG_TYPES (t));
504       break;
505
506     case ARRAY_TYPE:
507       dump_child ("elts", TREE_TYPE (t));
508       dump_child ("domn", TYPE_DOMAIN (t));
509       break;
510
511     case RECORD_TYPE:
512     case UNION_TYPE:
513       if (TYPE_PTRMEMFUNC_P (t))
514         {
515           dump_string (di, "ptrmem");
516           dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
517           dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
518         }
519       else
520         {
521           if (CLASSTYPE_DECLARED_CLASS (t))
522             dump_string (di, "class");
523           else if (TREE_CODE (t) == RECORD_TYPE)
524             dump_string (di, "struct");
525           else
526             dump_string (di, "union");
527
528           dump_child ("flds", TYPE_FIELDS (t));
529           dump_child ("fncs", TYPE_METHODS (t));
530           dump_child ("vfld", TYPE_VFIELD (t));
531           queue_and_dump_index (di, "binf", TYPE_BINFO (t), 
532                                 DUMP_BINFO);
533         }
534       break;
535
536     case CONST_DECL:
537       dump_child ("cnst", DECL_INITIAL (t));
538       break;
539
540     case VAR_DECL:
541     case PARM_DECL:
542     case FIELD_DECL:
543     case RESULT_DECL:
544       if (TREE_CODE (t) == PARM_DECL)
545         dump_child ("argt", DECL_ARG_TYPE (t));
546       else
547         dump_child ("init", DECL_INITIAL (t));
548       dump_child ("size", DECL_SIZE (t));
549       dump_int (di, "algn", DECL_ALIGN (t));
550
551       if (TREE_CODE (t) == FIELD_DECL)
552         {
553           if (DECL_C_BIT_FIELD (t))
554             dump_string (di, "bitfield");
555           if (DECL_FIELD_OFFSET (t))
556             dump_child ("bpos", bit_position (t));
557         }
558       break;
559
560     case FUNCTION_DECL:
561       dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
562       dump_child ("args", DECL_ARGUMENTS (t));
563       if (DECL_EXTERNAL (t))
564         dump_string (di, "undefined");
565       if (TREE_PUBLIC (t))
566         dump_string(di, "extern");
567       else
568         dump_string (di, "static");
569       if (TREE_CODE (t) == FUNCTION_DECL)
570         {
571           if (DECL_FUNCTION_MEMBER_P (t))
572             dump_string (di, "member");
573           if (DECL_CONSTRUCTOR_P (t))
574             dump_string (di, "constructor");
575           if (DECL_DESTRUCTOR_P (t))
576             dump_string (di, "destructor");
577           if (DECL_OVERLOADED_OPERATOR_P (t))
578             dump_string (di, "operator");
579           if (DECL_CONV_FN_P (t))
580             dump_string (di, "conversion");
581           if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
582             {
583               if (DECL_GLOBAL_CTOR_P (t))
584                 dump_string (di, "global init");
585               if (DECL_GLOBAL_DTOR_P (t))
586                 dump_string (di, "global fini");
587               dump_int (di, "prio", GLOBAL_INIT_PRIORITY (t));
588             }
589           if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t))
590             dump_string (di, "pseudo tmpl");
591
592           dump_child ("body", DECL_SAVED_TREE (t));
593         }
594       else
595         {
596           dump_int (di, "dlta", THUNK_DELTA (t));
597           dump_child ("init", DECL_INITIAL (t));
598         }
599       break;
600
601     case NAMESPACE_DECL:
602       /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
603          and therefore many other macros do not work on it.  */
604       if (t == std_node)
605         break;
606       if (DECL_NAMESPACE_ALIAS (t))
607         dump_child ("alis", DECL_NAMESPACE_ALIAS (t));
608       else
609         dump_child ("dcls", cp_namespace_decls (t));
610       break;
611
612     case TEMPLATE_DECL:
613       dump_child ("rslt", DECL_TEMPLATE_RESULT (t));
614       dump_child ("inst", DECL_TEMPLATE_INSTANTIATIONS (t));
615       dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t));
616       break;
617
618     case OVERLOAD:
619       dump_child ("crnt", OVL_CURRENT (t));
620       dump_child ("chan", OVL_CHAIN (t));
621       break;
622
623     case ASM_STMT:
624       dump_stmt (di, t);
625       if (ASM_VOLATILE_P (t))
626         dump_string (di, "volatile");
627       dump_child ("strg", ASM_STRING (t));
628       dump_child ("outs", ASM_OUTPUTS (t));
629       dump_child ("ins", ASM_INPUTS (t));
630       dump_child ("clbr", ASM_CLOBBERS (t));
631       dump_next_stmt (di, t);
632       break;
633
634     case BREAK_STMT:
635     case CONTINUE_STMT:
636       dump_stmt (di, t);
637       dump_next_stmt (di, t);
638       break;
639
640     case CASE_LABEL:
641       /* Note that a case label is not like other statments; there is
642          no way to get the line-number of a case label.  */
643       dump_child ("low", CASE_LOW (t));
644       dump_child ("high", CASE_HIGH (t));
645       dump_next_stmt (di, t);
646       break;
647
648     case COMPOUND_STMT:
649       dump_stmt (di, t);
650       dump_child ("body", COMPOUND_BODY (t));
651       dump_next_stmt (di, t);
652       break;
653
654     case CTOR_STMT:
655       dump_stmt (di, t);
656       if (CTOR_BEGIN_P (t))
657         dump_string (di, "begn");
658       else
659         dump_string (di, "end");
660       dump_next_stmt (di, t);
661       break;
662
663     case DECL_STMT:
664       dump_stmt (di, t);
665       dump_child ("decl", DECL_STMT_DECL (t));
666       dump_next_stmt (di, t);
667       break;
668       
669     case DO_STMT:
670       dump_stmt (di, t);
671       dump_child ("body", DO_BODY (t));
672       dump_child ("cond", DO_COND (t));
673       dump_next_stmt (di, t);
674       break;
675
676     case EXPR_STMT:
677       dump_stmt (di, t);
678       dump_child ("expr", EXPR_STMT_EXPR (t));
679       dump_next_stmt (di, t);
680       break;
681
682     case FOR_STMT:
683       dump_stmt (di, t);
684       dump_child ("init", FOR_INIT_STMT (t));
685       dump_child ("cond", FOR_COND (t));
686       dump_child ("expr", FOR_EXPR (t));
687       dump_child ("body", FOR_BODY (t));
688       dump_next_stmt (di, t);
689       break;
690
691     case GOTO_STMT:
692       dump_stmt (di, t);
693       dump_child ("dest", GOTO_DESTINATION (t));
694       dump_next_stmt (di, t);
695       break;
696
697     case HANDLER:
698       dump_stmt (di, t);
699       dump_child ("body", HANDLER_BODY (t));
700       dump_next_stmt (di, t);
701       break;
702
703     case IF_STMT:
704       dump_stmt (di, t);
705       dump_child ("cond", IF_COND (t));
706       dump_child ("then", THEN_CLAUSE (t));
707       dump_child ("else", ELSE_CLAUSE (t));
708       dump_next_stmt (di, t);
709       break;
710
711     case LABEL_STMT:
712       dump_stmt (di, t);
713       dump_child ("labl", LABEL_STMT_LABEL (t));
714       dump_next_stmt (di, t);
715       break;
716
717     case RETURN_STMT:
718       dump_stmt (di, t);
719       dump_child ("expr", RETURN_EXPR (t));
720       dump_next_stmt (di, t);
721       break;
722
723     case SWITCH_STMT:
724       dump_stmt (di, t);
725       dump_child ("cond", SWITCH_COND (t));
726       dump_child ("body", SWITCH_BODY (t));
727       dump_next_stmt (di, t);
728       break;
729
730     case TRY_BLOCK:
731       dump_stmt (di, t);
732       if (CLEANUP_P (t))
733         dump_string (di, "cleanup");
734       dump_child ("body", TRY_STMTS (t));
735       dump_child ("hdlr", TRY_HANDLERS (t));
736       dump_next_stmt (di, t);
737       break;
738
739     case WHILE_STMT:
740       dump_stmt (di, t);
741       dump_child ("cond", WHILE_COND (t));
742       dump_child ("body", WHILE_BODY (t));
743       dump_next_stmt (di, t);
744       break;
745
746     case SUBOBJECT:
747       dump_stmt (di, t);
748       dump_child ("clnp", TREE_OPERAND (t, 0));
749       dump_next_stmt (di, t);
750       break;
751
752     case START_CATCH_STMT:
753       dump_stmt (di, t);
754       queue_and_dump_type (di, t);
755       dump_next_stmt (di, t);
756       break;
757
758     case CLEANUP_STMT:
759       dump_stmt (di, t);
760       dump_child ("decl", CLEANUP_DECL (t));
761       dump_child ("expr", CLEANUP_EXPR (t));
762       dump_next_stmt (di, t);
763       break;
764
765     case SCOPE_STMT:
766       dump_stmt (di, t);
767       if (SCOPE_BEGIN_P (t))
768         dump_string (di, "begn");
769       else
770         dump_string (di, "end");
771       if (SCOPE_NULLIFIED_P (t))
772         dump_string (di, "null");
773       if (!SCOPE_NO_CLEANUPS_P (t))
774         dump_string (di, "clnp");
775       dump_next_stmt (di, t);
776       break;
777
778     case INTEGER_CST:
779       if (TREE_INT_CST_HIGH (t))
780         dump_int (di, "high", TREE_INT_CST_HIGH (t));
781       dump_int (di, "low", TREE_INT_CST_LOW (t));
782       break;
783
784     case STRING_CST:
785       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
786       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
787       break;
788
789     case PTRMEM_CST:
790       dump_child ("clas", PTRMEM_CST_CLASS (t));
791       dump_child ("mbr", PTRMEM_CST_MEMBER (t));
792       break;
793
794     case TRUTH_NOT_EXPR:
795     case ADDR_EXPR:
796     case INDIRECT_REF:
797     case THROW_EXPR:
798     case CLEANUP_POINT_EXPR:
799     case SAVE_EXPR:
800       /* These nodes are unary, but do not have code class `1'.  */
801       dump_child ("op 0", TREE_OPERAND (t, 0));
802       break;
803
804     case TRUTH_ANDIF_EXPR:
805     case TRUTH_ORIF_EXPR:
806     case INIT_EXPR:
807     case MODIFY_EXPR:
808     case COMPONENT_REF:
809     case COMPOUND_EXPR:
810     case ARRAY_REF:
811     case PREDECREMENT_EXPR:
812     case PREINCREMENT_EXPR:
813     case POSTDECREMENT_EXPR:
814     case POSTINCREMENT_EXPR:
815       /* These nodes are binary, but do not have code class `2'.  */
816       dump_child ("op 0", TREE_OPERAND (t, 0));
817       dump_child ("op 1", TREE_OPERAND (t, 1));
818       break;
819
820     case COND_EXPR:
821       dump_child ("op 0", TREE_OPERAND (t, 0));
822       dump_child ("op 1", TREE_OPERAND (t, 1));
823       dump_child ("op 2", TREE_OPERAND (t, 2));
824       break;
825
826     case CALL_EXPR:
827       dump_child ("fn", TREE_OPERAND (t, 0));
828       dump_child ("args", TREE_OPERAND (t, 1));
829       break;
830
831     case CONSTRUCTOR:
832       dump_child ("elts", TREE_OPERAND (t, 1));
833       break;
834
835     case STMT_EXPR:
836       dump_child ("stmt", STMT_EXPR_STMT (t));
837       break;
838
839     case BIND_EXPR:
840       dump_child ("vars", TREE_OPERAND (t, 0));
841       dump_child ("body", TREE_OPERAND (t, 1));
842       break;
843
844     case LOOP_EXPR:
845       dump_child ("body", TREE_OPERAND (t, 0));
846       break;
847
848     case EXIT_EXPR:
849       dump_child ("cond", TREE_OPERAND (t, 0));
850       break;
851
852     case TARGET_EXPR:
853       dump_child ("decl", TREE_OPERAND (t, 0));
854       dump_child ("init", TREE_OPERAND (t, 1));
855       dump_child ("clnp", TREE_OPERAND (t, 2));
856       /* There really are two possible places the initializer can be.
857          After RTL expansion, the second operand is moved to the
858          position of the fourth operand, and the second operand
859          becomes NULL.  */
860       dump_child ("init", TREE_OPERAND (t, 3));
861       break;
862       
863     case AGGR_INIT_EXPR:
864       dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
865       dump_child ("fn", TREE_OPERAND (t, 0));
866       dump_child ("args", TREE_OPERAND (t, 1));
867       dump_child ("decl", TREE_OPERAND (t, 2));
868       break;
869       
870     case EXPR_WITH_FILE_LOCATION:
871       dump_child ("expr", EXPR_WFL_NODE (t));
872       break;
873
874     default:
875       /* There are no additional fields to print.  */
876       break;
877     }
878
879  done:
880   /* Terminate the line.  */
881   fprintf (di->stream, "\n");
882 }
883
884 /* Dump T, and all its children, on STREAM.  */
885
886 static void
887 dump_node (t, stream)
888      tree t;
889      FILE *stream;
890 {
891   struct dump_info di;
892   dump_queue_p dq;
893   dump_queue_p next_dq;
894
895   /* Initialize the dump-information structure.  */
896   di.stream = stream;
897   di.index = 0;
898   di.column = 0;
899   di.queue = 0;
900   di.queue_end = 0;
901   di.free_list = 0;
902   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
903                              (splay_tree_delete_value_fn) &free);
904
905   /* Queue up the first node.  */
906   queue (&di, t, DUMP_NONE);
907
908   /* Until the queue is empty, keep dumping nodes.  */
909   while (di.queue)
910     dequeue_and_dump (&di);
911
912   /* Now, clean up.  */
913   for (dq = di.free_list; dq; dq = next_dq)
914     {
915       next_dq = dq->next;
916       free (dq);
917     }
918   splay_tree_delete (di.nodes);
919 }
920
921 /* Dump T, and all its children, to FILE.  */
922
923 void
924 dump_node_to_file (t, file)
925      tree t;
926      const char *file;
927 {
928   FILE *f;
929
930   f = fopen (file, "w");
931   if (!f)
932     cp_error ("could not open `%s'", file);
933   else
934     {
935       dump_node (t, f);
936       fclose (f);
937     }
938 }