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