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