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