OSDN Git Service

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