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