Update copyright years.
[platform/upstream/gcc.git] / gcc / tree-dump.c
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999-2016 Free Software Foundation, Inc.
3    Written by Mark Mitchell <mark@codesourcery.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "tree-pretty-print.h"
26 #include "tree-dump.h"
27 #include "langhooks.h"
28 #include "tree-iterator.h"
29 #include "tree-cfg.h"
30
31 static unsigned int queue (dump_info_p, const_tree, int);
32 static void dump_index (dump_info_p, unsigned int);
33 static void dequeue_and_dump (dump_info_p);
34 static void dump_new_line (dump_info_p);
35 static void dump_maybe_newline (dump_info_p);
36
37 /* Add T to the end of the queue of nodes to dump.  Returns the index
38    assigned to T.  */
39
40 static unsigned int
41 queue (dump_info_p di, const_tree t, int flags)
42 {
43   dump_queue_p dq;
44   dump_node_info_p dni;
45   unsigned int index;
46
47   /* Assign the next available index to T.  */
48   index = ++di->index;
49
50   /* Obtain a new queue node.  */
51   if (di->free_list)
52     {
53       dq = di->free_list;
54       di->free_list = dq->next;
55     }
56   else
57     dq = XNEW (struct dump_queue);
58
59   /* Create a new entry in the splay-tree.  */
60   dni = XNEW (struct dump_node_info);
61   dni->index = index;
62   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
63   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
64                                 (splay_tree_value) dni);
65
66   /* Add it to the end of the queue.  */
67   dq->next = 0;
68   if (!di->queue_end)
69     di->queue = dq;
70   else
71     di->queue_end->next = dq;
72   di->queue_end = dq;
73
74   /* Return the index.  */
75   return index;
76 }
77
78 static void
79 dump_index (dump_info_p di, unsigned int index)
80 {
81   fprintf (di->stream, "@%-6u ", index);
82   di->column += 8;
83 }
84
85 /* If T has not already been output, queue it for subsequent output.
86    FIELD is a string to print before printing the index.  Then, the
87    index of T is printed.  */
88
89 void
90 queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
91 {
92   unsigned int index;
93   splay_tree_node n;
94
95   /* If there's no node, just return.  This makes for fewer checks in
96      our callers.  */
97   if (!t)
98     return;
99
100   /* See if we've already queued or dumped this node.  */
101   n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
102   if (n)
103     index = ((dump_node_info_p) n->value)->index;
104   else
105     /* If we haven't, add it to the queue.  */
106     index = queue (di, t, flags);
107
108   /* Print the index of the node.  */
109   dump_maybe_newline (di);
110   fprintf (di->stream, "%-4s: ", field);
111   di->column += 6;
112   dump_index (di, index);
113 }
114
115 /* Dump the type of T.  */
116
117 void
118 queue_and_dump_type (dump_info_p di, const_tree t)
119 {
120   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
121 }
122
123 /* Dump column control */
124 #define SOL_COLUMN 25           /* Start of line column.  */
125 #define EOL_COLUMN 55           /* End of line column.  */
126 #define COLUMN_ALIGNMENT 15     /* Alignment.  */
127
128 /* Insert a new line in the dump output, and indent to an appropriate
129    place to start printing more fields.  */
130
131 static void
132 dump_new_line (dump_info_p di)
133 {
134   fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
135   di->column = SOL_COLUMN;
136 }
137
138 /* If necessary, insert a new line.  */
139
140 static void
141 dump_maybe_newline (dump_info_p di)
142 {
143   int extra;
144
145   /* See if we need a new line.  */
146   if (di->column > EOL_COLUMN)
147     dump_new_line (di);
148   /* See if we need any padding.  */
149   else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
150     {
151       fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
152       di->column += COLUMN_ALIGNMENT - extra;
153     }
154 }
155
156 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
157
158 void
159 dump_function (int phase, tree fn)
160 {
161   FILE *stream;
162   int flags;
163
164   stream = dump_begin (phase, &flags);
165   if (stream)
166     {
167       dump_function_to_file (fn, stream, flags);
168       dump_end (phase, stream);
169     }
170 }
171
172 /* Dump pointer PTR using FIELD to identify it.  */
173
174 void
175 dump_pointer (dump_info_p di, const char *field, void *ptr)
176 {
177   dump_maybe_newline (di);
178   fprintf (di->stream, "%-4s: %-8" HOST_WIDE_INT_PRINT "x ", field,
179            (unsigned HOST_WIDE_INT) (uintptr_t) ptr);
180   di->column += 15;
181 }
182
183 /* Dump integer I using FIELD to identify it.  */
184
185 void
186 dump_int (dump_info_p di, const char *field, int i)
187 {
188   dump_maybe_newline (di);
189   fprintf (di->stream, "%-4s: %-7d ", field, i);
190   di->column += 14;
191 }
192
193 /* Dump the floating point value R, using FIELD to identify it.  */
194
195 static void
196 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
197 {
198   char buf[32];
199   real_to_decimal (buf, r, sizeof (buf), 0, true);
200   dump_maybe_newline (di);
201   fprintf (di->stream, "%-4s: %s ", field, buf);
202   di->column += strlen (buf) + 7;
203 }
204
205 /* Dump the fixed-point value F, using FIELD to identify it.  */
206
207 static void
208 dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
209 {
210   char buf[32];
211   fixed_to_decimal (buf, f, sizeof (buf));
212   dump_maybe_newline (di);
213   fprintf (di->stream, "%-4s: %s ", field, buf);
214   di->column += strlen (buf) + 7;
215 }
216
217
218 /* Dump the string S.  */
219
220 void
221 dump_string (dump_info_p di, const char *string)
222 {
223   dump_maybe_newline (di);
224   fprintf (di->stream, "%-13s ", string);
225   if (strlen (string) > 13)
226     di->column += strlen (string) + 1;
227   else
228     di->column += 14;
229 }
230
231 /* Dump the string field S.  */
232
233 void
234 dump_string_field (dump_info_p di, const char *field, const char *string)
235 {
236   dump_maybe_newline (di);
237   fprintf (di->stream, "%-4s: %-7s ", field, string);
238   if (strlen (string) > 7)
239     di->column += 6 + strlen (string) + 1;
240   else
241     di->column += 14;
242 }
243
244 /* Dump the next node in the queue.  */
245
246 static void
247 dequeue_and_dump (dump_info_p di)
248 {
249   dump_queue_p dq;
250   splay_tree_node stn;
251   dump_node_info_p dni;
252   tree t;
253   unsigned int index;
254   enum tree_code code;
255   enum tree_code_class code_class;
256   const char* code_name;
257
258   /* Get the next node from the queue.  */
259   dq = di->queue;
260   stn = dq->node;
261   t = (tree) stn->key;
262   dni = (dump_node_info_p) stn->value;
263   index = dni->index;
264
265   /* Remove the node from the queue, and put it on the free list.  */
266   di->queue = dq->next;
267   if (!di->queue)
268     di->queue_end = 0;
269   dq->next = di->free_list;
270   di->free_list = dq;
271
272   /* Print the node index.  */
273   dump_index (di, index);
274   /* And the type of node this is.  */
275   if (dni->binfo_p)
276     code_name = "binfo";
277   else
278     code_name = get_tree_code_name (TREE_CODE (t));
279   fprintf (di->stream, "%-16s ", code_name);
280   di->column = 25;
281
282   /* Figure out what kind of node this is.  */
283   code = TREE_CODE (t);
284   code_class = TREE_CODE_CLASS (code);
285
286   /* Although BINFOs are TREE_VECs, we dump them specially so as to be
287      more informative.  */
288   if (dni->binfo_p)
289     {
290       unsigned ix;
291       tree base;
292       vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (t);
293
294       dump_child ("type", BINFO_TYPE (t));
295
296       if (BINFO_VIRTUAL_P (t))
297         dump_string_field (di, "spec", "virt");
298
299       dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
300       for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
301         {
302           tree access = (accesses ? (*accesses)[ix] : access_public_node);
303           const char *string = NULL;
304
305           if (access == access_public_node)
306             string = "pub";
307           else if (access == access_protected_node)
308             string = "prot";
309           else if (access == access_private_node)
310             string = "priv";
311           else
312             gcc_unreachable ();
313
314           dump_string_field (di, "accs", string);
315           queue_and_dump_index (di, "binf", base, DUMP_BINFO);
316         }
317
318       goto done;
319     }
320
321   /* We can knock off a bunch of expression nodes in exactly the same
322      way.  */
323   if (IS_EXPR_CODE_CLASS (code_class))
324     {
325       /* If we're dumping children, dump them now.  */
326       queue_and_dump_type (di, t);
327
328       switch (code_class)
329         {
330         case tcc_unary:
331           dump_child ("op 0", TREE_OPERAND (t, 0));
332           break;
333
334         case tcc_binary:
335         case tcc_comparison:
336           dump_child ("op 0", TREE_OPERAND (t, 0));
337           dump_child ("op 1", TREE_OPERAND (t, 1));
338           break;
339
340         case tcc_expression:
341         case tcc_reference:
342         case tcc_statement:
343         case tcc_vl_exp:
344           /* These nodes are handled explicitly below.  */
345           break;
346
347         default:
348           gcc_unreachable ();
349         }
350     }
351   else if (DECL_P (t))
352     {
353       expanded_location xloc;
354       /* All declarations have names.  */
355       if (DECL_NAME (t))
356         dump_child ("name", DECL_NAME (t));
357       if (DECL_ASSEMBLER_NAME_SET_P (t)
358           && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
359         dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
360       if (DECL_ABSTRACT_ORIGIN (t))
361         dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
362       /* And types.  */
363       queue_and_dump_type (di, t);
364       dump_child ("scpe", DECL_CONTEXT (t));
365       /* And a source position.  */
366       xloc = expand_location (DECL_SOURCE_LOCATION (t));
367       if (xloc.file)
368         {
369           const char *filename = lbasename (xloc.file);
370
371           dump_maybe_newline (di);
372           fprintf (di->stream, "srcp: %s:%-6d ", filename,
373                    xloc.line);
374           di->column += 6 + strlen (filename) + 8;
375         }
376       /* And any declaration can be compiler-generated.  */
377       if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
378           && DECL_ARTIFICIAL (t))
379         dump_string_field (di, "note", "artificial");
380       if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
381         dump_child ("chain", DECL_CHAIN (t));
382     }
383   else if (code_class == tcc_type)
384     {
385       /* All types have qualifiers.  */
386       int quals = lang_hooks.tree_dump.type_quals (t);
387
388       if (quals != TYPE_UNQUALIFIED)
389         {
390           fprintf (di->stream, "qual: %c%c%c     ",
391                    (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
392                    (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
393                    (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
394           di->column += 14;
395         }
396
397       /* All types have associated declarations.  */
398       dump_child ("name", TYPE_NAME (t));
399
400       /* All types have a main variant.  */
401       if (TYPE_MAIN_VARIANT (t) != t)
402         dump_child ("unql", TYPE_MAIN_VARIANT (t));
403
404       /* And sizes.  */
405       dump_child ("size", TYPE_SIZE (t));
406
407       /* All types have alignments.  */
408       dump_int (di, "algn", TYPE_ALIGN (t));
409     }
410   else if (code_class == tcc_constant)
411     /* All constants can have types.  */
412     queue_and_dump_type (di, t);
413
414   /* Give the language-specific code a chance to print something.  If
415      it's completely taken care of things, don't bother printing
416      anything more ourselves.  */
417   if (lang_hooks.tree_dump.dump_tree (di, t))
418     goto done;
419
420   /* Now handle the various kinds of nodes.  */
421   switch (code)
422     {
423       int i;
424
425     case IDENTIFIER_NODE:
426       dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
427       dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
428       break;
429
430     case TREE_LIST:
431       dump_child ("purp", TREE_PURPOSE (t));
432       dump_child ("valu", TREE_VALUE (t));
433       dump_child ("chan", TREE_CHAIN (t));
434       break;
435
436     case STATEMENT_LIST:
437       {
438         tree_stmt_iterator it;
439         for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
440           {
441             char buffer[32];
442             sprintf (buffer, "%u", i);
443             dump_child (buffer, tsi_stmt (it));
444           }
445       }
446       break;
447
448     case TREE_VEC:
449       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
450       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
451         {
452           char buffer[32];
453           sprintf (buffer, "%u", i);
454           dump_child (buffer, TREE_VEC_ELT (t, i));
455         }
456       break;
457
458     case INTEGER_TYPE:
459     case ENUMERAL_TYPE:
460       dump_int (di, "prec", TYPE_PRECISION (t));
461       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
462       dump_child ("min", TYPE_MIN_VALUE (t));
463       dump_child ("max", TYPE_MAX_VALUE (t));
464
465       if (code == ENUMERAL_TYPE)
466         dump_child ("csts", TYPE_VALUES (t));
467       break;
468
469     case REAL_TYPE:
470       dump_int (di, "prec", TYPE_PRECISION (t));
471       break;
472
473     case FIXED_POINT_TYPE:
474       dump_int (di, "prec", TYPE_PRECISION (t));
475       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
476       dump_string_field (di, "saturating",
477                          TYPE_SATURATING (t) ? "saturating": "non-saturating");
478       break;
479
480     case POINTER_TYPE:
481       dump_child ("ptd", TREE_TYPE (t));
482       break;
483
484     case REFERENCE_TYPE:
485       dump_child ("refd", TREE_TYPE (t));
486       break;
487
488     case METHOD_TYPE:
489       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
490       /* Fall through.  */
491
492     case FUNCTION_TYPE:
493       dump_child ("retn", TREE_TYPE (t));
494       dump_child ("prms", TYPE_ARG_TYPES (t));
495       break;
496
497     case ARRAY_TYPE:
498       dump_child ("elts", TREE_TYPE (t));
499       dump_child ("domn", TYPE_DOMAIN (t));
500       break;
501
502     case RECORD_TYPE:
503     case UNION_TYPE:
504       if (TREE_CODE (t) == RECORD_TYPE)
505         dump_string_field (di, "tag", "struct");
506       else
507         dump_string_field (di, "tag", "union");
508
509       dump_child ("flds", TYPE_FIELDS (t));
510       dump_child ("fncs", TYPE_METHODS (t));
511       queue_and_dump_index (di, "binf", TYPE_BINFO (t),
512                             DUMP_BINFO);
513       break;
514
515     case CONST_DECL:
516       dump_child ("cnst", DECL_INITIAL (t));
517       break;
518
519     case DEBUG_EXPR_DECL:
520       dump_int (di, "-uid", DEBUG_TEMP_UID (t));
521       /* Fall through.  */
522
523     case VAR_DECL:
524     case PARM_DECL:
525     case FIELD_DECL:
526     case RESULT_DECL:
527       if (TREE_CODE (t) == PARM_DECL)
528         dump_child ("argt", DECL_ARG_TYPE (t));
529       else
530         dump_child ("init", DECL_INITIAL (t));
531       dump_child ("size", DECL_SIZE (t));
532       dump_int (di, "algn", DECL_ALIGN (t));
533
534       if (TREE_CODE (t) == FIELD_DECL)
535         {
536           if (DECL_FIELD_OFFSET (t))
537             dump_child ("bpos", bit_position (t));
538         }
539       else if (TREE_CODE (t) == VAR_DECL
540                || TREE_CODE (t) == PARM_DECL)
541         {
542           dump_int (di, "used", TREE_USED (t));
543           if (DECL_REGISTER (t))
544             dump_string_field (di, "spec", "register");
545         }
546       break;
547
548     case FUNCTION_DECL:
549       dump_child ("args", DECL_ARGUMENTS (t));
550       if (DECL_EXTERNAL (t))
551         dump_string_field (di, "body", "undefined");
552       if (TREE_PUBLIC (t))
553         dump_string_field (di, "link", "extern");
554       else
555         dump_string_field (di, "link", "static");
556       if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
557         dump_child ("body", DECL_SAVED_TREE (t));
558       break;
559
560     case INTEGER_CST:
561       fprintf (di->stream, "int: ");
562       print_decs (t, di->stream);
563       break;
564
565     case STRING_CST:
566       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
567       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
568       break;
569
570     case REAL_CST:
571       dump_real (di, "valu", TREE_REAL_CST_PTR (t));
572       break;
573
574     case FIXED_CST:
575       dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
576       break;
577
578     case TRUTH_NOT_EXPR:
579     case ADDR_EXPR:
580     case INDIRECT_REF:
581     case CLEANUP_POINT_EXPR:
582     case SAVE_EXPR:
583     case REALPART_EXPR:
584     case IMAGPART_EXPR:
585       /* These nodes are unary, but do not have code class `1'.  */
586       dump_child ("op 0", TREE_OPERAND (t, 0));
587       break;
588
589     case TRUTH_ANDIF_EXPR:
590     case TRUTH_ORIF_EXPR:
591     case INIT_EXPR:
592     case MODIFY_EXPR:
593     case COMPOUND_EXPR:
594     case PREDECREMENT_EXPR:
595     case PREINCREMENT_EXPR:
596     case POSTDECREMENT_EXPR:
597     case POSTINCREMENT_EXPR:
598       /* These nodes are binary, but do not have code class `2'.  */
599       dump_child ("op 0", TREE_OPERAND (t, 0));
600       dump_child ("op 1", TREE_OPERAND (t, 1));
601       break;
602
603     case COMPONENT_REF:
604     case BIT_FIELD_REF:
605       dump_child ("op 0", TREE_OPERAND (t, 0));
606       dump_child ("op 1", TREE_OPERAND (t, 1));
607       dump_child ("op 2", TREE_OPERAND (t, 2));
608       break;
609
610     case ARRAY_REF:
611     case ARRAY_RANGE_REF:
612       dump_child ("op 0", TREE_OPERAND (t, 0));
613       dump_child ("op 1", TREE_OPERAND (t, 1));
614       dump_child ("op 2", TREE_OPERAND (t, 2));
615       dump_child ("op 3", TREE_OPERAND (t, 3));
616       break;
617
618     case COND_EXPR:
619       dump_child ("op 0", TREE_OPERAND (t, 0));
620       dump_child ("op 1", TREE_OPERAND (t, 1));
621       dump_child ("op 2", TREE_OPERAND (t, 2));
622       break;
623
624     case TRY_FINALLY_EXPR:
625       dump_child ("op 0", TREE_OPERAND (t, 0));
626       dump_child ("op 1", TREE_OPERAND (t, 1));
627       break;
628
629     case CALL_EXPR:
630       {
631         int i = 0;
632         tree arg;
633         call_expr_arg_iterator iter;
634         dump_child ("fn", CALL_EXPR_FN (t));
635         FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
636           {
637             char buffer[32];
638             sprintf (buffer, "%u", i);
639             dump_child (buffer, arg);
640             i++;
641           }
642       }
643       break;
644
645     case CONSTRUCTOR:
646       {
647         unsigned HOST_WIDE_INT cnt;
648         tree index, value;
649         dump_int (di, "lngt", vec_safe_length (CONSTRUCTOR_ELTS (t)));
650         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
651           {
652             dump_child ("idx", index);
653             dump_child ("val", value);
654           }
655       }
656       break;
657
658     case BIND_EXPR:
659       dump_child ("vars", TREE_OPERAND (t, 0));
660       dump_child ("body", TREE_OPERAND (t, 1));
661       break;
662
663     case LOOP_EXPR:
664       dump_child ("body", TREE_OPERAND (t, 0));
665       break;
666
667     case EXIT_EXPR:
668       dump_child ("cond", TREE_OPERAND (t, 0));
669       break;
670
671     case RETURN_EXPR:
672       dump_child ("expr", TREE_OPERAND (t, 0));
673       break;
674
675     case TARGET_EXPR:
676       dump_child ("decl", TREE_OPERAND (t, 0));
677       dump_child ("init", TREE_OPERAND (t, 1));
678       dump_child ("clnp", TREE_OPERAND (t, 2));
679       /* There really are two possible places the initializer can be.
680          After RTL expansion, the second operand is moved to the
681          position of the fourth operand, and the second operand
682          becomes NULL.  */
683       dump_child ("init", TREE_OPERAND (t, 3));
684       break;
685
686     case CASE_LABEL_EXPR:
687       dump_child ("name", CASE_LABEL (t));
688       if (CASE_LOW (t))
689         {
690           dump_child ("low ", CASE_LOW (t));
691           if (CASE_HIGH (t))
692             dump_child ("high", CASE_HIGH (t));
693         }
694       break;
695     case LABEL_EXPR:
696       dump_child ("name", TREE_OPERAND (t,0));
697       break;
698     case GOTO_EXPR:
699       dump_child ("labl", TREE_OPERAND (t, 0));
700       break;
701     case SWITCH_EXPR:
702       dump_child ("cond", TREE_OPERAND (t, 0));
703       dump_child ("body", TREE_OPERAND (t, 1));
704       if (TREE_OPERAND (t, 2))
705         {
706           dump_child ("labl", TREE_OPERAND (t,2));
707         }
708       break;
709     case OMP_CLAUSE:
710       {
711         int i;
712         fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
713         for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
714           dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
715       }
716       break;
717     default:
718       /* There are no additional fields to print.  */
719       break;
720     }
721
722  done:
723   if (dump_flag (di, TDF_ADDRESS, NULL))
724     dump_pointer (di, "addr", (void *)t);
725
726   /* Terminate the line.  */
727   fprintf (di->stream, "\n");
728 }
729
730 /* Return nonzero if FLAG has been specified for the dump, and NODE
731    is not the root node of the dump.  */
732
733 int dump_flag (dump_info_p di, int flag, const_tree node)
734 {
735   return (di->flags & flag) && (node != di->node);
736 }
737
738 /* Dump T, and all its children, on STREAM.  */
739
740 void
741 dump_node (const_tree t, int flags, FILE *stream)
742 {
743   struct dump_info di;
744   dump_queue_p dq;
745   dump_queue_p next_dq;
746
747   /* Initialize the dump-information structure.  */
748   di.stream = stream;
749   di.index = 0;
750   di.column = 0;
751   di.queue = 0;
752   di.queue_end = 0;
753   di.free_list = 0;
754   di.flags = flags;
755   di.node = t;
756   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
757                              (splay_tree_delete_value_fn) &free);
758
759   /* Queue up the first node.  */
760   queue (&di, t, DUMP_NONE);
761
762   /* Until the queue is empty, keep dumping nodes.  */
763   while (di.queue)
764     dequeue_and_dump (&di);
765
766   /* Now, clean up.  */
767   for (dq = di.free_list; dq; dq = next_dq)
768     {
769       next_dq = dq->next;
770       free (dq);
771     }
772   splay_tree_delete (di.nodes);
773 }