OSDN Git Service

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