xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-dump.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
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