xref: /dragonfly/contrib/gcc-4.7/gcc/tree-dump.c (revision 0ca59c34)
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3    2010, 2011 Free Software Foundation, Inc.
4    Written by Mark Mitchell <mark@codesourcery.com>
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "splay-tree.h"
28 #include "filenames.h"
29 #include "diagnostic-core.h"
30 #include "toplev.h"
31 #include "tree-dump.h"
32 #include "tree-pass.h"
33 #include "langhooks.h"
34 #include "tree-iterator.h"
35 
36 /* If non-NULL, return one past-the-end of the matching SUBPART of
37    the WHOLE string.  */
38 #define skip_leading_substring(whole,  part) \
39    (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
40 
41 static unsigned int queue (dump_info_p, const_tree, int);
42 static void dump_index (dump_info_p, unsigned int);
43 static void dequeue_and_dump (dump_info_p);
44 static void dump_new_line (dump_info_p);
45 static void dump_maybe_newline (dump_info_p);
46 
47 /* Add T to the end of the queue of nodes to dump.  Returns the index
48    assigned to T.  */
49 
50 static unsigned int
51 queue (dump_info_p di, const_tree t, int flags)
52 {
53   dump_queue_p dq;
54   dump_node_info_p dni;
55   unsigned int index;
56 
57   /* Assign the next available index to T.  */
58   index = ++di->index;
59 
60   /* Obtain a new queue node.  */
61   if (di->free_list)
62     {
63       dq = di->free_list;
64       di->free_list = dq->next;
65     }
66   else
67     dq = XNEW (struct dump_queue);
68 
69   /* Create a new entry in the splay-tree.  */
70   dni = XNEW (struct dump_node_info);
71   dni->index = index;
72   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
73   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
74 				(splay_tree_value) dni);
75 
76   /* Add it to the end of the queue.  */
77   dq->next = 0;
78   if (!di->queue_end)
79     di->queue = dq;
80   else
81     di->queue_end->next = dq;
82   di->queue_end = dq;
83 
84   /* Return the index.  */
85   return index;
86 }
87 
88 static void
89 dump_index (dump_info_p di, unsigned int index)
90 {
91   fprintf (di->stream, "@%-6u ", index);
92   di->column += 8;
93 }
94 
95 /* If T has not already been output, queue it for subsequent output.
96    FIELD is a string to print before printing the index.  Then, the
97    index of T is printed.  */
98 
99 void
100 queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
101 {
102   unsigned int index;
103   splay_tree_node n;
104 
105   /* If there's no node, just return.  This makes for fewer checks in
106      our callers.  */
107   if (!t)
108     return;
109 
110   /* See if we've already queued or dumped this node.  */
111   n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
112   if (n)
113     index = ((dump_node_info_p) n->value)->index;
114   else
115     /* If we haven't, add it to the queue.  */
116     index = queue (di, t, flags);
117 
118   /* Print the index of the node.  */
119   dump_maybe_newline (di);
120   fprintf (di->stream, "%-4s: ", field);
121   di->column += 6;
122   dump_index (di, index);
123 }
124 
125 /* Dump the type of T.  */
126 
127 void
128 queue_and_dump_type (dump_info_p di, const_tree t)
129 {
130   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
131 }
132 
133 /* Dump column control */
134 #define SOL_COLUMN 25		/* Start of line column.  */
135 #define EOL_COLUMN 55		/* End of line column.  */
136 #define COLUMN_ALIGNMENT 15	/* Alignment.  */
137 
138 /* Insert a new line in the dump output, and indent to an appropriate
139    place to start printing more fields.  */
140 
141 static void
142 dump_new_line (dump_info_p di)
143 {
144   fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
145   di->column = SOL_COLUMN;
146 }
147 
148 /* If necessary, insert a new line.  */
149 
150 static void
151 dump_maybe_newline (dump_info_p di)
152 {
153   int extra;
154 
155   /* See if we need a new line.  */
156   if (di->column > EOL_COLUMN)
157     dump_new_line (di);
158   /* See if we need any padding.  */
159   else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
160     {
161       fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
162       di->column += COLUMN_ALIGNMENT - extra;
163     }
164 }
165 
166 /* Dump pointer PTR using FIELD to identify it.  */
167 
168 void
169 dump_pointer (dump_info_p di, const char *field, void *ptr)
170 {
171   dump_maybe_newline (di);
172   fprintf (di->stream, "%-4s: %-8" HOST_WIDE_INT_PRINT "x ", field,
173 	   (unsigned HOST_WIDE_INT) (uintptr_t) ptr);
174   di->column += 15;
175 }
176 
177 /* Dump integer I using FIELD to identify it.  */
178 
179 void
180 dump_int (dump_info_p di, const char *field, int i)
181 {
182   dump_maybe_newline (di);
183   fprintf (di->stream, "%-4s: %-7d ", field, i);
184   di->column += 14;
185 }
186 
187 /* Dump the floating point value R, using FIELD to identify it.  */
188 
189 static void
190 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
191 {
192   char buf[32];
193   real_to_decimal (buf, r, sizeof (buf), 0, true);
194   dump_maybe_newline (di);
195   fprintf (di->stream, "%-4s: %s ", field, buf);
196   di->column += strlen (buf) + 7;
197 }
198 
199 /* Dump the fixed-point value F, using FIELD to identify it.  */
200 
201 static void
202 dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
203 {
204   char buf[32];
205   fixed_to_decimal (buf, f, sizeof (buf));
206   dump_maybe_newline (di);
207   fprintf (di->stream, "%-4s: %s ", field, buf);
208   di->column += strlen (buf) + 7;
209 }
210 
211 
212 /* Dump the string S.  */
213 
214 void
215 dump_string (dump_info_p di, const char *string)
216 {
217   dump_maybe_newline (di);
218   fprintf (di->stream, "%-13s ", string);
219   if (strlen (string) > 13)
220     di->column += strlen (string) + 1;
221   else
222     di->column += 14;
223 }
224 
225 /* Dump the string field S.  */
226 
227 void
228 dump_string_field (dump_info_p di, const char *field, const char *string)
229 {
230   dump_maybe_newline (di);
231   fprintf (di->stream, "%-4s: %-7s ", field, string);
232   if (strlen (string) > 7)
233     di->column += 6 + strlen (string) + 1;
234   else
235     di->column += 14;
236 }
237 
238 /* Dump the next node in the queue.  */
239 
240 static void
241 dequeue_and_dump (dump_info_p di)
242 {
243   dump_queue_p dq;
244   splay_tree_node stn;
245   dump_node_info_p dni;
246   tree t;
247   unsigned int index;
248   enum tree_code code;
249   enum tree_code_class code_class;
250   const char* code_name;
251 
252   /* Get the next node from the queue.  */
253   dq = di->queue;
254   stn = dq->node;
255   t = (tree) stn->key;
256   dni = (dump_node_info_p) stn->value;
257   index = dni->index;
258 
259   /* Remove the node from the queue, and put it on the free list.  */
260   di->queue = dq->next;
261   if (!di->queue)
262     di->queue_end = 0;
263   dq->next = di->free_list;
264   di->free_list = dq;
265 
266   /* Print the node index.  */
267   dump_index (di, index);
268   /* And the type of node this is.  */
269   if (dni->binfo_p)
270     code_name = "binfo";
271   else
272     code_name = tree_code_name[(int) TREE_CODE (t)];
273   fprintf (di->stream, "%-16s ", code_name);
274   di->column = 25;
275 
276   /* Figure out what kind of node this is.  */
277   code = TREE_CODE (t);
278   code_class = TREE_CODE_CLASS (code);
279 
280   /* Although BINFOs are TREE_VECs, we dump them specially so as to be
281      more informative.  */
282   if (dni->binfo_p)
283     {
284       unsigned ix;
285       tree base;
286       VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
287 
288       dump_child ("type", BINFO_TYPE (t));
289 
290       if (BINFO_VIRTUAL_P (t))
291 	dump_string_field (di, "spec", "virt");
292 
293       dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
294       for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
295 	{
296 	  tree access = (accesses ? VEC_index (tree, accesses, ix)
297 			 : access_public_node);
298 	  const char *string = NULL;
299 
300 	  if (access == access_public_node)
301 	    string = "pub";
302 	  else if (access == access_protected_node)
303 	    string = "prot";
304 	  else if (access == access_private_node)
305 	    string = "priv";
306 	  else
307 	    gcc_unreachable ();
308 
309 	  dump_string_field (di, "accs", string);
310 	  queue_and_dump_index (di, "binf", base, DUMP_BINFO);
311 	}
312 
313       goto done;
314     }
315 
316   /* We can knock off a bunch of expression nodes in exactly the same
317      way.  */
318   if (IS_EXPR_CODE_CLASS (code_class))
319     {
320       /* If we're dumping children, dump them now.  */
321       queue_and_dump_type (di, t);
322 
323       switch (code_class)
324 	{
325 	case tcc_unary:
326 	  dump_child ("op 0", TREE_OPERAND (t, 0));
327 	  break;
328 
329 	case tcc_binary:
330 	case tcc_comparison:
331 	  dump_child ("op 0", TREE_OPERAND (t, 0));
332 	  dump_child ("op 1", TREE_OPERAND (t, 1));
333 	  break;
334 
335 	case tcc_expression:
336 	case tcc_reference:
337 	case tcc_statement:
338 	case tcc_vl_exp:
339 	  /* These nodes are handled explicitly below.  */
340 	  break;
341 
342 	default:
343 	  gcc_unreachable ();
344 	}
345     }
346   else if (DECL_P (t))
347     {
348       expanded_location xloc;
349       /* All declarations have names.  */
350       if (DECL_NAME (t))
351 	dump_child ("name", DECL_NAME (t));
352       if (DECL_ASSEMBLER_NAME_SET_P (t)
353 	  && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
354 	dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
355       if (DECL_ABSTRACT_ORIGIN (t))
356         dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
357       /* And types.  */
358       queue_and_dump_type (di, t);
359       dump_child ("scpe", DECL_CONTEXT (t));
360       /* And a source position.  */
361       xloc = expand_location (DECL_SOURCE_LOCATION (t));
362       if (xloc.file)
363 	{
364 	  const char *filename = lbasename (xloc.file);
365 
366 	  dump_maybe_newline (di);
367 	  fprintf (di->stream, "srcp: %s:%-6d ", filename,
368 		   xloc.line);
369 	  di->column += 6 + strlen (filename) + 8;
370 	}
371       /* And any declaration can be compiler-generated.  */
372       if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
373 	  && DECL_ARTIFICIAL (t))
374 	dump_string_field (di, "note", "artificial");
375       if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
376 	dump_child ("chain", DECL_CHAIN (t));
377     }
378   else if (code_class == tcc_type)
379     {
380       /* All types have qualifiers.  */
381       int quals = lang_hooks.tree_dump.type_quals (t);
382 
383       if (quals != TYPE_UNQUALIFIED)
384 	{
385 	  fprintf (di->stream, "qual: %c%c%c     ",
386 		   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
387 		   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
388 		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
389 	  di->column += 14;
390 	}
391 
392       /* All types have associated declarations.  */
393       dump_child ("name", TYPE_NAME (t));
394 
395       /* All types have a main variant.  */
396       if (TYPE_MAIN_VARIANT (t) != t)
397 	dump_child ("unql", TYPE_MAIN_VARIANT (t));
398 
399       /* And sizes.  */
400       dump_child ("size", TYPE_SIZE (t));
401 
402       /* All types have alignments.  */
403       dump_int (di, "algn", TYPE_ALIGN (t));
404     }
405   else if (code_class == tcc_constant)
406     /* All constants can have types.  */
407     queue_and_dump_type (di, t);
408 
409   /* Give the language-specific code a chance to print something.  If
410      it's completely taken care of things, don't bother printing
411      anything more ourselves.  */
412   if (lang_hooks.tree_dump.dump_tree (di, t))
413     goto done;
414 
415   /* Now handle the various kinds of nodes.  */
416   switch (code)
417     {
418       int i;
419 
420     case IDENTIFIER_NODE:
421       dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
422       dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
423       break;
424 
425     case TREE_LIST:
426       dump_child ("purp", TREE_PURPOSE (t));
427       dump_child ("valu", TREE_VALUE (t));
428       dump_child ("chan", TREE_CHAIN (t));
429       break;
430 
431     case STATEMENT_LIST:
432       {
433 	tree_stmt_iterator it;
434 	for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
435 	  {
436 	    char buffer[32];
437 	    sprintf (buffer, "%u", i);
438 	    dump_child (buffer, tsi_stmt (it));
439 	  }
440       }
441       break;
442 
443     case TREE_VEC:
444       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
445       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
446 	{
447 	  char buffer[32];
448 	  sprintf (buffer, "%u", i);
449 	  dump_child (buffer, TREE_VEC_ELT (t, i));
450 	}
451       break;
452 
453     case INTEGER_TYPE:
454     case ENUMERAL_TYPE:
455       dump_int (di, "prec", TYPE_PRECISION (t));
456       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
457       dump_child ("min", TYPE_MIN_VALUE (t));
458       dump_child ("max", TYPE_MAX_VALUE (t));
459 
460       if (code == ENUMERAL_TYPE)
461 	dump_child ("csts", TYPE_VALUES (t));
462       break;
463 
464     case REAL_TYPE:
465       dump_int (di, "prec", TYPE_PRECISION (t));
466       break;
467 
468     case FIXED_POINT_TYPE:
469       dump_int (di, "prec", TYPE_PRECISION (t));
470       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
471       dump_string_field (di, "saturating",
472 			 TYPE_SATURATING (t) ? "saturating": "non-saturating");
473       break;
474 
475     case POINTER_TYPE:
476       dump_child ("ptd", TREE_TYPE (t));
477       break;
478 
479     case REFERENCE_TYPE:
480       dump_child ("refd", TREE_TYPE (t));
481       break;
482 
483     case METHOD_TYPE:
484       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
485       /* Fall through.  */
486 
487     case FUNCTION_TYPE:
488       dump_child ("retn", TREE_TYPE (t));
489       dump_child ("prms", TYPE_ARG_TYPES (t));
490       break;
491 
492     case ARRAY_TYPE:
493       dump_child ("elts", TREE_TYPE (t));
494       dump_child ("domn", TYPE_DOMAIN (t));
495       break;
496 
497     case RECORD_TYPE:
498     case UNION_TYPE:
499       if (TREE_CODE (t) == RECORD_TYPE)
500 	dump_string_field (di, "tag", "struct");
501       else
502 	dump_string_field (di, "tag", "union");
503 
504       dump_child ("flds", TYPE_FIELDS (t));
505       dump_child ("fncs", TYPE_METHODS (t));
506       queue_and_dump_index (di, "binf", TYPE_BINFO (t),
507 			    DUMP_BINFO);
508       break;
509 
510     case CONST_DECL:
511       dump_child ("cnst", DECL_INITIAL (t));
512       break;
513 
514     case DEBUG_EXPR_DECL:
515       dump_int (di, "-uid", DEBUG_TEMP_UID (t));
516       /* Fall through.  */
517 
518     case VAR_DECL:
519     case PARM_DECL:
520     case FIELD_DECL:
521     case RESULT_DECL:
522       if (TREE_CODE (t) == PARM_DECL)
523 	dump_child ("argt", DECL_ARG_TYPE (t));
524       else
525 	dump_child ("init", DECL_INITIAL (t));
526       dump_child ("size", DECL_SIZE (t));
527       dump_int (di, "algn", DECL_ALIGN (t));
528 
529       if (TREE_CODE (t) == FIELD_DECL)
530 	{
531 	  if (DECL_FIELD_OFFSET (t))
532 	    dump_child ("bpos", bit_position (t));
533 	}
534       else if (TREE_CODE (t) == VAR_DECL
535 	       || TREE_CODE (t) == PARM_DECL)
536 	{
537 	  dump_int (di, "used", TREE_USED (t));
538 	  if (DECL_REGISTER (t))
539 	    dump_string_field (di, "spec", "register");
540 	}
541       break;
542 
543     case FUNCTION_DECL:
544       dump_child ("args", DECL_ARGUMENTS (t));
545       if (DECL_EXTERNAL (t))
546 	dump_string_field (di, "body", "undefined");
547       if (TREE_PUBLIC (t))
548 	dump_string_field (di, "link", "extern");
549       else
550 	dump_string_field (di, "link", "static");
551       if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
552 	dump_child ("body", DECL_SAVED_TREE (t));
553       break;
554 
555     case INTEGER_CST:
556       if (TREE_INT_CST_HIGH (t))
557 	dump_int (di, "high", TREE_INT_CST_HIGH (t));
558       dump_int (di, "low", TREE_INT_CST_LOW (t));
559       break;
560 
561     case STRING_CST:
562       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
563       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
564       break;
565 
566     case REAL_CST:
567       dump_real (di, "valu", TREE_REAL_CST_PTR (t));
568       break;
569 
570     case FIXED_CST:
571       dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
572       break;
573 
574     case TRUTH_NOT_EXPR:
575     case ADDR_EXPR:
576     case INDIRECT_REF:
577     case CLEANUP_POINT_EXPR:
578     case SAVE_EXPR:
579     case REALPART_EXPR:
580     case IMAGPART_EXPR:
581       /* These nodes are unary, but do not have code class `1'.  */
582       dump_child ("op 0", TREE_OPERAND (t, 0));
583       break;
584 
585     case TRUTH_ANDIF_EXPR:
586     case TRUTH_ORIF_EXPR:
587     case INIT_EXPR:
588     case MODIFY_EXPR:
589     case COMPOUND_EXPR:
590     case PREDECREMENT_EXPR:
591     case PREINCREMENT_EXPR:
592     case POSTDECREMENT_EXPR:
593     case POSTINCREMENT_EXPR:
594       /* These nodes are binary, but do not have code class `2'.  */
595       dump_child ("op 0", TREE_OPERAND (t, 0));
596       dump_child ("op 1", TREE_OPERAND (t, 1));
597       break;
598 
599     case COMPONENT_REF:
600       dump_child ("op 0", TREE_OPERAND (t, 0));
601       dump_child ("op 1", TREE_OPERAND (t, 1));
602       dump_child ("op 2", TREE_OPERAND (t, 2));
603       break;
604 
605     case ARRAY_REF:
606     case ARRAY_RANGE_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       dump_child ("op 3", TREE_OPERAND (t, 3));
611       break;
612 
613     case COND_EXPR:
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       break;
618 
619     case TRY_FINALLY_EXPR:
620       dump_child ("op 0", TREE_OPERAND (t, 0));
621       dump_child ("op 1", TREE_OPERAND (t, 1));
622       break;
623 
624     case CALL_EXPR:
625       {
626 	int i = 0;
627 	tree arg;
628 	call_expr_arg_iterator iter;
629 	dump_child ("fn", CALL_EXPR_FN (t));
630 	FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
631 	  {
632 	    char buffer[32];
633 	    sprintf (buffer, "%u", i);
634 	    dump_child (buffer, arg);
635 	    i++;
636 	  }
637       }
638       break;
639 
640     case CONSTRUCTOR:
641       {
642 	unsigned HOST_WIDE_INT cnt;
643 	tree index, value;
644 	dump_int (di, "lngt", VEC_length (constructor_elt,
645 					  CONSTRUCTOR_ELTS (t)));
646 	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
647 	  {
648 	    dump_child ("idx", index);
649 	    dump_child ("val", value);
650 	  }
651       }
652       break;
653 
654     case BIND_EXPR:
655       dump_child ("vars", TREE_OPERAND (t, 0));
656       dump_child ("body", TREE_OPERAND (t, 1));
657       break;
658 
659     case LOOP_EXPR:
660       dump_child ("body", TREE_OPERAND (t, 0));
661       break;
662 
663     case EXIT_EXPR:
664       dump_child ("cond", TREE_OPERAND (t, 0));
665       break;
666 
667     case RETURN_EXPR:
668       dump_child ("expr", TREE_OPERAND (t, 0));
669       break;
670 
671     case TARGET_EXPR:
672       dump_child ("decl", TREE_OPERAND (t, 0));
673       dump_child ("init", TREE_OPERAND (t, 1));
674       dump_child ("clnp", TREE_OPERAND (t, 2));
675       /* There really are two possible places the initializer can be.
676 	 After RTL expansion, the second operand is moved to the
677 	 position of the fourth operand, and the second operand
678 	 becomes NULL.  */
679       dump_child ("init", TREE_OPERAND (t, 3));
680       break;
681 
682     case CASE_LABEL_EXPR:
683       dump_child ("name", CASE_LABEL (t));
684       if (CASE_LOW (t))
685 	{
686 	  dump_child ("low ", CASE_LOW (t));
687 	  if (CASE_HIGH (t))
688 	    dump_child ("high", CASE_HIGH (t));
689 	}
690       break;
691     case LABEL_EXPR:
692       dump_child ("name", TREE_OPERAND (t,0));
693       break;
694     case GOTO_EXPR:
695       dump_child ("labl", TREE_OPERAND (t, 0));
696       break;
697     case SWITCH_EXPR:
698       dump_child ("cond", TREE_OPERAND (t, 0));
699       dump_child ("body", TREE_OPERAND (t, 1));
700       if (TREE_OPERAND (t, 2))
701         {
702       	  dump_child ("labl", TREE_OPERAND (t,2));
703         }
704       break;
705     case OMP_CLAUSE:
706       {
707 	int i;
708 	fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
709 	for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
710 	  dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
711       }
712       break;
713     default:
714       /* There are no additional fields to print.  */
715       break;
716     }
717 
718  done:
719   if (dump_flag (di, TDF_ADDRESS, NULL))
720     dump_pointer (di, "addr", (void *)t);
721 
722   /* Terminate the line.  */
723   fprintf (di->stream, "\n");
724 }
725 
726 /* Return nonzero if FLAG has been specified for the dump, and NODE
727    is not the root node of the dump.  */
728 
729 int dump_flag (dump_info_p di, int flag, const_tree node)
730 {
731   return (di->flags & flag) && (node != di->node);
732 }
733 
734 /* Dump T, and all its children, on STREAM.  */
735 
736 void
737 dump_node (const_tree t, int flags, FILE *stream)
738 {
739   struct dump_info di;
740   dump_queue_p dq;
741   dump_queue_p next_dq;
742 
743   /* Initialize the dump-information structure.  */
744   di.stream = stream;
745   di.index = 0;
746   di.column = 0;
747   di.queue = 0;
748   di.queue_end = 0;
749   di.free_list = 0;
750   di.flags = flags;
751   di.node = t;
752   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
753 			     (splay_tree_delete_value_fn) &free);
754 
755   /* Queue up the first node.  */
756   queue (&di, t, DUMP_NONE);
757 
758   /* Until the queue is empty, keep dumping nodes.  */
759   while (di.queue)
760     dequeue_and_dump (&di);
761 
762   /* Now, clean up.  */
763   for (dq = di.free_list; dq; dq = next_dq)
764     {
765       next_dq = dq->next;
766       free (dq);
767     }
768   splay_tree_delete (di.nodes);
769 }
770 
771 
772 /* Table of tree dump switches. This must be consistent with the
773    tree_dump_index enumeration in tree-pass.h.  */
774 static struct dump_file_info dump_files[TDI_end] =
775 {
776   {NULL, NULL, NULL, 0, 0, 0},
777   {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
778   {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
779   {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
780   {".original", "tree-original", NULL, TDF_TREE, 0, 3},
781   {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
782   {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
783   {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
784   {".ads", "ada-spec", NULL, 0, 0, 7},
785 #define FIRST_AUTO_NUMBERED_DUMP 8
786 
787   {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
788   {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
789   {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
790 };
791 
792 /* Dynamically registered tree dump files and switches.  */
793 static struct dump_file_info *extra_dump_files;
794 static size_t extra_dump_files_in_use;
795 static size_t extra_dump_files_alloced;
796 
797 /* Define a name->number mapping for a dump flag value.  */
798 struct dump_option_value_info
799 {
800   const char *const name;	/* the name of the value */
801   const int value;		/* the value of the name */
802 };
803 
804 /* Table of dump options. This must be consistent with the TDF_* flags
805    in tree.h */
806 static const struct dump_option_value_info dump_options[] =
807 {
808   {"address", TDF_ADDRESS},
809   {"asmname", TDF_ASMNAME},
810   {"slim", TDF_SLIM},
811   {"raw", TDF_RAW},
812   {"graph", TDF_GRAPH},
813   {"details", TDF_DETAILS},
814   {"cselib", TDF_CSELIB},
815   {"stats", TDF_STATS},
816   {"blocks", TDF_BLOCKS},
817   {"vops", TDF_VOPS},
818   {"lineno", TDF_LINENO},
819   {"uid", TDF_UID},
820   {"stmtaddr", TDF_STMTADDR},
821   {"memsyms", TDF_MEMSYMS},
822   {"verbose", TDF_VERBOSE},
823   {"eh", TDF_EH},
824   {"alias", TDF_ALIAS},
825   {"nouid", TDF_NOUID},
826   {"enumerate_locals", TDF_ENUMERATE_LOCALS},
827   {"scev", TDF_SCEV},
828   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
829 	    | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
830 	    | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
831   {NULL, 0}
832 };
833 
834 unsigned int
835 dump_register (const char *suffix, const char *swtch, const char *glob,
836 	       int flags)
837 {
838   static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
839   int num = next_dump++;
840 
841   size_t count = extra_dump_files_in_use++;
842 
843   if (count >= extra_dump_files_alloced)
844     {
845       if (extra_dump_files_alloced == 0)
846 	extra_dump_files_alloced = 32;
847       else
848 	extra_dump_files_alloced *= 2;
849       extra_dump_files = XRESIZEVEC (struct dump_file_info,
850 				     extra_dump_files,
851 				     extra_dump_files_alloced);
852     }
853 
854   memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
855   extra_dump_files[count].suffix = suffix;
856   extra_dump_files[count].swtch = swtch;
857   extra_dump_files[count].glob = glob;
858   extra_dump_files[count].flags = flags;
859   extra_dump_files[count].num = num;
860 
861   return count + TDI_end;
862 }
863 
864 
865 /* Return the dump_file_info for the given phase.  */
866 
867 struct dump_file_info *
868 get_dump_file_info (int phase)
869 {
870   if (phase < TDI_end)
871     return &dump_files[phase];
872   else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
873     return NULL;
874   else
875     return extra_dump_files + (phase - TDI_end);
876 }
877 
878 
879 /* Return the name of the dump file for the given phase.
880    If the dump is not enabled, returns NULL.  */
881 
882 char *
883 get_dump_file_name (int phase)
884 {
885   char dump_id[10];
886   struct dump_file_info *dfi;
887 
888   if (phase == TDI_none)
889     return NULL;
890 
891   dfi = get_dump_file_info (phase);
892   if (dfi->state == 0)
893     return NULL;
894 
895   if (dfi->num < 0)
896     dump_id[0] = '\0';
897   else
898     {
899       char suffix;
900       if (dfi->flags & TDF_TREE)
901 	suffix = 't';
902       else if (dfi->flags & TDF_IPA)
903 	suffix = 'i';
904       else
905 	suffix = 'r';
906 
907       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
908 	dump_id[0] = '\0';
909     }
910 
911   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
912 }
913 
914 /* Begin a tree dump for PHASE. Stores any user supplied flag in
915    *FLAG_PTR and returns a stream to write to. If the dump is not
916    enabled, returns NULL.
917    Multiple calls will reopen and append to the dump file.  */
918 
919 FILE *
920 dump_begin (int phase, int *flag_ptr)
921 {
922   char *name;
923   struct dump_file_info *dfi;
924   FILE *stream;
925 
926   if (phase == TDI_none || !dump_enabled_p (phase))
927     return NULL;
928 
929   name = get_dump_file_name (phase);
930   dfi = get_dump_file_info (phase);
931   stream = fopen (name, dfi->state < 0 ? "w" : "a");
932   if (!stream)
933     error ("could not open dump file %qs: %m", name);
934   else
935     dfi->state = 1;
936   free (name);
937 
938   if (flag_ptr)
939     *flag_ptr = dfi->flags;
940 
941   return stream;
942 }
943 
944 /* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
945    TDI_tree_all, return nonzero if any dump is enabled.  */
946 
947 int
948 dump_enabled_p (int phase)
949 {
950   if (phase == TDI_tree_all)
951     {
952       size_t i;
953       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
954 	if (dump_files[i].state)
955 	  return 1;
956       for (i = 0; i < extra_dump_files_in_use; i++)
957 	if (extra_dump_files[i].state)
958 	  return 1;
959       return 0;
960     }
961   else
962     {
963       struct dump_file_info *dfi = get_dump_file_info (phase);
964       return dfi->state;
965     }
966 }
967 
968 /* Returns nonzero if tree dump PHASE has been initialized.  */
969 
970 int
971 dump_initialized_p (int phase)
972 {
973   struct dump_file_info *dfi = get_dump_file_info (phase);
974   return dfi->state > 0;
975 }
976 
977 /* Returns the switch name of PHASE.  */
978 
979 const char *
980 dump_flag_name (int phase)
981 {
982   struct dump_file_info *dfi = get_dump_file_info (phase);
983   return dfi->swtch;
984 }
985 
986 /* Finish a tree dump for PHASE. STREAM is the stream created by
987    dump_begin.  */
988 
989 void
990 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
991 {
992   fclose (stream);
993 }
994 
995 /* Enable all tree dumps.  Return number of enabled tree dumps.  */
996 
997 static int
998 dump_enable_all (int flags)
999 {
1000   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
1001   int n = 0;
1002   size_t i;
1003 
1004   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1005     if ((dump_files[i].flags & ir_dump_type))
1006       {
1007         dump_files[i].state = -1;
1008         dump_files[i].flags |= flags;
1009         n++;
1010       }
1011 
1012   for (i = 0; i < extra_dump_files_in_use; i++)
1013     if ((extra_dump_files[i].flags & ir_dump_type))
1014       {
1015         extra_dump_files[i].state = -1;
1016         extra_dump_files[i].flags |= flags;
1017 	n++;
1018       }
1019 
1020   return n;
1021 }
1022 
1023 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1024    relevant details in the dump_files array.  */
1025 
1026 static int
1027 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1028 {
1029   const char *option_value;
1030   const char *ptr;
1031   int flags;
1032 
1033   if (doglob && !dfi->glob)
1034     return 0;
1035 
1036   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1037   if (!option_value)
1038     return 0;
1039 
1040   if (*option_value && *option_value != '-')
1041     return 0;
1042 
1043   ptr = option_value;
1044   flags = 0;
1045 
1046   while (*ptr)
1047     {
1048       const struct dump_option_value_info *option_ptr;
1049       const char *end_ptr;
1050       unsigned length;
1051 
1052       while (*ptr == '-')
1053 	ptr++;
1054       end_ptr = strchr (ptr, '-');
1055       if (!end_ptr)
1056 	end_ptr = ptr + strlen (ptr);
1057       length = end_ptr - ptr;
1058 
1059       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1060 	if (strlen (option_ptr->name) == length
1061 	    && !memcmp (option_ptr->name, ptr, length))
1062 	  {
1063 	    flags |= option_ptr->value;
1064 	    goto found;
1065 	  }
1066       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1067 	       length, ptr, dfi->swtch);
1068     found:;
1069       ptr = end_ptr;
1070     }
1071 
1072   dfi->state = -1;
1073   dfi->flags |= flags;
1074 
1075   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1076      known dumps.  */
1077   if (dfi->suffix == NULL)
1078     dump_enable_all (dfi->flags);
1079 
1080   return 1;
1081 }
1082 
1083 int
1084 dump_switch_p (const char *arg)
1085 {
1086   size_t i;
1087   int any = 0;
1088 
1089   for (i = TDI_none + 1; i != TDI_end; i++)
1090     any |= dump_switch_p_1 (arg, &dump_files[i], false);
1091 
1092   /* Don't glob if we got a hit already */
1093   if (!any)
1094     for (i = TDI_none + 1; i != TDI_end; i++)
1095       any |= dump_switch_p_1 (arg, &dump_files[i], true);
1096 
1097   for (i = 0; i < extra_dump_files_in_use; i++)
1098     any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1099 
1100   if (!any)
1101     for (i = 0; i < extra_dump_files_in_use; i++)
1102       any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1103 
1104 
1105   return any;
1106 }
1107 
1108 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1109 
1110 void
1111 dump_function (int phase, tree fn)
1112 {
1113   FILE *stream;
1114   int flags;
1115 
1116   stream = dump_begin (phase, &flags);
1117   if (stream)
1118     {
1119       dump_function_to_file (fn, stream, flags);
1120       dump_end (phase, stream);
1121     }
1122 }
1123 
1124 bool
1125 enable_rtl_dump_file (void)
1126 {
1127   return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
1128 }
1129