xref: /dragonfly/contrib/gcc-8.0/gcc/tree-dump.c (revision 5fb3968e)
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       break;
687     case OMP_CLAUSE:
688       {
689 	int i;
690 	fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
691 	for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
692 	  dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
693       }
694       break;
695     default:
696       /* There are no additional fields to print.  */
697       break;
698     }
699 
700  done:
701   if (dump_flag (di, TDF_ADDRESS, NULL))
702     dump_pointer (di, "addr", (void *)t);
703 
704   /* Terminate the line.  */
705   fprintf (di->stream, "\n");
706 }
707 
708 /* Return nonzero if FLAG has been specified for the dump, and NODE
709    is not the root node of the dump.  */
710 
711 int dump_flag (dump_info_p di, dump_flags_t flag, const_tree node)
712 {
713   return (di->flags & flag) && (node != di->node);
714 }
715 
716 /* Dump T, and all its children, on STREAM.  */
717 
718 void
719 dump_node (const_tree t, dump_flags_t flags, FILE *stream)
720 {
721   struct dump_info di;
722   dump_queue_p dq;
723   dump_queue_p next_dq;
724 
725   /* Initialize the dump-information structure.  */
726   di.stream = stream;
727   di.index = 0;
728   di.column = 0;
729   di.queue = 0;
730   di.queue_end = 0;
731   di.free_list = 0;
732   di.flags = flags;
733   di.node = t;
734   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
735 			     (splay_tree_delete_value_fn)
736 			     (void (*) (void)) free);
737 
738   /* Queue up the first node.  */
739   queue (&di, t, DUMP_NONE);
740 
741   /* Until the queue is empty, keep dumping nodes.  */
742   while (di.queue)
743     dequeue_and_dump (&di);
744 
745   /* Now, clean up.  */
746   for (dq = di.free_list; dq; dq = next_dq)
747     {
748       next_dq = dq->next;
749       free (dq);
750     }
751   splay_tree_delete (di.nodes);
752 }
753