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