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