OSDN Git Service

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