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