OSDN Git Service

* config/sol2.c (solaris_assemble_visibility): Declare decl, vis
[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    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.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 (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
374         dump_child ("chan", TREE_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 ALIGN_INDIRECT_REF:
576     case MISALIGNED_INDIRECT_REF:
577     case CLEANUP_POINT_EXPR:
578     case SAVE_EXPR:
579     case REALPART_EXPR:
580     case IMAGPART_EXPR:
581       /* These nodes are unary, but do not have code class `1'.  */
582       dump_child ("op 0", TREE_OPERAND (t, 0));
583       break;
584
585     case TRUTH_ANDIF_EXPR:
586     case TRUTH_ORIF_EXPR:
587     case INIT_EXPR:
588     case MODIFY_EXPR:
589     case COMPOUND_EXPR:
590     case PREDECREMENT_EXPR:
591     case PREINCREMENT_EXPR:
592     case POSTDECREMENT_EXPR:
593     case POSTINCREMENT_EXPR:
594       /* These nodes are binary, but do not have code class `2'.  */
595       dump_child ("op 0", TREE_OPERAND (t, 0));
596       dump_child ("op 1", TREE_OPERAND (t, 1));
597       break;
598
599     case COMPONENT_REF:
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 ARRAY_REF:
606     case ARRAY_RANGE_REF:
607       dump_child ("op 0", TREE_OPERAND (t, 0));
608       dump_child ("op 1", TREE_OPERAND (t, 1));
609       dump_child ("op 2", TREE_OPERAND (t, 2));
610       dump_child ("op 3", TREE_OPERAND (t, 3));
611       break;
612
613     case COND_EXPR:
614       dump_child ("op 0", TREE_OPERAND (t, 0));
615       dump_child ("op 1", TREE_OPERAND (t, 1));
616       dump_child ("op 2", TREE_OPERAND (t, 2));
617       break;
618
619     case TRY_FINALLY_EXPR:
620       dump_child ("op 0", TREE_OPERAND (t, 0));
621       dump_child ("op 1", TREE_OPERAND (t, 1));
622       break;
623
624     case CALL_EXPR:
625       {
626         int i = 0;
627         tree arg;
628         call_expr_arg_iterator iter;
629         dump_child ("fn", CALL_EXPR_FN (t));
630         FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
631           {
632             char buffer[32];
633             sprintf (buffer, "%u", i);
634             dump_child (buffer, arg);
635             i++;
636           }
637       }
638       break;
639
640     case CONSTRUCTOR:
641       {
642         unsigned HOST_WIDE_INT cnt;
643         tree index, value;
644         dump_int (di, "lngt", VEC_length (constructor_elt,
645                                           CONSTRUCTOR_ELTS (t)));
646         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
647           {
648             dump_child ("idx", index);
649             dump_child ("val", value);
650           }
651       }
652       break;
653
654     case BIND_EXPR:
655       dump_child ("vars", TREE_OPERAND (t, 0));
656       dump_child ("body", TREE_OPERAND (t, 1));
657       break;
658
659     case LOOP_EXPR:
660       dump_child ("body", TREE_OPERAND (t, 0));
661       break;
662
663     case EXIT_EXPR:
664       dump_child ("cond", TREE_OPERAND (t, 0));
665       break;
666
667     case RETURN_EXPR:
668       dump_child ("expr", TREE_OPERAND (t, 0));
669       break;
670
671     case TARGET_EXPR:
672       dump_child ("decl", TREE_OPERAND (t, 0));
673       dump_child ("init", TREE_OPERAND (t, 1));
674       dump_child ("clnp", TREE_OPERAND (t, 2));
675       /* There really are two possible places the initializer can be.
676          After RTL expansion, the second operand is moved to the
677          position of the fourth operand, and the second operand
678          becomes NULL.  */
679       dump_child ("init", TREE_OPERAND (t, 3));
680       break;
681
682     case CASE_LABEL_EXPR:
683       dump_child ("name", CASE_LABEL (t));
684       if (CASE_LOW (t))
685         {
686           dump_child ("low ", CASE_LOW (t));
687           if (CASE_HIGH (t))
688             dump_child ("high", CASE_HIGH (t));
689         }
690       break;
691     case LABEL_EXPR:
692       dump_child ("name", TREE_OPERAND (t,0));
693       break;
694     case GOTO_EXPR:
695       dump_child ("labl", TREE_OPERAND (t, 0));
696       break;
697     case SWITCH_EXPR:
698       dump_child ("cond", TREE_OPERAND (t, 0));
699       dump_child ("body", TREE_OPERAND (t, 1));
700       if (TREE_OPERAND (t, 2))
701         {
702           dump_child ("labl", TREE_OPERAND (t,2));
703         }
704       break;
705     case OMP_CLAUSE:
706       {
707         int i;
708         fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
709         for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
710           dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
711       }
712       break;
713     default:
714       /* There are no additional fields to print.  */
715       break;
716     }
717
718  done:
719   if (dump_flag (di, TDF_ADDRESS, NULL))
720     dump_pointer (di, "addr", (void *)t);
721
722   /* Terminate the line.  */
723   fprintf (di->stream, "\n");
724 }
725
726 /* Return nonzero if FLAG has been specified for the dump, and NODE
727    is not the root node of the dump.  */
728
729 int dump_flag (dump_info_p di, int flag, const_tree node)
730 {
731   return (di->flags & flag) && (node != di->node);
732 }
733
734 /* Dump T, and all its children, on STREAM.  */
735
736 void
737 dump_node (const_tree t, int flags, FILE *stream)
738 {
739   struct dump_info di;
740   dump_queue_p dq;
741   dump_queue_p next_dq;
742
743   /* Initialize the dump-information structure.  */
744   di.stream = stream;
745   di.index = 0;
746   di.column = 0;
747   di.queue = 0;
748   di.queue_end = 0;
749   di.free_list = 0;
750   di.flags = flags;
751   di.node = t;
752   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
753                              (splay_tree_delete_value_fn) &free);
754
755   /* Queue up the first node.  */
756   queue (&di, t, DUMP_NONE);
757
758   /* Until the queue is empty, keep dumping nodes.  */
759   while (di.queue)
760     dequeue_and_dump (&di);
761
762   /* Now, clean up.  */
763   for (dq = di.free_list; dq; dq = next_dq)
764     {
765       next_dq = dq->next;
766       free (dq);
767     }
768   splay_tree_delete (di.nodes);
769 }
770 \f
771
772 /* Table of tree dump switches. This must be consistent with the
773    tree_dump_index enumeration in tree-pass.h.  */
774 static struct dump_file_info dump_files[TDI_end] =
775 {
776   {NULL, NULL, NULL, 0, 0, 0},
777   {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
778   {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
779   {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
780   {".original", "tree-original", NULL, TDF_TREE, 0, 3},
781   {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
782   {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
783   {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
784 #define FIRST_AUTO_NUMBERED_DUMP 7
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   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
825             | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
826             | TDF_RHS_ONLY | TDF_NOUID)},
827   {NULL, 0}
828 };
829
830 unsigned int
831 dump_register (const char *suffix, const char *swtch, const char *glob,
832                int flags)
833 {
834   static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
835   int num = next_dump++;
836
837   size_t count = extra_dump_files_in_use++;
838
839   if (count >= extra_dump_files_alloced)
840     {
841       if (extra_dump_files_alloced == 0)
842         extra_dump_files_alloced = 32;
843       else
844         extra_dump_files_alloced *= 2;
845       extra_dump_files = XRESIZEVEC (struct dump_file_info,
846                                      extra_dump_files,
847                                      extra_dump_files_alloced);
848     }
849
850   memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
851   extra_dump_files[count].suffix = suffix;
852   extra_dump_files[count].swtch = swtch;
853   extra_dump_files[count].glob = glob;
854   extra_dump_files[count].flags = flags;
855   extra_dump_files[count].num = num;
856
857   return count + TDI_end;
858 }
859
860
861 /* Return the dump_file_info for the given phase.  */
862
863 struct dump_file_info *
864 get_dump_file_info (int phase)
865 {
866   if (phase < TDI_end)
867     return &dump_files[phase];
868   else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
869     return NULL;
870   else
871     return extra_dump_files + (phase - TDI_end);
872 }
873
874
875 /* Return the name of the dump file for the given phase.
876    If the dump is not enabled, returns NULL.  */
877
878 char *
879 get_dump_file_name (int phase)
880 {
881   char dump_id[10];
882   struct dump_file_info *dfi;
883
884   if (phase == TDI_none)
885     return NULL;
886
887   dfi = get_dump_file_info (phase);
888   if (dfi->state == 0)
889     return NULL;
890
891   if (dfi->num < 0)
892     dump_id[0] = '\0';
893   else
894     {
895       char suffix;
896       if (dfi->flags & TDF_TREE)
897         suffix = 't';
898       else if (dfi->flags & TDF_IPA)
899         suffix = 'i';
900       else
901         suffix = 'r';
902
903       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
904         dump_id[0] = '\0';
905     }
906
907   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
908 }
909
910 /* Begin a tree dump for PHASE. Stores any user supplied flag in
911    *FLAG_PTR and returns a stream to write to. If the dump is not
912    enabled, returns NULL.
913    Multiple calls will reopen and append to the dump file.  */
914
915 FILE *
916 dump_begin (int phase, int *flag_ptr)
917 {
918   char *name;
919   struct dump_file_info *dfi;
920   FILE *stream;
921
922   if (phase == TDI_none || !dump_enabled_p (phase))
923     return NULL;
924
925   name = get_dump_file_name (phase);
926   dfi = get_dump_file_info (phase);
927   stream = fopen (name, dfi->state < 0 ? "w" : "a");
928   if (!stream)
929     error ("could not open dump file %qs: %s", name, strerror (errno));
930   else
931     dfi->state = 1;
932   free (name);
933
934   if (flag_ptr)
935     *flag_ptr = dfi->flags;
936
937   return stream;
938 }
939
940 /* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
941    TDI_tree_all, return nonzero if any dump is enabled.  */
942
943 int
944 dump_enabled_p (int phase)
945 {
946   if (phase == TDI_tree_all)
947     {
948       size_t i;
949       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
950         if (dump_files[i].state)
951           return 1;
952       for (i = 0; i < extra_dump_files_in_use; i++)
953         if (extra_dump_files[i].state)
954           return 1;
955       return 0;
956     }
957   else
958     {
959       struct dump_file_info *dfi = get_dump_file_info (phase);
960       return dfi->state;
961     }
962 }
963
964 /* Returns nonzero if tree dump PHASE has been initialized.  */
965
966 int
967 dump_initialized_p (int phase)
968 {
969   struct dump_file_info *dfi = get_dump_file_info (phase);
970   return dfi->state > 0;
971 }
972
973 /* Returns the switch name of PHASE.  */
974
975 const char *
976 dump_flag_name (int phase)
977 {
978   struct dump_file_info *dfi = get_dump_file_info (phase);
979   return dfi->swtch;
980 }
981
982 /* Finish a tree dump for PHASE. STREAM is the stream created by
983    dump_begin.  */
984
985 void
986 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
987 {
988   fclose (stream);
989 }
990
991 /* Enable all tree dumps.  Return number of enabled tree dumps.  */
992
993 static int
994 dump_enable_all (int flags)
995 {
996   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
997   int n = 0;
998   size_t i;
999
1000   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1001     if ((dump_files[i].flags & ir_dump_type))
1002       {
1003         dump_files[i].state = -1;
1004         dump_files[i].flags |= flags;
1005         n++;
1006       }
1007
1008   for (i = 0; i < extra_dump_files_in_use; i++)
1009     if ((extra_dump_files[i].flags & ir_dump_type))
1010       {
1011         extra_dump_files[i].state = -1;
1012         extra_dump_files[i].flags |= flags;
1013         n++;
1014       }
1015
1016   return n;
1017 }
1018
1019 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
1020    relevant details in the dump_files array.  */
1021
1022 static int
1023 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1024 {
1025   const char *option_value;
1026   const char *ptr;
1027   int flags;
1028
1029   if (doglob && !dfi->glob)
1030     return 0;
1031
1032   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1033   if (!option_value)
1034     return 0;
1035
1036   if (*option_value && *option_value != '-')
1037     return 0;
1038
1039   ptr = option_value;
1040   flags = 0;
1041
1042   while (*ptr)
1043     {
1044       const struct dump_option_value_info *option_ptr;
1045       const char *end_ptr;
1046       unsigned length;
1047
1048       while (*ptr == '-')
1049         ptr++;
1050       end_ptr = strchr (ptr, '-');
1051       if (!end_ptr)
1052         end_ptr = ptr + strlen (ptr);
1053       length = end_ptr - ptr;
1054
1055       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1056         if (strlen (option_ptr->name) == length
1057             && !memcmp (option_ptr->name, ptr, length))
1058           {
1059             flags |= option_ptr->value;
1060             goto found;
1061           }
1062       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1063                length, ptr, dfi->swtch);
1064     found:;
1065       ptr = end_ptr;
1066     }
1067
1068   dfi->state = -1;
1069   dfi->flags |= flags;
1070
1071   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1072      known dumps.  */
1073   if (dfi->suffix == NULL)
1074     dump_enable_all (dfi->flags);
1075
1076   return 1;
1077 }
1078
1079 int
1080 dump_switch_p (const char *arg)
1081 {
1082   size_t i;
1083   int any = 0;
1084
1085   for (i = TDI_none + 1; i != TDI_end; i++)
1086     any |= dump_switch_p_1 (arg, &dump_files[i], false);
1087
1088   /* Don't glob if we got a hit already */
1089   if (!any)
1090     for (i = TDI_none + 1; i != TDI_end; i++)
1091       any |= dump_switch_p_1 (arg, &dump_files[i], true);
1092
1093   for (i = 0; i < extra_dump_files_in_use; i++)
1094     any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1095
1096   if (!any)
1097     for (i = 0; i < extra_dump_files_in_use; i++)
1098       any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1099
1100
1101   return any;
1102 }
1103
1104 /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1105
1106 void
1107 dump_function (int phase, tree fn)
1108 {
1109   FILE *stream;
1110   int flags;
1111
1112   stream = dump_begin (phase, &flags);
1113   if (stream)
1114     {
1115       dump_function_to_file (fn, stream, flags);
1116       dump_end (phase, stream);
1117     }
1118 }
1119
1120 bool
1121 enable_rtl_dump_file (void)
1122 {
1123   return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
1124 }