OSDN Git Service

1999-10-21 Mark Mitchell <mark@codesourcery.com>
[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 IF_STMT:
682       dump_stmt (di, t);
683       dump_child ("cond", IF_COND (t));
684       dump_child ("then", THEN_CLAUSE (t));
685       dump_child ("else", ELSE_CLAUSE (t));
686       dump_next_stmt (di, t);
687       break;
688
689     case LABEL_STMT:
690       dump_stmt (di, t);
691       dump_child ("labl", LABEL_STMT_LABEL (t));
692       dump_next_stmt (di, t);
693       break;
694
695     case RETURN_STMT:
696       dump_stmt (di, t);
697       dump_child ("expr", RETURN_EXPR (t));
698       dump_next_stmt (di, t);
699       break;
700
701     case SWITCH_STMT:
702       dump_stmt (di, t);
703       dump_child ("cond", SWITCH_COND (t));
704       dump_child ("body", SWITCH_BODY (t));
705       dump_next_stmt (di, t);
706       break;
707
708     case TRY_BLOCK:
709       dump_stmt (di, t);
710       dump_child ("body", TRY_STMTS (t));
711       dump_child ("hdlr", TRY_HANDLERS (t));
712       dump_next_stmt (di, t);
713       break;
714
715     case WHILE_STMT:
716       dump_stmt (di, t);
717       dump_child ("cond", WHILE_COND (t));
718       dump_child ("body", WHILE_BODY (t));
719       dump_next_stmt (di, t);
720       break;
721
722     case SUBOBJECT:
723       dump_stmt (di, t);
724       dump_child ("clnp", TREE_OPERAND (t, 0));
725       dump_next_stmt (di, t);
726       break;
727
728     case START_CATCH_STMT:
729       dump_stmt (di, t);
730       queue_and_dump_type (di, TREE_TYPE (t));
731       dump_next_stmt (di, t);
732       break;
733
734     case CLEANUP_STMT:
735       dump_stmt (di, t);
736       dump_child ("decl", CLEANUP_DECL (t));
737       dump_child ("expr", CLEANUP_EXPR (t));
738       dump_next_stmt (di, t);
739       break;
740
741     case SCOPE_STMT:
742       dump_stmt (di, t);
743       if (SCOPE_BEGIN_P (t))
744         dump_string (di, "begn");
745       else
746         dump_string (di, "end");
747       if (SCOPE_NULLIFIED_P (t))
748         dump_string (di, "null");
749       dump_next_stmt (di, t);
750       break;
751
752     case INTEGER_CST:
753       if (TREE_INT_CST_HIGH (t))
754         dump_int (di, "high", TREE_INT_CST_HIGH (t));
755       dump_int (di, "low", TREE_INT_CST_LOW (t));
756       break;
757
758     case STRING_CST:
759       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
760       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
761       break;
762
763     case PTRMEM_CST:
764       dump_child ("clas", PTRMEM_CST_CLASS (t));
765       dump_child ("mbr", PTRMEM_CST_MEMBER (t));
766       break;
767
768     case TRUTH_NOT_EXPR:
769     case ADDR_EXPR:
770     case INDIRECT_REF:
771     case THROW_EXPR:
772     case CLEANUP_POINT_EXPR:
773       /* These nodes are unary, but do not have code class `1'.  */
774       dump_child ("op 0", TREE_OPERAND (t, 0));
775       break;
776
777     case TRUTH_ANDIF_EXPR:
778     case TRUTH_ORIF_EXPR:
779     case INIT_EXPR:
780     case MODIFY_EXPR:
781     case COMPONENT_REF:
782     case COMPOUND_EXPR:
783     case ARRAY_REF:
784       /* These nodes are binary, but do not have code class `2'.  */
785       dump_child ("op 0", TREE_OPERAND (t, 0));
786       dump_child ("op 1", TREE_OPERAND (t, 1));
787       break;
788
789     case COND_EXPR:
790       dump_child ("op 0", TREE_OPERAND (t, 0));
791       dump_child ("op 1", TREE_OPERAND (t, 1));
792       dump_child ("op 2", TREE_OPERAND (t, 2));
793       break;
794
795     case CALL_EXPR:
796       dump_child ("fn", TREE_OPERAND (t, 0));
797       dump_child ("args", TREE_OPERAND (t, 1));
798       break;
799
800     case CONSTRUCTOR:
801       dump_child ("elts", TREE_OPERAND (t, 1));
802       break;
803
804     case STMT_EXPR:
805       dump_child ("stmt", STMT_EXPR_STMT (t));
806       break;
807
808     case BIND_EXPR:
809       dump_child ("vars", TREE_OPERAND (t, 0));
810       dump_child ("body", TREE_OPERAND (t, 1));
811       break;
812
813     case LOOP_EXPR:
814       dump_child ("body", TREE_OPERAND (t, 0));
815       break;
816
817     case EXIT_EXPR:
818       dump_child ("cond", TREE_OPERAND (t, 0));
819       break;
820
821     case TARGET_EXPR:
822       dump_child ("decl", TREE_OPERAND (t, 0));
823       dump_child ("init", TREE_OPERAND (t, 1));
824       dump_child ("clnp", TREE_OPERAND (t, 2));
825       /* There really are two possible places the initializer can be.
826          After RTL expansion, the second operand is moved to the
827          position of the fourth operand, and the second operand
828          becomes NULL.  */
829       dump_child ("init", TREE_OPERAND (t, 3));
830       break;
831       
832     case AGGR_INIT_EXPR:
833       dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
834       dump_child ("fn", TREE_OPERAND (t, 0));
835       dump_child ("args", TREE_OPERAND (t, 1));
836       dump_child ("decl", TREE_OPERAND (t, 2));
837       break;
838
839     default:
840       /* There are no additional fields to print.  */
841       break;
842     }
843
844  done:
845   /* Terminate the line.  */
846   fprintf (di->stream, "\n");
847 }
848
849 /* Dump T, and all its children, on STREAM.  */
850
851 static void
852 dump_node (t, stream)
853      tree t;
854      FILE *stream;
855 {
856   struct dump_info di;
857   dump_queue_p dq;
858   dump_queue_p next_dq;
859
860   /* Initialize the dump-information structure.  */
861   di.stream = stream;
862   di.index = 0;
863   di.column = 0;
864   di.queue = 0;
865   di.queue_end = 0;
866   di.free_list = 0;
867   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
868                              (splay_tree_delete_value_fn) &free);
869
870   /* Queue up the first node.  */
871   queue (&di, t, DUMP_NONE);
872
873   /* Until the queue is empty, keep dumping nodes.  */
874   while (di.queue)
875     dequeue_and_dump (&di);
876
877   /* Now, clean up.  */
878   for (dq = di.free_list; dq; dq = next_dq)
879     {
880       next_dq = dq->next;
881       free (dq);
882     }
883   splay_tree_delete (di.nodes);
884 }
885
886 /* Dump T, and all its children, to FILE.  */
887
888 void
889 dump_node_to_file (t, file)
890      tree t;
891      const char *file;
892 {
893   FILE *f;
894
895   f = fopen (file, "w");
896   if (!f)
897     cp_error ("could not open `%s'", file);
898   else
899     {
900       dump_node (t, f);
901       fclose (f);
902     }
903 }