OSDN Git Service

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