* config/xtensa/lib1funcs.asm (__umulsidi3): Restore a12-a15 on exit.
[official-gcc.git] / gcc / tree-dump.c
blob8c008ab705c88d5fa7f0f04402c928594e01128d
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>
6 This file is part of GCC.
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.
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.
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. */
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"
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);
44 /* Add T to the end of the queue of nodes to dump. Returns the index
45 assigned to T. */
47 static unsigned int
48 queue (dump_info_p di, tree t, int flags)
50 dump_queue_p dq;
51 dump_node_info_p dni;
52 unsigned int index;
54 /* Assign the next available index to T. */
55 index = ++di->index;
57 /* Obtain a new queue node. */
58 if (di->free_list)
60 dq = di->free_list;
61 di->free_list = dq->next;
63 else
64 dq = XNEW (struct dump_queue);
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);
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;
81 /* Return the index. */
82 return index;
85 static void
86 dump_index (dump_info_p di, unsigned int index)
88 fprintf (di->stream, "@%-6u ", index);
89 di->column += 8;
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. */
96 void
97 queue_and_dump_index (dump_info_p di, const char *field, tree t, int flags)
99 unsigned int index;
100 splay_tree_node n;
102 /* If there's no node, just return. This makes for fewer checks in
103 our callers. */
104 if (!t)
105 return;
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);
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);
122 /* Dump the type of T. */
124 void
125 queue_and_dump_type (dump_info_p di, tree t)
127 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
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. */
135 /* Insert a new line in the dump output, and indent to an appropriate
136 place to start printing more fields. */
138 static void
139 dump_new_line (dump_info_p di)
141 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
142 di->column = SOL_COLUMN;
145 /* If necessary, insert a new line. */
147 static void
148 dump_maybe_newline (dump_info_p di)
150 int extra;
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)
158 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
159 di->column += COLUMN_ALIGNMENT - extra;
163 /* Dump pointer PTR using FIELD to identify it. */
165 void
166 dump_pointer (dump_info_p di, const char *field, void *ptr)
168 dump_maybe_newline (di);
169 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
170 di->column += 15;
173 /* Dump integer I using FIELD to identify it. */
175 void
176 dump_int (dump_info_p di, const char *field, int i)
178 dump_maybe_newline (di);
179 fprintf (di->stream, "%-4s: %-7d ", field, i);
180 di->column += 14;
183 /* Dump the floating point value R, using FIELD to identify it. */
185 static void
186 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
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;
196 /* Dump the string S. */
198 void
199 dump_string (dump_info_p di, const char *string)
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;
209 /* Dump the string field S. */
211 void
212 dump_string_field (dump_info_p di, const char *field, const char *string)
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;
222 /* Dump the next node in the queue. */
224 static void
225 dequeue_and_dump (dump_info_p di)
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;
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;
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;
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;
260 /* Figure out what kind of node this is. */
261 code = TREE_CODE (t);
262 code_class = TREE_CODE_CLASS (code);
264 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
265 more informative. */
266 if (dni->binfo_p)
268 unsigned ix;
269 tree base;
270 VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
272 dump_child ("type", BINFO_TYPE (t));
274 if (BINFO_VIRTUAL_P (t))
275 dump_string_field (di, "spec", "virt");
277 dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
278 for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
280 tree access = (accesses ? VEC_index (tree, accesses, ix)
281 : access_public_node);
282 const char *string = NULL;
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 ();
293 dump_string_field (di, "accs", string);
294 queue_and_dump_index (di, "binf", base, DUMP_BINFO);
297 goto done;
300 /* We can knock off a bunch of expression nodes in exactly the same
301 way. */
302 if (IS_EXPR_CODE_CLASS (code_class))
304 /* If we're dumping children, dump them now. */
305 queue_and_dump_type (di, t);
307 switch (code_class)
309 case tcc_unary:
310 dump_child ("op 0", TREE_OPERAND (t, 0));
311 break;
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;
319 case tcc_expression:
320 case tcc_reference:
321 case tcc_statement:
322 /* These nodes are handled explicitly below. */
323 break;
325 default:
326 gcc_unreachable ();
329 else if (DECL_P (t))
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)
347 const char *filename = strrchr (xloc.file, '/');
348 if (!filename)
349 filename = xloc.file;
350 else
351 /* Skip the slash. */
352 ++filename;
354 dump_maybe_newline (di);
355 fprintf (di->stream, "srcp: %s:%-6d ", filename,
356 xloc.line);
357 di->column += 6 + strlen (filename) + 8;
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));
366 else if (code_class == tcc_type)
368 /* All types have qualifiers. */
369 int quals = lang_hooks.tree_dump.type_quals (t);
371 if (quals != TYPE_UNQUALIFIED)
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;
380 /* All types have associated declarations. */
381 dump_child ("name", TYPE_NAME (t));
383 /* All types have a main variant. */
384 if (TYPE_MAIN_VARIANT (t) != t)
385 dump_child ("unql", TYPE_MAIN_VARIANT (t));
387 /* And sizes. */
388 dump_child ("size", TYPE_SIZE (t));
390 /* All types have alignments. */
391 dump_int (di, "algn", TYPE_ALIGN (t));
393 else if (code_class == tcc_constant)
394 /* All constants can have types. */
395 queue_and_dump_type (di, t);
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;
403 /* Now handle the various kinds of nodes. */
404 switch (code)
406 int i;
408 case IDENTIFIER_NODE:
409 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
410 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
411 break;
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;
419 case STATEMENT_LIST:
421 tree_stmt_iterator it;
422 for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
424 char buffer[32];
425 sprintf (buffer, "%u", i);
426 dump_child (buffer, tsi_stmt (it));
429 break;
431 case TREE_VEC:
432 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
433 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
435 char buffer[32];
436 sprintf (buffer, "%u", i);
437 dump_child (buffer, TREE_VEC_ELT (t, i));
439 break;
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));
448 if (code == ENUMERAL_TYPE)
449 dump_child ("csts", TYPE_VALUES (t));
450 break;
452 case REAL_TYPE:
453 dump_int (di, "prec", TYPE_PRECISION (t));
454 break;
456 case POINTER_TYPE:
457 dump_child ("ptd", TREE_TYPE (t));
458 break;
460 case REFERENCE_TYPE:
461 dump_child ("refd", TREE_TYPE (t));
462 break;
464 case METHOD_TYPE:
465 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
466 /* Fall through. */
468 case FUNCTION_TYPE:
469 dump_child ("retn", TREE_TYPE (t));
470 dump_child ("prms", TYPE_ARG_TYPES (t));
471 break;
473 case ARRAY_TYPE:
474 dump_child ("elts", TREE_TYPE (t));
475 dump_child ("domn", TYPE_DOMAIN (t));
476 break;
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");
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;
491 case CONST_DECL:
492 dump_child ("cnst", DECL_INITIAL (t));
493 break;
495 case SYMBOL_MEMORY_TAG:
496 case NAME_MEMORY_TAG:
497 case STRUCT_FIELD_TAG:
498 break;
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));
511 if (TREE_CODE (t) == FIELD_DECL)
513 if (DECL_FIELD_OFFSET (t))
514 dump_child ("bpos", bit_position (t));
516 else if (TREE_CODE (t) == VAR_DECL
517 || TREE_CODE (t) == PARM_DECL)
519 dump_int (di, "used", TREE_USED (t));
520 if (DECL_REGISTER (t))
521 dump_string_field (di, "spec", "register");
523 break;
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;
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;
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;
548 case REAL_CST:
549 dump_real (di, "valu", TREE_REAL_CST_PTR (t));
550 break;
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;
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;
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;
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;
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;
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;
604 case CALL_EXPR:
605 dump_child ("fn", TREE_OPERAND (t, 0));
606 dump_child ("args", TREE_OPERAND (t, 1));
607 break;
609 case CONSTRUCTOR:
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)
617 dump_child ("idx", index);
618 dump_child ("val", value);
621 break;
623 case BIND_EXPR:
624 dump_child ("vars", TREE_OPERAND (t, 0));
625 dump_child ("body", TREE_OPERAND (t, 1));
626 break;
628 case LOOP_EXPR:
629 dump_child ("body", TREE_OPERAND (t, 0));
630 break;
632 case EXIT_EXPR:
633 dump_child ("cond", TREE_OPERAND (t, 0));
634 break;
636 case RETURN_EXPR:
637 dump_child ("expr", TREE_OPERAND (t, 0));
638 break;
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;
651 case CASE_LABEL_EXPR:
652 dump_child ("name", CASE_LABEL (t));
653 if (CASE_LOW (t))
655 dump_child ("low ", CASE_LOW (t));
656 if (CASE_HIGH (t))
657 dump_child ("high", CASE_HIGH (t));
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))
671 dump_child ("labl", TREE_OPERAND (t,2));
673 break;
674 case OMP_CLAUSE:
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));
681 break;
682 default:
683 /* There are no additional fields to print. */
684 break;
687 done:
688 if (dump_flag (di, TDF_ADDRESS, NULL))
689 dump_pointer (di, "addr", (void *)t);
691 /* Terminate the line. */
692 fprintf (di->stream, "\n");
695 /* Return nonzero if FLAG has been specified for the dump, and NODE
696 is not the root node of the dump. */
698 int dump_flag (dump_info_p di, int flag, tree node)
700 return (di->flags & flag) && (node != di->node);
703 /* Dump T, and all its children, on STREAM. */
705 void
706 dump_node (tree t, int flags, FILE *stream)
708 struct dump_info di;
709 dump_queue_p dq;
710 dump_queue_p next_dq;
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);
724 /* Queue up the first node. */
725 queue (&di, t, DUMP_NONE);
727 /* Until the queue is empty, keep dumping nodes. */
728 while (di.queue)
729 dequeue_and_dump (&di);
731 /* Now, clean up. */
732 for (dq = di.free_list; dq; dq = next_dq)
734 next_dq = dq->next;
735 free (dq);
737 splay_tree_delete (di.nodes);
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] =
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
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},
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;
766 /* Define a name->number mapping for a dump flag value. */
767 struct dump_option_value_info
769 const char *const name; /* the name of the value */
770 const int value; /* the value of the name */
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[] =
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}
792 unsigned int
793 dump_register (const char *suffix, const char *swtch, const char *glob,
794 int flags, int letter)
796 static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
797 int num = next_dump++;
799 size_t this = extra_dump_files_in_use++;
801 if (this >= extra_dump_files_alloced)
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);
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;
820 return this + TDI_end;
824 /* Return the dump_file_info for the given phase. */
826 struct dump_file_info *
827 get_dump_file_info (enum tree_dump_index phase)
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);
838 /* Return the name of the dump file for the given phase.
839 If the dump is not enabled, returns NULL. */
841 char *
842 get_dump_file_name (enum tree_dump_index phase)
844 char dump_id[10];
845 struct dump_file_info *dfi;
847 if (phase == TDI_none)
848 return NULL;
850 dfi = get_dump_file_info (phase);
851 if (dfi->state == 0)
852 return NULL;
854 if (dfi->num < 0)
855 dump_id[0] = '\0';
856 else
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';
866 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
867 dump_id[0] = '\0';
870 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
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. */
878 FILE *
879 dump_begin (enum tree_dump_index phase, int *flag_ptr)
881 char *name;
882 struct dump_file_info *dfi;
883 FILE *stream;
885 if (phase == TDI_none || !dump_enabled_p (phase))
886 return NULL;
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);
897 if (flag_ptr)
898 *flag_ptr = dfi->flags;
900 return stream;
903 /* Returns nonzero if tree dump PHASE is enabled. If PHASE is
904 TDI_tree_all, return nonzero if any dump is enabled. */
907 dump_enabled_p (enum tree_dump_index phase)
909 if (phase == TDI_tree_all)
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;
920 else
922 struct dump_file_info *dfi = get_dump_file_info (phase);
923 return dfi->state;
927 /* Returns nonzero if tree dump PHASE has been initialized. */
930 dump_initialized_p (enum tree_dump_index phase)
932 struct dump_file_info *dfi = get_dump_file_info (phase);
933 return dfi->state > 0;
936 /* Returns the switch name of PHASE. */
938 const char *
939 dump_flag_name (enum tree_dump_index phase)
941 struct dump_file_info *dfi = get_dump_file_info (phase);
942 return dfi->swtch;
945 /* Finish a tree dump for PHASE. STREAM is the stream created by
946 dump_begin. */
948 void
949 dump_end (enum tree_dump_index phase ATTRIBUTE_UNUSED, FILE *stream)
951 fclose (stream);
954 /* Enable all tree dumps. Return number of enabled tree dumps. */
956 static int
957 dump_enable_all (int flags, int letter)
959 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
960 int n = 0;
961 size_t i;
963 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
964 if ((dump_files[i].flags & ir_dump_type)
965 && (letter == 0 || letter == dump_files[i].letter))
967 dump_files[i].state = -1;
968 dump_files[i].flags |= flags;
969 n++;
972 for (i = 0; i < extra_dump_files_in_use; i++)
973 if ((extra_dump_files[i].flags & ir_dump_type)
974 && (letter == 0 || letter == extra_dump_files[i].letter))
976 extra_dump_files[i].state = -1;
977 extra_dump_files[i].flags |= flags;
978 n++;
981 return n;
984 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
985 relevant details in the dump_files array. */
987 static int
988 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
990 const char *option_value;
991 const char *ptr;
992 int flags;
994 if (doglob && !dfi->glob)
995 return 0;
997 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
998 if (!option_value)
999 return 0;
1001 ptr = option_value;
1002 flags = 0;
1004 while (*ptr)
1006 const struct dump_option_value_info *option_ptr;
1007 const char *end_ptr;
1008 unsigned length;
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;
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))
1021 flags |= option_ptr->value;
1022 goto found;
1024 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1025 length, ptr, dfi->swtch);
1026 found:;
1027 ptr = end_ptr;
1030 dfi->state = -1;
1031 dfi->flags |= flags;
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);
1038 return 1;
1042 dump_switch_p (const char *arg)
1044 size_t i;
1045 int any = 0;
1047 for (i = TDI_none + 1; i != TDI_end; i++)
1048 any |= dump_switch_p_1 (arg, &dump_files[i], false);
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);
1055 for (i = 0; i < extra_dump_files_in_use; i++)
1056 any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
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);
1063 return any;
1066 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
1068 void
1069 dump_function (enum tree_dump_index phase, tree fn)
1071 FILE *stream;
1072 int flags;
1074 stream = dump_begin (phase, &flags);
1075 if (stream)
1077 dump_function_to_file (fn, stream, flags);
1078 dump_end (phase, stream);
1082 bool
1083 enable_rtl_dump_file (int letter)
1085 if (letter == 'a')
1086 letter = 0;
1088 return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0;