typeck2.c (store_init_value): Don't re-digest a bracketed initializer.
[gcc.git] / gcc / c-dump.c
1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3 Written by Mark Mitchell <mark@codesourcery.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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. */
21
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"
30
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. */
34
35 dump_tree_fn lang_dump_tree;
36
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 *));
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
48 queue (di, t, flags)
49 dump_info_p di;
50 tree t;
51 int flags;
52 {
53 dump_queue_p dq;
54 dump_node_info_p dni;
55 unsigned int index;
56
57 /* Assign the next available index to T. */
58 index = ++di->index;
59
60 /* Obtain a new queue node. */
61 if (di->free_list)
62 {
63 dq = di->free_list;
64 di->free_list = dq->next;
65 }
66 else
67 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
68
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);
75
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;
83
84 /* Return the index. */
85 return index;
86 }
87
88 static void
89 dump_index (di, index)
90 dump_info_p di;
91 unsigned int index;
92 {
93 fprintf (di->stream, "@%-6u ", index);
94 di->column += 8;
95 }
96
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. */
100
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;
107 {
108 unsigned int index;
109 splay_tree_node n;
110
111 /* If there's no node, just return. This makes for fewer checks in
112 our callers. */
113 if (!t)
114 return;
115
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);
123
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);
129 }
130
131 /* Dump the type of T. */
132
133 void
134 queue_and_dump_type (di, t)
135 dump_info_p di;
136 tree t;
137 {
138 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
139 }
140
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. */
145
146 /* Insert a new line in the dump output, and indent to an appropriate
147 place to start printing more fields. */
148
149 static void
150 dump_new_line (di)
151 dump_info_p di;
152 {
153 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
154 di->column = SOL_COLUMN;
155 }
156
157 /* If necessary, insert a new line. */
158
159 static void
160 dump_maybe_newline (di)
161 dump_info_p di;
162 {
163 int extra;
164
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)
170 {
171 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
172 di->column += COLUMN_ALIGNMENT - extra;
173 }
174 }
175
176 /* Dump pointer PTR using FIELD to identify it. */
177
178 void
179 dump_pointer (di, field, ptr)
180 dump_info_p di;
181 const char *field;
182 void *ptr;
183 {
184 dump_maybe_newline (di);
185 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
186 di->column += 15;
187 }
188
189 /* Dump integer I using FIELD to identify it. */
190
191 void
192 dump_int (di, field, i)
193 dump_info_p di;
194 const char *field;
195 int i;
196 {
197 dump_maybe_newline (di);
198 fprintf (di->stream, "%-4s: %-7d ", field, i);
199 di->column += 14;
200 }
201
202 /* Dump the string S. */
203
204 void
205 dump_string (di, string)
206 dump_info_p di;
207 const char *string;
208 {
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;
215 }
216
217 /* Dump the string field S. */
218
219 static void
220 dump_string_field (di, field, string)
221 dump_info_p di;
222 const char *field;
223 const char *string;
224 {
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;
231 }
232
233 /* Dump information common to statements from STMT. */
234
235 void
236 dump_stmt (di, t)
237 dump_info_p di;
238 tree t;
239 {
240 dump_int (di, "line", STMT_LINENO (t));
241 }
242
243 /* Dump the next statement after STMT. */
244
245 void
246 dump_next_stmt (di, t)
247 dump_info_p di;
248 tree t;
249 {
250 dump_child ("next", TREE_CHAIN (t));
251 }
252
253 /* Dump the next node in the queue. */
254
255 static void
256 dequeue_and_dump (di)
257 dump_info_p di;
258 {
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;
267
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;
274
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;
281
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;
291
292 /* Figure out what kind of node this is. */
293 code = TREE_CODE (t);
294 code_class = TREE_CODE_CLASS (code);
295
296 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
297 more informative. */
298 if (dni->binfo_p)
299 {
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");
308
309 dump_child ("type", BINFO_TYPE (t));
310 dump_child ("base", BINFO_BASETYPES (t));
311
312 goto done;
313 }
314
315 /* We can knock off a bunch of expression nodes in exactly the same
316 way. */
317 if (IS_EXPR_CODE_CLASS (code_class))
318 {
319 /* If we're dumping children, dump them now. */
320 queue_and_dump_type (di, t);
321
322 switch (code_class)
323 {
324 case '1':
325 dump_child ("op 0", TREE_OPERAND (t, 0));
326 break;
327
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;
333
334 case 'e':
335 /* These nodes are handled explicitly below. */
336 break;
337
338 default:
339 abort();
340 }
341 }
342 else if (DECL_P (t))
343 {
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))
355 {
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;
362
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;
367 }
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));
373 }
374 else if (code_class == 't')
375 {
376 /* All types have qualifiers. */
377 int quals = C_TYPE_QUALS (t);
378 if (quals != TYPE_UNQUALIFIED)
379 {
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;
385 }
386
387 /* All types have associated declarations. */
388 dump_child ("name", TYPE_NAME (t));
389
390 /* All types have a main variant. */
391 if (TYPE_MAIN_VARIANT (t) != t)
392 dump_child ("unql", TYPE_MAIN_VARIANT (t));
393
394 /* And sizes. */
395 dump_child ("size", TYPE_SIZE (t));
396
397 /* All types have alignments. */
398 dump_int (di, "algn", TYPE_ALIGN (t));
399 }
400 else if (code_class == 'c')
401 /* All constants can have types. */
402 queue_and_dump_type (di, t);
403
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;
409
410 /* Now handle the various kinds of nodes. */
411 switch (code)
412 {
413 int i;
414
415 case IDENTIFIER_NODE:
416 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
417 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
418 break;
419
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;
425
426 case TREE_VEC:
427 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
428 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
429 {
430 char buffer[32];
431 sprintf (buffer, "%u", i);
432 dump_child (buffer, TREE_VEC_ELT (t, i));
433 }
434 break;
435
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));
443
444 if (code == ENUMERAL_TYPE)
445 dump_child ("csts", TYPE_VALUES (t));
446 break;
447
448 case REAL_TYPE:
449 dump_int (di, "prec", TYPE_PRECISION (t));
450 break;
451
452 case POINTER_TYPE:
453 dump_child ("ptd", TREE_TYPE (t));
454 break;
455
456 case REFERENCE_TYPE:
457 dump_child ("refd", TREE_TYPE (t));
458 break;
459
460 case METHOD_TYPE:
461 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
462 /* Fall through. */
463
464 case FUNCTION_TYPE:
465 dump_child ("retn", TREE_TYPE (t));
466 dump_child ("prms", TYPE_ARG_TYPES (t));
467 break;
468
469 case ARRAY_TYPE:
470 dump_child ("elts", TREE_TYPE (t));
471 dump_child ("domn", TYPE_DOMAIN (t));
472 break;
473
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");
480
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;
486
487 case CONST_DECL:
488 dump_child ("cnst", DECL_INITIAL (t));
489 break;
490
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));
501
502 if (TREE_CODE (t) == FIELD_DECL)
503 {
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));
508 }
509 else if (TREE_CODE (t) == VAR_DECL
510 || TREE_CODE (t) == PARM_DECL)
511 {
512 dump_int (di, "used", TREE_USED (t));
513 if (DECL_REGISTER (t))
514 dump_string (di, "register");
515 }
516 break;
517
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;
529
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;
540
541 case BREAK_STMT:
542 case CONTINUE_STMT:
543 dump_stmt (di, t);
544 dump_next_stmt (di, t);
545 break;
546
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;
554
555 case COMPOUND_STMT:
556 dump_stmt (di, t);
557 dump_child ("body", COMPOUND_BODY (t));
558 dump_next_stmt (di, t);
559 break;
560
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;
566
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;
573
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;
579
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;
588
589 case GOTO_STMT:
590 dump_stmt (di, t);
591 dump_child ("dest", GOTO_DESTINATION (t));
592 dump_next_stmt (di, t);
593 break;
594
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;
602
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;
608
609 case RETURN_STMT:
610 dump_stmt (di, t);
611 dump_child ("expr", RETURN_EXPR (t));
612 dump_next_stmt (di, t);
613 break;
614
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;
621
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;
628
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;
641
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;
647
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;
652
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;
661
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;
677
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;
683
684 case CALL_EXPR:
685 dump_child ("fn", TREE_OPERAND (t, 0));
686 dump_child ("args", TREE_OPERAND (t, 1));
687 break;
688
689 case CONSTRUCTOR:
690 dump_child ("elts", TREE_OPERAND (t, 1));
691 break;
692
693 case STMT_EXPR:
694 dump_child ("stmt", STMT_EXPR_STMT (t));
695 break;
696
697 case BIND_EXPR:
698 dump_child ("vars", TREE_OPERAND (t, 0));
699 dump_child ("body", TREE_OPERAND (t, 1));
700 break;
701
702 case LOOP_EXPR:
703 dump_child ("body", TREE_OPERAND (t, 0));
704 break;
705
706 case EXIT_EXPR:
707 dump_child ("cond", TREE_OPERAND (t, 0));
708 break;
709
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;
720
721 case EXPR_WITH_FILE_LOCATION:
722 dump_child ("expr", EXPR_WFL_NODE (t));
723 break;
724
725 default:
726 /* There are no additional fields to print. */
727 break;
728 }
729
730 done:
731 if (dump_flag (di, TDF_ADDRESS, NULL))
732 dump_pointer (di, "addr", (void *)t);
733
734 /* Terminate the line. */
735 fprintf (di->stream, "\n");
736 }
737
738 /* Return non-zero if FLAG has been specified for the dump, and NODE
739 is not the root node of the dump. */
740
741 int dump_flag (di, flag, node)
742 dump_info_p di;
743 int flag;
744 tree node;
745 {
746 return (di->flags & flag) && (node != di->node);
747 }
748
749 /* Dump T, and all its children, on STREAM. */
750
751 void
752 dump_node (t, flags, stream)
753 tree t;
754 int flags;
755 FILE *stream;
756 {
757 struct dump_info di;
758 dump_queue_p dq;
759 dump_queue_p next_dq;
760
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);
772
773 /* Queue up the first node. */
774 queue (&di, t, DUMP_NONE);
775
776 /* Until the queue is empty, keep dumping nodes. */
777 while (di.queue)
778 dequeue_and_dump (&di);
779
780 /* Now, clean up. */
781 for (dq = di.free_list; dq; dq = next_dq)
782 {
783 next_dq = dq->next;
784 free (dq);
785 }
786 splay_tree_delete (di.nodes);
787 }
788
789 /* Define a tree dump switch. */
790 struct dump_file_info
791 {
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 */
796 };
797
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] =
801 {
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},
807 };
808
809 /* Define a name->number mapping for a dump flag value. */
810 struct dump_option_value_info
811 {
812 const char *const name; /* the name of the value */
813 const int value; /* the value of the name */
814 };
815
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[] =
819 {
820 {"address", TDF_ADDRESS},
821 {"slim", TDF_SLIM},
822 {"all", ~0},
823 {NULL, 0}
824 };
825
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. */
830
831 FILE *
832 dump_begin (phase, flag_ptr)
833 enum tree_dump_index phase;
834 int *flag_ptr;
835 {
836 FILE *stream;
837 char *name;
838
839 if (!dump_files[phase].state)
840 return NULL;
841
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;
851
852 return stream;
853 }
854
855 /* Returns non-zero if tree dump PHASE is enabled. */
856
857 int
858 dump_enabled_p (phase)
859 enum tree_dump_index phase;
860 {
861 return dump_files[phase].state;
862 }
863
864 /* Returns the switch name of PHASE. */
865
866 const char *
867 dump_flag_name (phase)
868 enum tree_dump_index phase;
869 {
870 return dump_files[phase].swtch;
871 }
872
873 /* Finish a tree dump for PHASE. STREAM is the stream created by
874 dump_begin. */
875
876 void
877 dump_end (phase, stream)
878 enum tree_dump_index phase ATTRIBUTE_UNUSED;
879 FILE *stream;
880 {
881 fclose (stream);
882 }
883
884 /* Parse ARG as a dump switch. Return non-zero if it is, and store the
885 relevant details in the dump_files array. */
886
887 int
888 dump_switch_p (arg)
889 const char *arg;
890 {
891 unsigned ix;
892 const char *option_value;
893
894 for (ix = 0; ix != TDI_end; ix++)
895 if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
896 {
897 const char *ptr = option_value;
898 int flags = 0;
899
900 while (*ptr)
901 {
902 const struct dump_option_value_info *option_ptr;
903 const char *end_ptr;
904 unsigned length;
905
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;
912
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))
917 {
918 flags |= option_ptr->value;
919 goto found;
920 }
921 warning ("ignoring unknown option `%.*s' in `-f%s'",
922 length, ptr, dump_files[ix].swtch);
923 found:;
924 ptr = end_ptr;
925 }
926
927 dump_files[ix].state = -1;
928 dump_files[ix].flags = flags;
929
930 return 1;
931 }
932 return 0;
933 }