xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-dump.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999-2017 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 (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
540 	{
541 	  dump_int (di, "used", TREE_USED (t));
542 	  if (DECL_REGISTER (t))
543 	    dump_string_field (di, "spec", "register");
544 	}
545       break;
546 
547     case FUNCTION_DECL:
548       dump_child ("args", DECL_ARGUMENTS (t));
549       if (DECL_EXTERNAL (t))
550 	dump_string_field (di, "body", "undefined");
551       if (TREE_PUBLIC (t))
552 	dump_string_field (di, "link", "extern");
553       else
554 	dump_string_field (di, "link", "static");
555       if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
556 	dump_child ("body", DECL_SAVED_TREE (t));
557       break;
558 
559     case INTEGER_CST:
560       fprintf (di->stream, "int: ");
561       print_decs (t, di->stream);
562       break;
563 
564     case STRING_CST:
565       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
566       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
567       break;
568 
569     case REAL_CST:
570       dump_real (di, "valu", TREE_REAL_CST_PTR (t));
571       break;
572 
573     case FIXED_CST:
574       dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
575       break;
576 
577     case TRUTH_NOT_EXPR:
578     case ADDR_EXPR:
579     case INDIRECT_REF:
580     case CLEANUP_POINT_EXPR:
581     case SAVE_EXPR:
582     case REALPART_EXPR:
583     case IMAGPART_EXPR:
584       /* These nodes are unary, but do not have code class `1'.  */
585       dump_child ("op 0", TREE_OPERAND (t, 0));
586       break;
587 
588     case TRUTH_ANDIF_EXPR:
589     case TRUTH_ORIF_EXPR:
590     case INIT_EXPR:
591     case MODIFY_EXPR:
592     case COMPOUND_EXPR:
593     case PREDECREMENT_EXPR:
594     case PREINCREMENT_EXPR:
595     case POSTDECREMENT_EXPR:
596     case POSTINCREMENT_EXPR:
597       /* These nodes are binary, but do not have code class `2'.  */
598       dump_child ("op 0", TREE_OPERAND (t, 0));
599       dump_child ("op 1", TREE_OPERAND (t, 1));
600       break;
601 
602     case COMPONENT_REF:
603     case BIT_FIELD_REF:
604       dump_child ("op 0", TREE_OPERAND (t, 0));
605       dump_child ("op 1", TREE_OPERAND (t, 1));
606       dump_child ("op 2", TREE_OPERAND (t, 2));
607       break;
608 
609     case ARRAY_REF:
610     case ARRAY_RANGE_REF:
611       dump_child ("op 0", TREE_OPERAND (t, 0));
612       dump_child ("op 1", TREE_OPERAND (t, 1));
613       dump_child ("op 2", TREE_OPERAND (t, 2));
614       dump_child ("op 3", TREE_OPERAND (t, 3));
615       break;
616 
617     case COND_EXPR:
618       dump_child ("op 0", TREE_OPERAND (t, 0));
619       dump_child ("op 1", TREE_OPERAND (t, 1));
620       dump_child ("op 2", TREE_OPERAND (t, 2));
621       break;
622 
623     case TRY_FINALLY_EXPR:
624       dump_child ("op 0", TREE_OPERAND (t, 0));
625       dump_child ("op 1", TREE_OPERAND (t, 1));
626       break;
627 
628     case CALL_EXPR:
629       {
630 	int i = 0;
631 	tree arg;
632 	call_expr_arg_iterator iter;
633 	dump_child ("fn", CALL_EXPR_FN (t));
634 	FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
635 	  {
636 	    char buffer[32];
637 	    sprintf (buffer, "%u", i);
638 	    dump_child (buffer, arg);
639 	    i++;
640 	  }
641       }
642       break;
643 
644     case CONSTRUCTOR:
645       {
646 	unsigned HOST_WIDE_INT cnt;
647 	tree index, value;
648 	dump_int (di, "lngt", CONSTRUCTOR_NELTS (t));
649 	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
650 	  {
651 	    dump_child ("idx", index);
652 	    dump_child ("val", value);
653 	  }
654       }
655       break;
656 
657     case BIND_EXPR:
658       dump_child ("vars", TREE_OPERAND (t, 0));
659       dump_child ("body", TREE_OPERAND (t, 1));
660       break;
661 
662     case LOOP_EXPR:
663       dump_child ("body", TREE_OPERAND (t, 0));
664       break;
665 
666     case EXIT_EXPR:
667       dump_child ("cond", TREE_OPERAND (t, 0));
668       break;
669 
670     case RETURN_EXPR:
671       dump_child ("expr", TREE_OPERAND (t, 0));
672       break;
673 
674     case TARGET_EXPR:
675       dump_child ("decl", TREE_OPERAND (t, 0));
676       dump_child ("init", TREE_OPERAND (t, 1));
677       dump_child ("clnp", TREE_OPERAND (t, 2));
678       /* There really are two possible places the initializer can be.
679 	 After RTL expansion, the second operand is moved to the
680 	 position of the fourth operand, and the second operand
681 	 becomes NULL.  */
682       dump_child ("init", TREE_OPERAND (t, 3));
683       break;
684 
685     case CASE_LABEL_EXPR:
686       dump_child ("name", CASE_LABEL (t));
687       if (CASE_LOW (t))
688 	{
689 	  dump_child ("low ", CASE_LOW (t));
690 	  if (CASE_HIGH (t))
691 	    dump_child ("high", CASE_HIGH (t));
692 	}
693       break;
694     case LABEL_EXPR:
695       dump_child ("name", TREE_OPERAND (t,0));
696       break;
697     case GOTO_EXPR:
698       dump_child ("labl", TREE_OPERAND (t, 0));
699       break;
700     case SWITCH_EXPR:
701       dump_child ("cond", TREE_OPERAND (t, 0));
702       dump_child ("body", TREE_OPERAND (t, 1));
703       if (TREE_OPERAND (t, 2))
704         {
705       	  dump_child ("labl", TREE_OPERAND (t,2));
706         }
707       break;
708     case OMP_CLAUSE:
709       {
710 	int i;
711 	fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
712 	for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
713 	  dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
714       }
715       break;
716     default:
717       /* There are no additional fields to print.  */
718       break;
719     }
720 
721  done:
722   if (dump_flag (di, TDF_ADDRESS, NULL))
723     dump_pointer (di, "addr", (void *)t);
724 
725   /* Terminate the line.  */
726   fprintf (di->stream, "\n");
727 }
728 
729 /* Return nonzero if FLAG has been specified for the dump, and NODE
730    is not the root node of the dump.  */
731 
732 int dump_flag (dump_info_p di, int flag, const_tree node)
733 {
734   return (di->flags & flag) && (node != di->node);
735 }
736 
737 /* Dump T, and all its children, on STREAM.  */
738 
739 void
740 dump_node (const_tree t, int flags, FILE *stream)
741 {
742   struct dump_info di;
743   dump_queue_p dq;
744   dump_queue_p next_dq;
745 
746   /* Initialize the dump-information structure.  */
747   di.stream = stream;
748   di.index = 0;
749   di.column = 0;
750   di.queue = 0;
751   di.queue_end = 0;
752   di.free_list = 0;
753   di.flags = flags;
754   di.node = t;
755   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
756 			     (splay_tree_delete_value_fn) &free);
757 
758   /* Queue up the first node.  */
759   queue (&di, t, DUMP_NONE);
760 
761   /* Until the queue is empty, keep dumping nodes.  */
762   while (di.queue)
763     dequeue_and_dump (&di);
764 
765   /* Now, clean up.  */
766   for (dq = di.free_list; dq; dq = next_dq)
767     {
768       next_dq = dq->next;
769       free (dq);
770     }
771   splay_tree_delete (di.nodes);
772 }
773