* Makefile.in (rtlanal.o): Depend on $(TM_P_H).
[official-gcc.git] / gcc / c-dump.c
blob5c792683f33f5978ea8d2729556a874ba7da7ffb
1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3 Written by Mark Mitchell <mark@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "c-common.h"
26 #include "splay-tree.h"
27 #include "diagnostic.h"
28 #include "toplev.h"
29 #include "c-dump.h"
31 /* A callback function used dump language-specific parts of tree
32 nodes. Returns non-zero if it does not want the usual dumping of
33 the second argument. */
35 dump_tree_fn lang_dump_tree;
37 static unsigned int queue PARAMS ((dump_info_p, tree, int));
38 static void dump_index PARAMS ((dump_info_p, unsigned int));
39 static void dequeue_and_dump PARAMS ((dump_info_p));
40 static void dump_new_line PARAMS ((dump_info_p));
41 static void dump_maybe_newline PARAMS ((dump_info_p));
42 static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
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 (di, t, flags)
49 dump_info_p di;
50 tree t;
51 int flags;
53 dump_queue_p dq;
54 dump_node_info_p dni;
55 unsigned int index;
57 /* Assign the next available index to T. */
58 index = ++di->index;
60 /* Obtain a new queue node. */
61 if (di->free_list)
63 dq = di->free_list;
64 di->free_list = dq->next;
66 else
67 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
69 /* Create a new entry in the splay-tree. */
70 dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
71 dni->index = index;
72 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
73 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
74 (splay_tree_value) dni);
76 /* Add it to the end of the queue. */
77 dq->next = 0;
78 if (!di->queue_end)
79 di->queue = dq;
80 else
81 di->queue_end->next = dq;
82 di->queue_end = dq;
84 /* Return the index. */
85 return index;
88 static void
89 dump_index (di, index)
90 dump_info_p di;
91 unsigned int index;
93 fprintf (di->stream, "@%-6u ", index);
94 di->column += 8;
97 /* If T has not already been output, queue it for subsequent output.
98 FIELD is a string to print before printing the index. Then, the
99 index of T is printed. */
101 void
102 queue_and_dump_index (di, field, t, flags)
103 dump_info_p di;
104 const char *field;
105 tree t;
106 int flags;
108 unsigned int index;
109 splay_tree_node n;
111 /* If there's no node, just return. This makes for fewer checks in
112 our callers. */
113 if (!t)
114 return;
116 /* See if we've already queued or dumped this node. */
117 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
118 if (n)
119 index = ((dump_node_info_p) n->value)->index;
120 else
121 /* If we haven't, add it to the queue. */
122 index = queue (di, t, flags);
124 /* Print the index of the node. */
125 dump_maybe_newline (di);
126 fprintf (di->stream, "%-4s: ", field);
127 di->column += 6;
128 dump_index (di, index);
131 /* Dump the type of T. */
133 void
134 queue_and_dump_type (di, t)
135 dump_info_p di;
136 tree t;
138 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
141 /* Dump column control */
142 #define SOL_COLUMN 25 /* Start of line column. */
143 #define EOL_COLUMN 55 /* End of line column. */
144 #define COLUMN_ALIGNMENT 15 /* Alignment. */
146 /* Insert a new line in the dump output, and indent to an appropriate
147 place to start printing more fields. */
149 static void
150 dump_new_line (di)
151 dump_info_p di;
153 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
154 di->column = SOL_COLUMN;
157 /* If necessary, insert a new line. */
159 static void
160 dump_maybe_newline (di)
161 dump_info_p di;
163 int extra;
165 /* See if we need a new line. */
166 if (di->column > EOL_COLUMN)
167 dump_new_line (di);
168 /* See if we need any padding. */
169 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
171 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
172 di->column += COLUMN_ALIGNMENT - extra;
176 /* Dump pointer PTR using FIELD to identify it. */
178 void
179 dump_pointer (di, field, ptr)
180 dump_info_p di;
181 const char *field;
182 void *ptr;
184 dump_maybe_newline (di);
185 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
186 di->column += 15;
189 /* Dump integer I using FIELD to identify it. */
191 void
192 dump_int (di, field, i)
193 dump_info_p di;
194 const char *field;
195 int i;
197 dump_maybe_newline (di);
198 fprintf (di->stream, "%-4s: %-7d ", field, i);
199 di->column += 14;
202 /* Dump the string S. */
204 void
205 dump_string (di, string)
206 dump_info_p di;
207 const char *string;
209 dump_maybe_newline (di);
210 fprintf (di->stream, "%-13s ", string);
211 if (strlen (string) > 13)
212 di->column += strlen (string) + 1;
213 else
214 di->column += 14;
217 /* Dump the string field S. */
219 static void
220 dump_string_field (di, field, string)
221 dump_info_p di;
222 const char *field;
223 const char *string;
225 dump_maybe_newline (di);
226 fprintf (di->stream, "%-4s: %-7s ", field, string);
227 if (strlen (string) > 7)
228 di->column += 6 + strlen (string) + 1;
229 else
230 di->column += 14;
233 /* Dump information common to statements from STMT. */
235 void
236 dump_stmt (di, t)
237 dump_info_p di;
238 tree t;
240 dump_int (di, "line", STMT_LINENO (t));
243 /* Dump the next statement after STMT. */
245 void
246 dump_next_stmt (di, t)
247 dump_info_p di;
248 tree t;
250 dump_child ("next", TREE_CHAIN (t));
253 /* Dump the next node in the queue. */
255 static void
256 dequeue_and_dump (di)
257 dump_info_p di;
259 dump_queue_p dq;
260 splay_tree_node stn;
261 dump_node_info_p dni;
262 tree t;
263 unsigned int index;
264 enum tree_code code;
265 char code_class;
266 const char* code_name;
268 /* Get the next node from the queue. */
269 dq = di->queue;
270 stn = dq->node;
271 t = (tree) stn->key;
272 dni = (dump_node_info_p) stn->value;
273 index = dni->index;
275 /* Remove the node from the queue, and put it on the free list. */
276 di->queue = dq->next;
277 if (!di->queue)
278 di->queue_end = 0;
279 dq->next = di->free_list;
280 di->free_list = dq;
282 /* Print the node index. */
283 dump_index (di, index);
284 /* And the type of node this is. */
285 if (dni->binfo_p)
286 code_name = "binfo";
287 else
288 code_name = tree_code_name[(int) TREE_CODE (t)];
289 fprintf (di->stream, "%-16s ", code_name);
290 di->column = 25;
292 /* Figure out what kind of node this is. */
293 code = TREE_CODE (t);
294 code_class = TREE_CODE_CLASS (code);
296 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
297 more informative. */
298 if (dni->binfo_p)
300 if (TREE_VIA_PUBLIC (t))
301 dump_string (di, "pub");
302 else if (TREE_VIA_PROTECTED (t))
303 dump_string (di, "prot");
304 else if (TREE_VIA_PRIVATE (t))
305 dump_string (di, "priv");
306 if (TREE_VIA_VIRTUAL (t))
307 dump_string (di, "virt");
309 dump_child ("type", BINFO_TYPE (t));
310 dump_child ("base", BINFO_BASETYPES (t));
312 goto done;
315 /* We can knock off a bunch of expression nodes in exactly the same
316 way. */
317 if (IS_EXPR_CODE_CLASS (code_class))
319 /* If we're dumping children, dump them now. */
320 queue_and_dump_type (di, t);
322 switch (code_class)
324 case '1':
325 dump_child ("op 0", TREE_OPERAND (t, 0));
326 break;
328 case '2':
329 case '<':
330 dump_child ("op 0", TREE_OPERAND (t, 0));
331 dump_child ("op 1", TREE_OPERAND (t, 1));
332 break;
334 case 'e':
335 /* These nodes are handled explicitly below. */
336 break;
338 default:
339 abort();
342 else if (DECL_P (t))
344 /* All declarations have names. */
345 if (DECL_NAME (t))
346 dump_child ("name", DECL_NAME (t));
347 if (DECL_ASSEMBLER_NAME_SET_P (t)
348 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
349 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
350 /* And types. */
351 queue_and_dump_type (di, t);
352 dump_child ("scpe", DECL_CONTEXT (t));
353 /* And a source position. */
354 if (DECL_SOURCE_FILE (t))
356 const char *filename = strrchr (DECL_SOURCE_FILE (t), '/');
357 if (!filename)
358 filename = DECL_SOURCE_FILE (t);
359 else
360 /* Skip the slash. */
361 ++filename;
363 dump_maybe_newline (di);
364 fprintf (di->stream, "srcp: %s:%-6d ", filename,
365 DECL_SOURCE_LINE (t));
366 di->column += 6 + strlen (filename) + 8;
368 /* And any declaration can be compiler-generated. */
369 if (DECL_ARTIFICIAL (t))
370 dump_string (di, "artificial");
371 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
372 dump_child ("chan", TREE_CHAIN (t));
374 else if (code_class == 't')
376 /* All types have qualifiers. */
377 int quals = C_TYPE_QUALS (t);
378 if (quals != TYPE_UNQUALIFIED)
380 fprintf (di->stream, "qual: %c%c%c ",
381 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
382 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
383 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
384 di->column += 14;
387 /* All types have associated declarations. */
388 dump_child ("name", TYPE_NAME (t));
390 /* All types have a main variant. */
391 if (TYPE_MAIN_VARIANT (t) != t)
392 dump_child ("unql", TYPE_MAIN_VARIANT (t));
394 /* And sizes. */
395 dump_child ("size", TYPE_SIZE (t));
397 /* All types have alignments. */
398 dump_int (di, "algn", TYPE_ALIGN (t));
400 else if (code_class == 'c')
401 /* All constants can have types. */
402 queue_and_dump_type (di, t);
404 /* Give the language-specific code a chance to print something. If
405 it's completely taken care of things, don't bother printing
406 anything more ourselves. */
407 if (lang_dump_tree && (*lang_dump_tree) (di, t))
408 goto done;
410 /* Now handle the various kinds of nodes. */
411 switch (code)
413 int i;
415 case IDENTIFIER_NODE:
416 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
417 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
418 break;
420 case TREE_LIST:
421 dump_child ("purp", TREE_PURPOSE (t));
422 dump_child ("valu", TREE_VALUE (t));
423 dump_child ("chan", TREE_CHAIN (t));
424 break;
426 case TREE_VEC:
427 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
428 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
430 char buffer[32];
431 sprintf (buffer, "%u", i);
432 dump_child (buffer, TREE_VEC_ELT (t, i));
434 break;
436 case INTEGER_TYPE:
437 case ENUMERAL_TYPE:
438 dump_int (di, "prec", TYPE_PRECISION (t));
439 if (TREE_UNSIGNED (t))
440 dump_string (di, "unsigned");
441 dump_child ("min", TYPE_MIN_VALUE (t));
442 dump_child ("max", TYPE_MAX_VALUE (t));
444 if (code == ENUMERAL_TYPE)
445 dump_child ("csts", TYPE_VALUES (t));
446 break;
448 case REAL_TYPE:
449 dump_int (di, "prec", TYPE_PRECISION (t));
450 break;
452 case POINTER_TYPE:
453 dump_child ("ptd", TREE_TYPE (t));
454 break;
456 case REFERENCE_TYPE:
457 dump_child ("refd", TREE_TYPE (t));
458 break;
460 case METHOD_TYPE:
461 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
462 /* Fall through. */
464 case FUNCTION_TYPE:
465 dump_child ("retn", TREE_TYPE (t));
466 dump_child ("prms", TYPE_ARG_TYPES (t));
467 break;
469 case ARRAY_TYPE:
470 dump_child ("elts", TREE_TYPE (t));
471 dump_child ("domn", TYPE_DOMAIN (t));
472 break;
474 case RECORD_TYPE:
475 case UNION_TYPE:
476 if (TREE_CODE (t) == RECORD_TYPE)
477 dump_string (di, "struct");
478 else
479 dump_string (di, "union");
481 dump_child ("flds", TYPE_FIELDS (t));
482 dump_child ("fncs", TYPE_METHODS (t));
483 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
484 DUMP_BINFO);
485 break;
487 case CONST_DECL:
488 dump_child ("cnst", DECL_INITIAL (t));
489 break;
491 case VAR_DECL:
492 case PARM_DECL:
493 case FIELD_DECL:
494 case RESULT_DECL:
495 if (TREE_CODE (t) == PARM_DECL)
496 dump_child ("argt", DECL_ARG_TYPE (t));
497 else
498 dump_child ("init", DECL_INITIAL (t));
499 dump_child ("size", DECL_SIZE (t));
500 dump_int (di, "algn", DECL_ALIGN (t));
502 if (TREE_CODE (t) == FIELD_DECL)
504 if (DECL_C_BIT_FIELD (t))
505 dump_string (di, "bitfield");
506 if (DECL_FIELD_OFFSET (t))
507 dump_child ("bpos", bit_position (t));
509 else if (TREE_CODE (t) == VAR_DECL
510 || TREE_CODE (t) == PARM_DECL)
512 dump_int (di, "used", TREE_USED (t));
513 if (DECL_REGISTER (t))
514 dump_string (di, "register");
516 break;
518 case FUNCTION_DECL:
519 dump_child ("args", DECL_ARGUMENTS (t));
520 if (DECL_EXTERNAL (t))
521 dump_string (di, "undefined");
522 if (TREE_PUBLIC (t))
523 dump_string (di, "extern");
524 else
525 dump_string (di, "static");
526 if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
527 dump_child ("body", DECL_SAVED_TREE (t));
528 break;
530 case ASM_STMT:
531 dump_stmt (di, t);
532 if (ASM_VOLATILE_P (t))
533 dump_string (di, "volatile");
534 dump_child ("strg", ASM_STRING (t));
535 dump_child ("outs", ASM_OUTPUTS (t));
536 dump_child ("ins", ASM_INPUTS (t));
537 dump_child ("clbr", ASM_CLOBBERS (t));
538 dump_next_stmt (di, t);
539 break;
541 case BREAK_STMT:
542 case CONTINUE_STMT:
543 dump_stmt (di, t);
544 dump_next_stmt (di, t);
545 break;
547 case CASE_LABEL:
548 /* Note that a case label is not like other statments; there is
549 no way to get the line-number of a case label. */
550 dump_child ("low", CASE_LOW (t));
551 dump_child ("high", CASE_HIGH (t));
552 dump_next_stmt (di, t);
553 break;
555 case COMPOUND_STMT:
556 dump_stmt (di, t);
557 dump_child ("body", COMPOUND_BODY (t));
558 dump_next_stmt (di, t);
559 break;
561 case DECL_STMT:
562 dump_stmt (di, t);
563 dump_child ("decl", DECL_STMT_DECL (t));
564 dump_next_stmt (di, t);
565 break;
567 case DO_STMT:
568 dump_stmt (di, t);
569 dump_child ("body", DO_BODY (t));
570 dump_child ("cond", DO_COND (t));
571 dump_next_stmt (di, t);
572 break;
574 case EXPR_STMT:
575 dump_stmt (di, t);
576 dump_child ("expr", EXPR_STMT_EXPR (t));
577 dump_next_stmt (di, t);
578 break;
580 case FOR_STMT:
581 dump_stmt (di, t);
582 dump_child ("init", FOR_INIT_STMT (t));
583 dump_child ("cond", FOR_COND (t));
584 dump_child ("expr", FOR_EXPR (t));
585 dump_child ("body", FOR_BODY (t));
586 dump_next_stmt (di, t);
587 break;
589 case GOTO_STMT:
590 dump_stmt (di, t);
591 dump_child ("dest", GOTO_DESTINATION (t));
592 dump_next_stmt (di, t);
593 break;
595 case IF_STMT:
596 dump_stmt (di, t);
597 dump_child ("cond", IF_COND (t));
598 dump_child ("then", THEN_CLAUSE (t));
599 dump_child ("else", ELSE_CLAUSE (t));
600 dump_next_stmt (di, t);
601 break;
603 case LABEL_STMT:
604 dump_stmt (di, t);
605 dump_child ("labl", LABEL_STMT_LABEL (t));
606 dump_next_stmt (di, t);
607 break;
609 case RETURN_STMT:
610 dump_stmt (di, t);
611 dump_child ("expr", RETURN_EXPR (t));
612 dump_next_stmt (di, t);
613 break;
615 case SWITCH_STMT:
616 dump_stmt (di, t);
617 dump_child ("cond", SWITCH_COND (t));
618 dump_child ("body", SWITCH_BODY (t));
619 dump_next_stmt (di, t);
620 break;
622 case WHILE_STMT:
623 dump_stmt (di, t);
624 dump_child ("cond", WHILE_COND (t));
625 dump_child ("body", WHILE_BODY (t));
626 dump_next_stmt (di, t);
627 break;
629 case SCOPE_STMT:
630 dump_stmt (di, t);
631 if (SCOPE_BEGIN_P (t))
632 dump_string (di, "begn");
633 else
634 dump_string (di, "end");
635 if (SCOPE_NULLIFIED_P (t))
636 dump_string (di, "null");
637 if (!SCOPE_NO_CLEANUPS_P (t))
638 dump_string (di, "clnp");
639 dump_next_stmt (di, t);
640 break;
642 case INTEGER_CST:
643 if (TREE_INT_CST_HIGH (t))
644 dump_int (di, "high", TREE_INT_CST_HIGH (t));
645 dump_int (di, "low", TREE_INT_CST_LOW (t));
646 break;
648 case STRING_CST:
649 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
650 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
651 break;
653 case TRUTH_NOT_EXPR:
654 case ADDR_EXPR:
655 case INDIRECT_REF:
656 case CLEANUP_POINT_EXPR:
657 case SAVE_EXPR:
658 /* These nodes are unary, but do not have code class `1'. */
659 dump_child ("op 0", TREE_OPERAND (t, 0));
660 break;
662 case TRUTH_ANDIF_EXPR:
663 case TRUTH_ORIF_EXPR:
664 case INIT_EXPR:
665 case MODIFY_EXPR:
666 case COMPONENT_REF:
667 case COMPOUND_EXPR:
668 case ARRAY_REF:
669 case PREDECREMENT_EXPR:
670 case PREINCREMENT_EXPR:
671 case POSTDECREMENT_EXPR:
672 case POSTINCREMENT_EXPR:
673 /* These nodes are binary, but do not have code class `2'. */
674 dump_child ("op 0", TREE_OPERAND (t, 0));
675 dump_child ("op 1", TREE_OPERAND (t, 1));
676 break;
678 case COND_EXPR:
679 dump_child ("op 0", TREE_OPERAND (t, 0));
680 dump_child ("op 1", TREE_OPERAND (t, 1));
681 dump_child ("op 2", TREE_OPERAND (t, 2));
682 break;
684 case CALL_EXPR:
685 dump_child ("fn", TREE_OPERAND (t, 0));
686 dump_child ("args", TREE_OPERAND (t, 1));
687 break;
689 case CONSTRUCTOR:
690 dump_child ("elts", TREE_OPERAND (t, 1));
691 break;
693 case STMT_EXPR:
694 dump_child ("stmt", STMT_EXPR_STMT (t));
695 break;
697 case BIND_EXPR:
698 dump_child ("vars", TREE_OPERAND (t, 0));
699 dump_child ("body", TREE_OPERAND (t, 1));
700 break;
702 case LOOP_EXPR:
703 dump_child ("body", TREE_OPERAND (t, 0));
704 break;
706 case EXIT_EXPR:
707 dump_child ("cond", TREE_OPERAND (t, 0));
708 break;
710 case TARGET_EXPR:
711 dump_child ("decl", TREE_OPERAND (t, 0));
712 dump_child ("init", TREE_OPERAND (t, 1));
713 dump_child ("clnp", TREE_OPERAND (t, 2));
714 /* There really are two possible places the initializer can be.
715 After RTL expansion, the second operand is moved to the
716 position of the fourth operand, and the second operand
717 becomes NULL. */
718 dump_child ("init", TREE_OPERAND (t, 3));
719 break;
721 case EXPR_WITH_FILE_LOCATION:
722 dump_child ("expr", EXPR_WFL_NODE (t));
723 break;
725 default:
726 /* There are no additional fields to print. */
727 break;
730 done:
731 if (dump_flag (di, TDF_ADDRESS, NULL))
732 dump_pointer (di, "addr", (void *)t);
734 /* Terminate the line. */
735 fprintf (di->stream, "\n");
738 /* Return non-zero if FLAG has been specified for the dump, and NODE
739 is not the root node of the dump. */
741 int dump_flag (di, flag, node)
742 dump_info_p di;
743 int flag;
744 tree node;
746 return (di->flags & flag) && (node != di->node);
749 /* Dump T, and all its children, on STREAM. */
751 void
752 dump_node (t, flags, stream)
753 tree t;
754 int flags;
755 FILE *stream;
757 struct dump_info di;
758 dump_queue_p dq;
759 dump_queue_p next_dq;
761 /* Initialize the dump-information structure. */
762 di.stream = stream;
763 di.index = 0;
764 di.column = 0;
765 di.queue = 0;
766 di.queue_end = 0;
767 di.free_list = 0;
768 di.flags = flags;
769 di.node = t;
770 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
771 (splay_tree_delete_value_fn) &free);
773 /* Queue up the first node. */
774 queue (&di, t, DUMP_NONE);
776 /* Until the queue is empty, keep dumping nodes. */
777 while (di.queue)
778 dequeue_and_dump (&di);
780 /* Now, clean up. */
781 for (dq = di.free_list; dq; dq = next_dq)
783 next_dq = dq->next;
784 free (dq);
786 splay_tree_delete (di.nodes);
789 /* Define a tree dump switch. */
790 struct dump_file_info
792 const char *suffix; /* suffix to give output file. */
793 const char *swtch; /* command line switch */
794 int flags; /* user flags */
795 int state; /* state of play */
798 /* Table of tree dump switches. This must be consistent with the
799 TREE_DUMP_INDEX enumeration in c-common.h */
800 static struct dump_file_info dump_files[TDI_end] =
802 {".tu", "dump-translation-unit", 0, 0},
803 {".class", "dump-class-hierarchy", 0, 0},
804 {".original", "dump-tree-original", 0, 0},
805 {".optimized", "dump-tree-optimized", 0, 0},
806 {".inlined", "dump-tree-inlined", 0, 0},
809 /* Define a name->number mapping for a dump flag value. */
810 struct dump_option_value_info
812 const char *const name; /* the name of the value */
813 const int value; /* the value of the name */
816 /* Table of dump options. This must be consistent with the TDF_* flags
817 in c-common.h */
818 static const struct dump_option_value_info dump_options[] =
820 {"address", TDF_ADDRESS},
821 {"slim", TDF_SLIM},
822 {"all", ~0},
823 {NULL, 0}
826 /* Begin a tree dump for PHASE. Stores any user supplied flag in
827 *FLAG_PTR and returns a stream to write to. If the dump is not
828 enabled, returns NULL.
829 Multiple calls will reopen and append to the dump file. */
831 FILE *
832 dump_begin (phase, flag_ptr)
833 enum tree_dump_index phase;
834 int *flag_ptr;
836 FILE *stream;
837 char *name;
839 if (!dump_files[phase].state)
840 return NULL;
842 name = concat (dump_base_name, dump_files[phase].suffix, NULL);
843 stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
844 if (!stream)
845 error ("could not open dump file `%s'", name);
846 else
847 dump_files[phase].state = 1;
848 free (name);
849 if (flag_ptr)
850 *flag_ptr = dump_files[phase].flags;
852 return stream;
855 /* Returns non-zero if tree dump PHASE is enabled. */
858 dump_enabled_p (phase)
859 enum tree_dump_index phase;
861 return dump_files[phase].state;
864 /* Returns the switch name of PHASE. */
866 const char *
867 dump_flag_name (phase)
868 enum tree_dump_index phase;
870 return dump_files[phase].swtch;
873 /* Finish a tree dump for PHASE. STREAM is the stream created by
874 dump_begin. */
876 void
877 dump_end (phase, stream)
878 enum tree_dump_index phase ATTRIBUTE_UNUSED;
879 FILE *stream;
881 fclose (stream);
884 /* Parse ARG as a dump switch. Return non-zero if it is, and store the
885 relevant details in the dump_files array. */
888 dump_switch_p (arg)
889 const char *arg;
891 unsigned ix;
892 const char *option_value;
894 for (ix = 0; ix != TDI_end; ix++)
895 if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
897 const char *ptr = option_value;
898 int flags = 0;
900 while (*ptr)
902 const struct dump_option_value_info *option_ptr;
903 const char *end_ptr;
904 unsigned length;
906 while (*ptr == '-')
907 ptr++;
908 end_ptr = strchr (ptr, '-');
909 if (!end_ptr)
910 end_ptr = ptr + strlen (ptr);
911 length = end_ptr - ptr;
913 for (option_ptr = dump_options; option_ptr->name;
914 option_ptr++)
915 if (strlen (option_ptr->name) == length
916 && !memcmp (option_ptr->name, ptr, length))
918 flags |= option_ptr->value;
919 goto found;
921 warning ("ignoring unknown option `%.*s' in `-f%s'",
922 length, ptr, dump_files[ix].swtch);
923 found:;
924 ptr = end_ptr;
927 dump_files[ix].state = -1;
928 dump_files[ix].flags = flags;
930 return 1;
932 return 0;