OSDN Git Service

2008-03-04 Uros Bizjak <ubizjak@gmail.com>
[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, 2008
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_SAVED_TREE (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   {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6, 0},
793 #define FIRST_AUTO_NUMBERED_DUMP 7
794
795   {NULL, "tree-all", NULL, TDF_TREE, 0, 0, 0},
796   {NULL, "rtl-all", NULL, TDF_RTL, 0, 0, 0},
797   {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0},
798 };
799
800 /* Dynamically registered tree dump files and switches.  */
801 static struct dump_file_info *extra_dump_files;
802 static size_t extra_dump_files_in_use;
803 static size_t extra_dump_files_alloced;
804
805 /* Define a name->number mapping for a dump flag value.  */
806 struct dump_option_value_info
807 {
808   const char *const name;       /* the name of the value */
809   const int value;              /* the value of the name */
810 };
811
812 /* Table of dump options. This must be consistent with the TDF_* flags
813    in tree.h */
814 static const struct dump_option_value_info dump_options[] =
815 {
816   {"address", TDF_ADDRESS},
817   {"slim", TDF_SLIM},
818   {"raw", TDF_RAW},
819   {"details", TDF_DETAILS},
820   {"stats", TDF_STATS},
821   {"blocks", TDF_BLOCKS},
822   {"vops", TDF_VOPS},
823   {"lineno", TDF_LINENO},
824   {"uid", TDF_UID},
825   {"stmtaddr", TDF_STMTADDR},
826   {"memsyms", TDF_MEMSYMS},
827   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 
828             | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC)},
829   {NULL, 0}
830 };
831
832 unsigned int
833 dump_register (const char *suffix, const char *swtch, const char *glob,
834                int flags, int letter)
835 {
836   static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
837   int num = next_dump++;
838
839   size_t this = extra_dump_files_in_use++;
840
841   if (this >= extra_dump_files_alloced)
842     {
843       if (extra_dump_files_alloced == 0)
844         extra_dump_files_alloced = 32;
845       else
846         extra_dump_files_alloced *= 2;
847       extra_dump_files = xrealloc (extra_dump_files,
848                                    sizeof (struct dump_file_info)
849                                    * extra_dump_files_alloced);
850     }
851
852   memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info));
853   extra_dump_files[this].suffix = suffix;
854   extra_dump_files[this].swtch = swtch;
855   extra_dump_files[this].glob = glob;
856   extra_dump_files[this].flags = flags;
857   extra_dump_files[this].num = num;
858   extra_dump_files[this].letter = letter;
859
860   return this + TDI_end;
861 }
862
863
864 /* Return the dump_file_info for the given phase.  */
865
866 struct dump_file_info *
867 get_dump_file_info (enum tree_dump_index phase)
868 {
869   if (phase < TDI_end)
870     return &dump_files[phase];
871   else if (phase - TDI_end >= extra_dump_files_in_use)
872     return NULL;
873   else
874     return extra_dump_files + (phase - TDI_end);
875 }
876
877
878 /* Return the name of the dump file for the given phase.
879    If the dump is not enabled, returns NULL.  */
880
881 char *
882 get_dump_file_name (enum tree_dump_index phase)
883 {
884   char dump_id[10];
885   struct dump_file_info *dfi;
886
887   if (phase == TDI_none)
888     return NULL;
889
890   dfi = get_dump_file_info (phase);
891   if (dfi->state == 0)
892     return NULL;
893
894   if (dfi->num < 0)
895     dump_id[0] = '\0';
896   else
897     {
898       char suffix;
899       if (dfi->flags & TDF_TREE)
900         suffix = 't';
901       else if (dfi->flags & TDF_IPA)
902         suffix = 'i';
903       else
904         suffix = 'r';
905
906       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
907         dump_id[0] = '\0';
908     }
909
910   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
911 }
912
913 /* Begin a tree dump for PHASE. Stores any user supplied flag in
914    *FLAG_PTR and returns a stream to write to. If the dump is not
915    enabled, returns NULL.
916    Multiple calls will reopen and append to the dump file.  */
917
918 FILE *
919 dump_begin (enum tree_dump_index phase, int *flag_ptr)
920 {
921   char *name;
922   struct dump_file_info *dfi;
923   FILE *stream;
924
925   if (phase == TDI_none || !dump_enabled_p (phase))
926     return NULL;
927
928   name = get_dump_file_name (phase);
929   dfi = get_dump_file_info (phase);
930   stream = fopen (name, dfi->state < 0 ? "w" : "a");
931   if (!stream)
932     error ("could not open dump file %qs: %s", name, strerror (errno));
933   else
934     dfi->state = 1;
935   free (name);
936
937   if (flag_ptr)
938     *flag_ptr = dfi->flags;
939
940   return stream;
941 }
942
943 /* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
944    TDI_tree_all, return nonzero if any dump is enabled.  */
945
946 int
947 dump_enabled_p (enum tree_dump_index phase)
948 {
949   if (phase == TDI_tree_all)
950     {
951       size_t i;
952       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
953         if (dump_files[i].state)
954           return 1;
955       for (i = 0; i < extra_dump_files_in_use; i++)
956         if (extra_dump_files[i].state)
957           return 1;
958       return 0;
959     }
960   else
961     {
962       struct dump_file_info *dfi = get_dump_file_info (phase);
963       return dfi->state;
964     }
965 }
966
967 /* Returns nonzero if tree dump PHASE has been initialized.  */
968
969 int
970 dump_initialized_p (enum tree_dump_index phase)
971 {
972   struct dump_file_info *dfi = get_dump_file_info (phase);
973   return dfi->state > 0;
974 }
975
976 /* Returns the switch name of PHASE.  */
977
978 const char *
979 dump_flag_name (enum tree_dump_index phase)
980 {
981   struct dump_file_info *dfi = get_dump_file_info (phase);
982   return dfi->swtch;
983 }
984
985 /* Finish a tree dump for PHASE. STREAM is the stream created by
986    dump_begin.  */
987
988 void
989 dump_end (enum tree_dump_index phase ATTRIBUTE_UNUSED, FILE *stream)
990 {
991   fclose (stream);
992 }
993
994 /* Enable all tree dumps.  Return number of enabled tree dumps.  */
995
996 static int
997 dump_enable_all (int flags, int letter)
998 {
999   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
1000   int n = 0;
1001   size_t i;
1002
1003   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1004     if ((dump_files[i].flags & ir_dump_type)
1005         && (letter == 0 || letter == dump_files[i].letter))
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         && (letter == 0 || letter == extra_dump_files[i].letter))
1015       {
1016         extra_dump_files[i].state = -1;
1017         extra_dump_files[i].flags |= flags;
1018         n++;
1019       }
1020
1021   return n;
1022 }
1023
1024 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1025    relevant details in the dump_files array.  */
1026
1027 static int
1028 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1029 {
1030   const char *option_value;
1031   const char *ptr;
1032   int flags;
1033   
1034   if (doglob && !dfi->glob)
1035     return 0;
1036
1037   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1038   if (!option_value)
1039     return 0;
1040
1041   if (*option_value && *option_value != '-')
1042     return 0;
1043
1044   ptr = option_value;
1045   flags = 0;
1046
1047   while (*ptr)
1048     {
1049       const struct dump_option_value_info *option_ptr;
1050       const char *end_ptr;
1051       unsigned length;
1052
1053       while (*ptr == '-')
1054         ptr++;
1055       end_ptr = strchr (ptr, '-');
1056       if (!end_ptr)
1057         end_ptr = ptr + strlen (ptr);
1058       length = end_ptr - ptr;
1059
1060       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1061         if (strlen (option_ptr->name) == length
1062             && !memcmp (option_ptr->name, ptr, length))
1063           {
1064             flags |= option_ptr->value;
1065             goto found;
1066           }
1067       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1068                length, ptr, dfi->swtch);
1069     found:;
1070       ptr = end_ptr;
1071     }
1072
1073   dfi->state = -1;
1074   dfi->flags |= flags;
1075
1076   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1077      known dumps.  */
1078   if (dfi->suffix == NULL)
1079     dump_enable_all (dfi->flags, 0);
1080
1081   return 1;
1082 }
1083
1084 int
1085 dump_switch_p (const char *arg)
1086 {
1087   size_t i;
1088   int any = 0;
1089
1090   for (i = TDI_none + 1; i != TDI_end; i++)
1091     any |= dump_switch_p_1 (arg, &dump_files[i], false);
1092
1093   /* Don't glob if we got a hit already */
1094   if (!any)
1095     for (i = TDI_none + 1; i != TDI_end; i++)
1096       any |= dump_switch_p_1 (arg, &dump_files[i], true);
1097
1098   for (i = 0; i < extra_dump_files_in_use; i++)
1099     any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1100   
1101   if (!any)
1102     for (i = 0; i < extra_dump_files_in_use; i++)
1103       any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1104
1105
1106   return any;
1107 }
1108
1109 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1110
1111 void
1112 dump_function (enum tree_dump_index phase, tree fn)
1113 {
1114   FILE *stream;
1115   int flags;
1116
1117   stream = dump_begin (phase, &flags);
1118   if (stream)
1119     {
1120       dump_function_to_file (fn, stream, flags);
1121       dump_end (phase, stream);
1122     }
1123 }
1124
1125 bool
1126 enable_rtl_dump_file (int letter)
1127 {
1128   if (letter == 'a')
1129     letter = 0;
1130
1131   return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0;
1132 }
1133
1134