OSDN Git Service

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