OSDN Git Service

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