OSDN Git Service

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