OSDN Git Service

config/
[pf3gnuchains/gcc-fork.git] / gcc / tree-dump.c
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007
3    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 "diagnostic.h"
29 #include "toplev.h"
30 #include "tree-dump.h"
31 #include "tree-pass.h"
32 #include "langhooks.h"
33 #include "tree-iterator.h"
34 #include "real.h"
35 #include "fixed-value.h"
36
37 static unsigned int queue (dump_info_p, const_tree, int);
38 static void dump_index (dump_info_p, unsigned int);
39 static void dequeue_and_dump (dump_info_p);
40 static void dump_new_line (dump_info_p);
41 static void dump_maybe_newline (dump_info_p);
42 static int dump_enable_all (int, int);
43
44 /* Add T to the end of the queue of nodes to dump.  Returns the index
45    assigned to T.  */
46
47 static unsigned int
48 queue (dump_info_p di, const_tree t, int flags)
49 {
50   dump_queue_p dq;
51   dump_node_info_p dni;
52   unsigned int index;
53
54   /* Assign the next available index to T.  */
55   index = ++di->index;
56
57   /* Obtain a new queue node.  */
58   if (di->free_list)
59     {
60       dq = di->free_list;
61       di->free_list = dq->next;
62     }
63   else
64     dq = XNEW (struct dump_queue);
65
66   /* Create a new entry in the splay-tree.  */
67   dni = XNEW (struct dump_node_info);
68   dni->index = index;
69   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
70   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
71                                 (splay_tree_value) dni);
72
73   /* Add it to the end of the queue.  */
74   dq->next = 0;
75   if (!di->queue_end)
76     di->queue = dq;
77   else
78     di->queue_end->next = dq;
79   di->queue_end = dq;
80
81   /* Return the index.  */
82   return index;
83 }
84
85 static void
86 dump_index (dump_info_p di, unsigned int index)
87 {
88   fprintf (di->stream, "@%-6u ", index);
89   di->column += 8;
90 }
91
92 /* If T has not already been output, queue it for subsequent output.
93    FIELD is a string to print before printing the index.  Then, the
94    index of T is printed.  */
95
96 void
97 queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
98 {
99   unsigned int index;
100   splay_tree_node n;
101
102   /* If there's no node, just return.  This makes for fewer checks in
103      our callers.  */
104   if (!t)
105     return;
106
107   /* See if we've already queued or dumped this node.  */
108   n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
109   if (n)
110     index = ((dump_node_info_p) n->value)->index;
111   else
112     /* If we haven't, add it to the queue.  */
113     index = queue (di, t, flags);
114
115   /* Print the index of the node.  */
116   dump_maybe_newline (di);
117   fprintf (di->stream, "%-4s: ", field);
118   di->column += 6;
119   dump_index (di, index);
120 }
121
122 /* Dump the type of T.  */
123
124 void
125 queue_and_dump_type (dump_info_p di, const_tree t)
126 {
127   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
128 }
129
130 /* Dump column control */
131 #define SOL_COLUMN 25           /* Start of line column.  */
132 #define EOL_COLUMN 55           /* End of line column.  */
133 #define COLUMN_ALIGNMENT 15     /* Alignment.  */
134
135 /* Insert a new line in the dump output, and indent to an appropriate
136    place to start printing more fields.  */
137
138 static void
139 dump_new_line (dump_info_p di)
140 {
141   fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
142   di->column = SOL_COLUMN;
143 }
144
145 /* If necessary, insert a new line.  */
146
147 static void
148 dump_maybe_newline (dump_info_p di)
149 {
150   int extra;
151
152   /* See if we need a new line.  */
153   if (di->column > EOL_COLUMN)
154     dump_new_line (di);
155   /* See if we need any padding.  */
156   else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
157     {
158       fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
159       di->column += COLUMN_ALIGNMENT - extra;
160     }
161 }
162
163 /* Dump pointer PTR using FIELD to identify it.  */
164
165 void
166 dump_pointer (dump_info_p di, const char *field, void *ptr)
167 {
168   dump_maybe_newline (di);
169   fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr);
170   di->column += 15;
171 }
172
173 /* Dump integer I using FIELD to identify it.  */
174
175 void
176 dump_int (dump_info_p di, const char *field, int i)
177 {
178   dump_maybe_newline (di);
179   fprintf (di->stream, "%-4s: %-7d ", field, i);
180   di->column += 14;
181 }
182
183 /* Dump the floating point value R, using FIELD to identify it.  */
184
185 static void
186 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
187 {
188   char buf[32];
189   real_to_decimal (buf, r, sizeof (buf), 0, true);
190   dump_maybe_newline (di);
191   fprintf (di->stream, "%-4s: %s ", field, buf);
192   di->column += strlen (buf) + 7;
193 }
194
195 /* Dump the fixed-point value F, using FIELD to identify it.  */
196
197 static void
198 dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
199 {
200   char buf[32];
201   fixed_to_decimal (buf, f, sizeof (buf));
202   dump_maybe_newline (di);
203   fprintf (di->stream, "%-4s: %s ", field, buf);
204   di->column += strlen (buf) + 7;
205 }
206
207
208 /* Dump the string S.  */
209
210 void
211 dump_string (dump_info_p di, const char *string)
212 {
213   dump_maybe_newline (di);
214   fprintf (di->stream, "%-13s ", string);
215   if (strlen (string) > 13)
216     di->column += strlen (string) + 1;
217   else
218     di->column += 14;
219 }
220
221 /* Dump the string field S.  */
222
223 void
224 dump_string_field (dump_info_p di, const char *field, const char *string)
225 {
226   dump_maybe_newline (di);
227   fprintf (di->stream, "%-4s: %-7s ", field, string);
228   if (strlen (string) > 7)
229     di->column += 6 + strlen (string) + 1;
230   else
231     di->column += 14;
232 }
233
234 /* Dump the next node in the queue.  */
235
236 static void
237 dequeue_and_dump (dump_info_p di)
238 {
239   dump_queue_p dq;
240   splay_tree_node stn;
241   dump_node_info_p dni;
242   tree t;
243   unsigned int index;
244   enum tree_code code;
245   enum tree_code_class code_class;
246   const char* code_name;
247
248   /* Get the next node from the queue.  */
249   dq = di->queue;
250   stn = dq->node;
251   t = (tree) stn->key;
252   dni = (dump_node_info_p) stn->value;
253   index = dni->index;
254
255   /* Remove the node from the queue, and put it on the free list.  */
256   di->queue = dq->next;
257   if (!di->queue)
258     di->queue_end = 0;
259   dq->next = di->free_list;
260   di->free_list = dq;
261
262   /* Print the node index.  */
263   dump_index (di, index);
264   /* And the type of node this is.  */
265   if (dni->binfo_p)
266     code_name = "binfo";
267   else
268     code_name = tree_code_name[(int) TREE_CODE (t)];
269   fprintf (di->stream, "%-16s ", code_name);
270   di->column = 25;
271
272   /* Figure out what kind of node this is.  */
273   code = TREE_CODE (t);
274   code_class = TREE_CODE_CLASS (code);
275
276   /* Although BINFOs are TREE_VECs, we dump them specially so as to be
277      more informative.  */
278   if (dni->binfo_p)
279     {
280       unsigned ix;
281       tree base;
282       VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
283
284       dump_child ("type", BINFO_TYPE (t));
285
286       if (BINFO_VIRTUAL_P (t))
287         dump_string_field (di, "spec", "virt");
288
289       dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
290       for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
291         {
292           tree access = (accesses ? VEC_index (tree, accesses, ix)
293                          : access_public_node);
294           const char *string = NULL;
295
296           if (access == access_public_node)
297             string = "pub";
298           else if (access == access_protected_node)
299             string = "prot";
300           else if (access == access_private_node)
301             string = "priv";
302           else
303             gcc_unreachable ();
304
305           dump_string_field (di, "accs", string);
306           queue_and_dump_index (di, "binf", base, DUMP_BINFO);
307         }
308
309       goto done;
310     }
311
312   /* We can knock off a bunch of expression nodes in exactly the same
313      way.  */
314   if (IS_EXPR_CODE_CLASS (code_class))
315     {
316       /* If we're dumping children, dump them now.  */
317       queue_and_dump_type (di, t);
318
319       switch (code_class)
320         {
321         case tcc_unary:
322           dump_child ("op 0", TREE_OPERAND (t, 0));
323           break;
324
325         case tcc_binary:
326         case tcc_comparison:
327           dump_child ("op 0", TREE_OPERAND (t, 0));
328           dump_child ("op 1", TREE_OPERAND (t, 1));
329           break;
330
331         case tcc_expression:
332         case tcc_reference:
333         case tcc_statement:
334         case tcc_vl_exp:
335           /* These nodes are handled explicitly below.  */
336           break;
337
338         default:
339           gcc_unreachable ();
340         }
341     }
342   else if (DECL_P (t))
343     {
344       expanded_location xloc;
345       /* All declarations have names.  */
346       if (DECL_NAME (t))
347         dump_child ("name", DECL_NAME (t));
348       if (DECL_ASSEMBLER_NAME_SET_P (t)
349           && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
350         dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
351       if (DECL_ABSTRACT_ORIGIN (t))
352         dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
353       /* And types.  */
354       queue_and_dump_type (di, t);
355       dump_child ("scpe", DECL_CONTEXT (t));
356       /* And a source position.  */
357       xloc = expand_location (DECL_SOURCE_LOCATION (t));
358       if (xloc.file)
359         {
360           const char *filename = strrchr (xloc.file, '/');
361           if (!filename)
362             filename = xloc.file;
363           else
364             /* Skip the slash.  */
365             ++filename;
366
367           dump_maybe_newline (di);
368           fprintf (di->stream, "srcp: %s:%-6d ", filename,
369                    xloc.line);
370           di->column += 6 + strlen (filename) + 8;
371         }
372       /* And any declaration can be compiler-generated.  */
373       if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
374           && DECL_ARTIFICIAL (t))
375         dump_string_field (di, "note", "artificial");
376       if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
377         dump_child ("chan", TREE_CHAIN (t));
378     }
379   else if (code_class == tcc_type)
380     {
381       /* All types have qualifiers.  */
382       int quals = lang_hooks.tree_dump.type_quals (t);
383
384       if (quals != TYPE_UNQUALIFIED)
385         {
386           fprintf (di->stream, "qual: %c%c%c     ",
387                    (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
388                    (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
389                    (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
390           di->column += 14;
391         }
392
393       /* All types have associated declarations.  */
394       dump_child ("name", TYPE_NAME (t));
395
396       /* All types have a main variant.  */
397       if (TYPE_MAIN_VARIANT (t) != t)
398         dump_child ("unql", TYPE_MAIN_VARIANT (t));
399
400       /* And sizes.  */
401       dump_child ("size", TYPE_SIZE (t));
402
403       /* All types have alignments.  */
404       dump_int (di, "algn", TYPE_ALIGN (t));
405     }
406   else if (code_class == tcc_constant)
407     /* All constants can have types.  */
408     queue_and_dump_type (di, t);
409
410   /* Give the language-specific code a chance to print something.  If
411      it's completely taken care of things, don't bother printing
412      anything more ourselves.  */
413   if (lang_hooks.tree_dump.dump_tree (di, t))
414     goto done;
415
416   /* Now handle the various kinds of nodes.  */
417   switch (code)
418     {
419       int i;
420
421     case IDENTIFIER_NODE:
422       dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
423       dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
424       break;
425
426     case TREE_LIST:
427       dump_child ("purp", TREE_PURPOSE (t));
428       dump_child ("valu", TREE_VALUE (t));
429       dump_child ("chan", TREE_CHAIN (t));
430       break;
431
432     case STATEMENT_LIST:
433       {
434         tree_stmt_iterator it;
435         for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
436           {
437             char buffer[32];
438             sprintf (buffer, "%u", i);
439             dump_child (buffer, tsi_stmt (it));
440           }
441       }
442       break;
443
444     case TREE_VEC:
445       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
446       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
447         {
448           char buffer[32];
449           sprintf (buffer, "%u", i);
450           dump_child (buffer, TREE_VEC_ELT (t, i));
451         }
452       break;
453
454     case INTEGER_TYPE:
455     case ENUMERAL_TYPE:
456       dump_int (di, "prec", TYPE_PRECISION (t));
457       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
458       dump_child ("min", TYPE_MIN_VALUE (t));
459       dump_child ("max", TYPE_MAX_VALUE (t));
460
461       if (code == ENUMERAL_TYPE)
462         dump_child ("csts", TYPE_VALUES (t));
463       break;
464
465     case REAL_TYPE:
466       dump_int (di, "prec", TYPE_PRECISION (t));
467       break;
468
469     case FIXED_POINT_TYPE:
470       dump_int (di, "prec", TYPE_PRECISION (t));
471       dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
472       dump_string_field (di, "saturating",
473                          TYPE_SATURATING (t) ? "saturating": "non-saturating");
474       break;
475
476     case POINTER_TYPE:
477       dump_child ("ptd", TREE_TYPE (t));
478       break;
479
480     case REFERENCE_TYPE:
481       dump_child ("refd", TREE_TYPE (t));
482       break;
483
484     case METHOD_TYPE:
485       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
486       /* Fall through.  */
487
488     case FUNCTION_TYPE:
489       dump_child ("retn", TREE_TYPE (t));
490       dump_child ("prms", TYPE_ARG_TYPES (t));
491       break;
492
493     case ARRAY_TYPE:
494       dump_child ("elts", TREE_TYPE (t));
495       dump_child ("domn", TYPE_DOMAIN (t));
496       break;
497
498     case RECORD_TYPE:
499     case UNION_TYPE:
500       if (TREE_CODE (t) == RECORD_TYPE)
501         dump_string_field (di, "tag", "struct");
502       else
503         dump_string_field (di, "tag", "union");
504
505       dump_child ("flds", TYPE_FIELDS (t));
506       dump_child ("fncs", TYPE_METHODS (t));
507       queue_and_dump_index (di, "binf", TYPE_BINFO (t),
508                             DUMP_BINFO);
509       break;
510
511     case CONST_DECL:
512       dump_child ("cnst", DECL_INITIAL (t));
513       break;
514       
515     case SYMBOL_MEMORY_TAG:
516     case NAME_MEMORY_TAG:
517     case STRUCT_FIELD_TAG:
518       break;
519
520     case VAR_DECL:
521     case PARM_DECL:
522     case FIELD_DECL:
523     case RESULT_DECL:
524       if (TREE_CODE (t) == PARM_DECL)
525         dump_child ("argt", DECL_ARG_TYPE (t));
526       else
527         dump_child ("init", DECL_INITIAL (t));
528       dump_child ("size", DECL_SIZE (t));
529       dump_int (di, "algn", DECL_ALIGN (t));
530
531       if (TREE_CODE (t) == FIELD_DECL)
532         {
533           if (DECL_FIELD_OFFSET (t))
534             dump_child ("bpos", bit_position (t));
535         }
536       else if (TREE_CODE (t) == VAR_DECL
537                || TREE_CODE (t) == PARM_DECL)
538         {
539           dump_int (di, "used", TREE_USED (t));
540           if (DECL_REGISTER (t))
541             dump_string_field (di, "spec", "register");
542         }
543       break;
544
545     case FUNCTION_DECL:
546       dump_child ("args", DECL_ARGUMENTS (t));
547       if (DECL_EXTERNAL (t))
548         dump_string_field (di, "body", "undefined");
549       if (TREE_PUBLIC (t))
550         dump_string_field (di, "link", "extern");
551       else
552         dump_string_field (di, "link", "static");
553       if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
554         dump_child ("body", DECL_SAVED_TREE (t));
555       break;
556
557     case INTEGER_CST:
558       if (TREE_INT_CST_HIGH (t))
559         dump_int (di, "high", TREE_INT_CST_HIGH (t));
560       dump_int (di, "low", TREE_INT_CST_LOW (t));
561       break;
562
563     case STRING_CST:
564       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
565       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
566       break;
567
568     case REAL_CST:
569       dump_real (di, "valu", TREE_REAL_CST_PTR (t));
570       break;
571
572     case FIXED_CST:
573       dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
574       break;
575
576     case TRUTH_NOT_EXPR:
577     case ADDR_EXPR:
578     case INDIRECT_REF:
579     case ALIGN_INDIRECT_REF:
580     case MISALIGNED_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 GIMPLE_MODIFY_STMT:
604       dump_child ("op 0", GIMPLE_STMT_OPERAND (t, 0));
605       dump_child ("op 1", GIMPLE_STMT_OPERAND (t, 1));
606       break;
607
608     case COMPONENT_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_length (constructor_elt,
654                                           CONSTRUCTOR_ELTS (t)));
655         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
656           {
657             dump_child ("idx", index);
658             dump_child ("val", value);
659           }
660       }
661       break;
662
663     case BIND_EXPR:
664       dump_child ("vars", TREE_OPERAND (t, 0));
665       dump_child ("body", TREE_OPERAND (t, 1));
666       break;
667
668     case LOOP_EXPR:
669       dump_child ("body", TREE_OPERAND (t, 0));
670       break;
671
672     case EXIT_EXPR:
673       dump_child ("cond", TREE_OPERAND (t, 0));
674       break;
675
676     case RETURN_EXPR:
677       dump_child ("expr", TREE_OPERAND (t, 0));
678       break;
679
680     case TARGET_EXPR:
681       dump_child ("decl", TREE_OPERAND (t, 0));
682       dump_child ("init", TREE_OPERAND (t, 1));
683       dump_child ("clnp", TREE_OPERAND (t, 2));
684       /* There really are two possible places the initializer can be.
685          After RTL expansion, the second operand is moved to the
686          position of the fourth operand, and the second operand
687          becomes NULL.  */
688       dump_child ("init", TREE_OPERAND (t, 3));
689       break;
690
691     case CASE_LABEL_EXPR:
692       dump_child ("name", CASE_LABEL (t));
693       if (CASE_LOW (t))
694         {
695           dump_child ("low ", CASE_LOW (t));
696           if (CASE_HIGH (t))
697             dump_child ("high", CASE_HIGH (t));
698         }
699       break;
700     case LABEL_EXPR:
701       dump_child ("name", TREE_OPERAND (t,0));
702       break;
703     case GOTO_EXPR:
704       dump_child ("labl", TREE_OPERAND (t, 0));
705       break;
706     case SWITCH_EXPR:
707       dump_child ("cond", TREE_OPERAND (t, 0));
708       dump_child ("body", TREE_OPERAND (t, 1));
709       if (TREE_OPERAND (t, 2))
710         {
711           dump_child ("labl", TREE_OPERAND (t,2));
712         }
713       break;
714     case OMP_CLAUSE:
715       {
716         int i;
717         fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
718         for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
719           dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
720       }
721       break;
722     default:
723       /* There are no additional fields to print.  */
724       break;
725     }
726
727  done:
728   if (dump_flag (di, TDF_ADDRESS, NULL))
729     dump_pointer (di, "addr", (void *)t);
730
731   /* Terminate the line.  */
732   fprintf (di->stream, "\n");
733 }
734
735 /* Return nonzero if FLAG has been specified for the dump, and NODE
736    is not the root node of the dump.  */
737
738 int dump_flag (dump_info_p di, int flag, const_tree node)
739 {
740   return (di->flags & flag) && (node != di->node);
741 }
742
743 /* Dump T, and all its children, on STREAM.  */
744
745 void
746 dump_node (const_tree t, int flags, FILE *stream)
747 {
748   struct dump_info di;
749   dump_queue_p dq;
750   dump_queue_p next_dq;
751
752   /* Initialize the dump-information structure.  */
753   di.stream = stream;
754   di.index = 0;
755   di.column = 0;
756   di.queue = 0;
757   di.queue_end = 0;
758   di.free_list = 0;
759   di.flags = flags;
760   di.node = t;
761   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
762                              (splay_tree_delete_value_fn) &free);
763
764   /* Queue up the first node.  */
765   queue (&di, t, DUMP_NONE);
766
767   /* Until the queue is empty, keep dumping nodes.  */
768   while (di.queue)
769     dequeue_and_dump (&di);
770
771   /* Now, clean up.  */
772   for (dq = di.free_list; dq; dq = next_dq)
773     {
774       next_dq = dq->next;
775       free (dq);
776     }
777   splay_tree_delete (di.nodes);
778 }
779 \f
780
781 /* Table of tree dump switches. This must be consistent with the
782    tree_dump_index enumeration in tree-pass.h.  */
783 static struct dump_file_info dump_files[TDI_end] =
784 {
785   {NULL, NULL, NULL, 0, 0, 0, 0},
786   {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0, 0},
787   {".tu", "translation-unit", NULL, TDF_TREE, 0, 1, 0},
788   {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2, 0},
789   {".original", "tree-original", NULL, TDF_TREE, 0, 3, 0},
790   {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4, 0},
791   {".nested", "tree-nested", NULL, TDF_TREE, 0, 5, 0},
792   {".inlined", "tree-inlined", NULL, TDF_TREE, 0, 6, 0},
793   {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 7, 0},
794 #define FIRST_AUTO_NUMBERED_DUMP 8
795
796   {NULL, "tree-all", NULL, TDF_TREE, 0, 0, 0},
797   {NULL, "rtl-all", NULL, TDF_RTL, 0, 0, 0},
798   {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0},
799 };
800
801 /* Dynamically registered tree dump files and switches.  */
802 static struct dump_file_info *extra_dump_files;
803 static size_t extra_dump_files_in_use;
804 static size_t extra_dump_files_alloced;
805
806 /* Define a name->number mapping for a dump flag value.  */
807 struct dump_option_value_info
808 {
809   const char *const name;       /* the name of the value */
810   const int value;              /* the value of the name */
811 };
812
813 /* Table of dump options. This must be consistent with the TDF_* flags
814    in tree.h */
815 static const struct dump_option_value_info dump_options[] =
816 {
817   {"address", TDF_ADDRESS},
818   {"slim", TDF_SLIM},
819   {"raw", TDF_RAW},
820   {"details", TDF_DETAILS},
821   {"stats", TDF_STATS},
822   {"blocks", TDF_BLOCKS},
823   {"vops", TDF_VOPS},
824   {"lineno", TDF_LINENO},
825   {"uid", TDF_UID},
826   {"stmtaddr", TDF_STMTADDR},
827   {"memsyms", TDF_MEMSYMS},
828   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 
829             | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC)},
830   {NULL, 0}
831 };
832
833 unsigned int
834 dump_register (const char *suffix, const char *swtch, const char *glob,
835                int flags, int letter)
836 {
837   static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
838   int num = next_dump++;
839
840   size_t this = extra_dump_files_in_use++;
841
842   if (this >= extra_dump_files_alloced)
843     {
844       if (extra_dump_files_alloced == 0)
845         extra_dump_files_alloced = 32;
846       else
847         extra_dump_files_alloced *= 2;
848       extra_dump_files = xrealloc (extra_dump_files,
849                                    sizeof (struct dump_file_info)
850                                    * extra_dump_files_alloced);
851     }
852
853   memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info));
854   extra_dump_files[this].suffix = suffix;
855   extra_dump_files[this].swtch = swtch;
856   extra_dump_files[this].glob = glob;
857   extra_dump_files[this].flags = flags;
858   extra_dump_files[this].num = num;
859   extra_dump_files[this].letter = letter;
860
861   return this + 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 (enum tree_dump_index phase)
869 {
870   if (phase < TDI_end)
871     return &dump_files[phase];
872   else if (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 (enum tree_dump_index 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 (enum tree_dump_index 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: %s", name, strerror (errno));
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 (enum tree_dump_index 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 (enum tree_dump_index 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 (enum tree_dump_index 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 (enum tree_dump_index 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, int letter)
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         && (letter == 0 || letter == dump_files[i].letter))
1007       {
1008         dump_files[i].state = -1;
1009         dump_files[i].flags |= flags;
1010         n++;
1011       }
1012
1013   for (i = 0; i < extra_dump_files_in_use; i++)
1014     if ((extra_dump_files[i].flags & ir_dump_type)
1015         && (letter == 0 || letter == extra_dump_files[i].letter))
1016       {
1017         extra_dump_files[i].state = -1;
1018         extra_dump_files[i].flags |= flags;
1019         n++;
1020       }
1021
1022   return n;
1023 }
1024
1025 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1026    relevant details in the dump_files array.  */
1027
1028 static int
1029 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1030 {
1031   const char *option_value;
1032   const char *ptr;
1033   int flags;
1034   
1035   if (doglob && !dfi->glob)
1036     return 0;
1037
1038   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1039   if (!option_value)
1040     return 0;
1041
1042   if (*option_value && *option_value != '-')
1043     return 0;
1044
1045   ptr = option_value;
1046   flags = 0;
1047
1048   while (*ptr)
1049     {
1050       const struct dump_option_value_info *option_ptr;
1051       const char *end_ptr;
1052       unsigned length;
1053
1054       while (*ptr == '-')
1055         ptr++;
1056       end_ptr = strchr (ptr, '-');
1057       if (!end_ptr)
1058         end_ptr = ptr + strlen (ptr);
1059       length = end_ptr - ptr;
1060
1061       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1062         if (strlen (option_ptr->name) == length
1063             && !memcmp (option_ptr->name, ptr, length))
1064           {
1065             flags |= option_ptr->value;
1066             goto found;
1067           }
1068       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1069                length, ptr, dfi->swtch);
1070     found:;
1071       ptr = end_ptr;
1072     }
1073
1074   dfi->state = -1;
1075   dfi->flags |= flags;
1076
1077   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1078      known dumps.  */
1079   if (dfi->suffix == NULL)
1080     dump_enable_all (dfi->flags, 0);
1081
1082   return 1;
1083 }
1084
1085 int
1086 dump_switch_p (const char *arg)
1087 {
1088   size_t i;
1089   int any = 0;
1090
1091   for (i = TDI_none + 1; i != TDI_end; i++)
1092     any |= dump_switch_p_1 (arg, &dump_files[i], false);
1093
1094   /* Don't glob if we got a hit already */
1095   if (!any)
1096     for (i = TDI_none + 1; i != TDI_end; i++)
1097       any |= dump_switch_p_1 (arg, &dump_files[i], true);
1098
1099   for (i = 0; i < extra_dump_files_in_use; i++)
1100     any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1101   
1102   if (!any)
1103     for (i = 0; i < extra_dump_files_in_use; i++)
1104       any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1105
1106
1107   return any;
1108 }
1109
1110 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1111
1112 void
1113 dump_function (enum tree_dump_index phase, tree fn)
1114 {
1115   FILE *stream;
1116   int flags;
1117
1118   stream = dump_begin (phase, &flags);
1119   if (stream)
1120     {
1121       dump_function_to_file (fn, stream, flags);
1122       dump_end (phase, stream);
1123     }
1124 }
1125
1126 bool
1127 enable_rtl_dump_file (int letter)
1128 {
1129   if (letter == 'a')
1130     letter = 0;
1131
1132   return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0;
1133 }
1134
1135