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
queue(dump_info_p di,const_tree t,int flags)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
dump_index(dump_info_p di,unsigned int index)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
queue_and_dump_index(dump_info_p di,const char * field,const_tree t,int flags)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
queue_and_dump_type(dump_info_p di,const_tree t)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
dump_new_line(dump_info_p di)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
dump_maybe_newline(dump_info_p di)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
dump_function(int phase,tree fn)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
dump_pointer(dump_info_p di,const char * field,void * ptr)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
dump_int(dump_info_p di,const char * field,int i)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
dump_real(dump_info_p di,const char * field,const REAL_VALUE_TYPE * r)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
dump_fixed(dump_info_p di,const char * field,const FIXED_VALUE_TYPE * f)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
dump_string(dump_info_p di,const char * string)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
dump_string_field(dump_info_p di,const char * field,const char * string)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
dequeue_and_dump(dump_info_p di)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 
dump_flag(dump_info_p di,int flag,const_tree node)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
dump_node(const_tree t,int flags,FILE * stream)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 }
774