re PR c++/7386 (ran gcc compiler and it said to report htebug)
[official-gcc.git] / gcc / tree-dump.c
blob5b9f4f58ab6f87a7ad55affed3adf016ac2c5b7f
1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999, 2000, 2002 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 "splay-tree.h"
26 #include "diagnostic.h"
27 #include "toplev.h"
28 #include "tree-dump.h"
29 #include "langhooks.h"
31 static unsigned int queue PARAMS ((dump_info_p, tree, int));
32 static void dump_index PARAMS ((dump_info_p, unsigned int));
33 static void dequeue_and_dump PARAMS ((dump_info_p));
34 static void dump_new_line PARAMS ((dump_info_p));
35 static void dump_maybe_newline PARAMS ((dump_info_p));
36 static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
38 /* Add T to the end of the queue of nodes to dump. Returns the index
39 assigned to T. */
41 static unsigned int
42 queue (di, t, flags)
43 dump_info_p di;
44 tree t;
45 int flags;
47 dump_queue_p dq;
48 dump_node_info_p dni;
49 unsigned int index;
51 /* Assign the next available index to T. */
52 index = ++di->index;
54 /* Obtain a new queue node. */
55 if (di->free_list)
57 dq = di->free_list;
58 di->free_list = dq->next;
60 else
61 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
63 /* Create a new entry in the splay-tree. */
64 dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
65 dni->index = index;
66 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
67 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
68 (splay_tree_value) dni);
70 /* Add it to the end of the queue. */
71 dq->next = 0;
72 if (!di->queue_end)
73 di->queue = dq;
74 else
75 di->queue_end->next = dq;
76 di->queue_end = dq;
78 /* Return the index. */
79 return index;
82 static void
83 dump_index (di, index)
84 dump_info_p di;
85 unsigned int index;
87 fprintf (di->stream, "@%-6u ", index);
88 di->column += 8;
91 /* If T has not already been output, queue it for subsequent output.
92 FIELD is a string to print before printing the index. Then, the
93 index of T is printed. */
95 void
96 queue_and_dump_index (di, field, t, flags)
97 dump_info_p di;
98 const char *field;
99 tree t;
100 int flags;
102 unsigned int index;
103 splay_tree_node n;
105 /* If there's no node, just return. This makes for fewer checks in
106 our callers. */
107 if (!t)
108 return;
110 /* See if we've already queued or dumped this node. */
111 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
112 if (n)
113 index = ((dump_node_info_p) n->value)->index;
114 else
115 /* If we haven't, add it to the queue. */
116 index = queue (di, t, flags);
118 /* Print the index of the node. */
119 dump_maybe_newline (di);
120 fprintf (di->stream, "%-4s: ", field);
121 di->column += 6;
122 dump_index (di, index);
125 /* Dump the type of T. */
127 void
128 queue_and_dump_type (di, t)
129 dump_info_p di;
130 tree t;
132 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
135 /* Dump column control */
136 #define SOL_COLUMN 25 /* Start of line column. */
137 #define EOL_COLUMN 55 /* End of line column. */
138 #define COLUMN_ALIGNMENT 15 /* Alignment. */
140 /* Insert a new line in the dump output, and indent to an appropriate
141 place to start printing more fields. */
143 static void
144 dump_new_line (di)
145 dump_info_p di;
147 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
148 di->column = SOL_COLUMN;
151 /* If necessary, insert a new line. */
153 static void
154 dump_maybe_newline (di)
155 dump_info_p di;
157 int extra;
159 /* See if we need a new line. */
160 if (di->column > EOL_COLUMN)
161 dump_new_line (di);
162 /* See if we need any padding. */
163 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
165 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
166 di->column += COLUMN_ALIGNMENT - extra;
170 /* Dump pointer PTR using FIELD to identify it. */
172 void
173 dump_pointer (di, field, ptr)
174 dump_info_p di;
175 const char *field;
176 void *ptr;
178 dump_maybe_newline (di);
179 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
180 di->column += 15;
183 /* Dump integer I using FIELD to identify it. */
185 void
186 dump_int (di, field, i)
187 dump_info_p di;
188 const char *field;
189 int i;
191 dump_maybe_newline (di);
192 fprintf (di->stream, "%-4s: %-7d ", field, i);
193 di->column += 14;
196 /* Dump the string S. */
198 void
199 dump_string (di, string)
200 dump_info_p di;
201 const char *string;
203 dump_maybe_newline (di);
204 fprintf (di->stream, "%-13s ", string);
205 if (strlen (string) > 13)
206 di->column += strlen (string) + 1;
207 else
208 di->column += 14;
211 /* Dump the string field S. */
213 static void
214 dump_string_field (di, field, string)
215 dump_info_p di;
216 const char *field;
217 const char *string;
219 dump_maybe_newline (di);
220 fprintf (di->stream, "%-4s: %-7s ", field, string);
221 if (strlen (string) > 7)
222 di->column += 6 + strlen (string) + 1;
223 else
224 di->column += 14;
227 /* Dump the next node in the queue. */
229 static void
230 dequeue_and_dump (di)
231 dump_info_p di;
233 dump_queue_p dq;
234 splay_tree_node stn;
235 dump_node_info_p dni;
236 tree t;
237 unsigned int index;
238 enum tree_code code;
239 char code_class;
240 const char* code_name;
242 /* Get the next node from the queue. */
243 dq = di->queue;
244 stn = dq->node;
245 t = (tree) stn->key;
246 dni = (dump_node_info_p) stn->value;
247 index = dni->index;
249 /* Remove the node from the queue, and put it on the free list. */
250 di->queue = dq->next;
251 if (!di->queue)
252 di->queue_end = 0;
253 dq->next = di->free_list;
254 di->free_list = dq;
256 /* Print the node index. */
257 dump_index (di, index);
258 /* And the type of node this is. */
259 if (dni->binfo_p)
260 code_name = "binfo";
261 else
262 code_name = tree_code_name[(int) TREE_CODE (t)];
263 fprintf (di->stream, "%-16s ", code_name);
264 di->column = 25;
266 /* Figure out what kind of node this is. */
267 code = TREE_CODE (t);
268 code_class = TREE_CODE_CLASS (code);
270 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
271 more informative. */
272 if (dni->binfo_p)
274 if (TREE_VIA_PUBLIC (t))
275 dump_string (di, "pub");
276 else if (TREE_VIA_PROTECTED (t))
277 dump_string (di, "prot");
278 else if (TREE_VIA_PRIVATE (t))
279 dump_string (di, "priv");
280 if (TREE_VIA_VIRTUAL (t))
281 dump_string (di, "virt");
283 dump_child ("type", BINFO_TYPE (t));
284 dump_child ("base", BINFO_BASETYPES (t));
286 goto done;
289 /* We can knock off a bunch of expression nodes in exactly the same
290 way. */
291 if (IS_EXPR_CODE_CLASS (code_class))
293 /* If we're dumping children, dump them now. */
294 queue_and_dump_type (di, t);
296 switch (code_class)
298 case '1':
299 dump_child ("op 0", TREE_OPERAND (t, 0));
300 break;
302 case '2':
303 case '<':
304 dump_child ("op 0", TREE_OPERAND (t, 0));
305 dump_child ("op 1", TREE_OPERAND (t, 1));
306 break;
308 case 'e':
309 /* These nodes are handled explicitly below. */
310 break;
312 default:
313 abort ();
316 else if (DECL_P (t))
318 /* All declarations have names. */
319 if (DECL_NAME (t))
320 dump_child ("name", DECL_NAME (t));
321 if (DECL_ASSEMBLER_NAME_SET_P (t)
322 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
323 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
324 /* And types. */
325 queue_and_dump_type (di, t);
326 dump_child ("scpe", DECL_CONTEXT (t));
327 /* And a source position. */
328 if (DECL_SOURCE_FILE (t))
330 const char *filename = strrchr (DECL_SOURCE_FILE (t), '/');
331 if (!filename)
332 filename = DECL_SOURCE_FILE (t);
333 else
334 /* Skip the slash. */
335 ++filename;
337 dump_maybe_newline (di);
338 fprintf (di->stream, "srcp: %s:%-6d ", filename,
339 DECL_SOURCE_LINE (t));
340 di->column += 6 + strlen (filename) + 8;
342 /* And any declaration can be compiler-generated. */
343 if (DECL_ARTIFICIAL (t))
344 dump_string (di, "artificial");
345 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
346 dump_child ("chan", TREE_CHAIN (t));
348 else if (code_class == 't')
350 /* All types have qualifiers. */
351 int quals = (*lang_hooks.tree_dump.type_quals) (t);
353 if (quals != TYPE_UNQUALIFIED)
355 fprintf (di->stream, "qual: %c%c%c ",
356 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
357 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
358 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
359 di->column += 14;
362 /* All types have associated declarations. */
363 dump_child ("name", TYPE_NAME (t));
365 /* All types have a main variant. */
366 if (TYPE_MAIN_VARIANT (t) != t)
367 dump_child ("unql", TYPE_MAIN_VARIANT (t));
369 /* And sizes. */
370 dump_child ("size", TYPE_SIZE (t));
372 /* All types have alignments. */
373 dump_int (di, "algn", TYPE_ALIGN (t));
375 else if (code_class == 'c')
376 /* All constants can have types. */
377 queue_and_dump_type (di, t);
379 /* Give the language-specific code a chance to print something. If
380 it's completely taken care of things, don't bother printing
381 anything more ourselves. */
382 if ((*lang_hooks.tree_dump.dump_tree) (di, t))
383 goto done;
385 /* Now handle the various kinds of nodes. */
386 switch (code)
388 int i;
390 case IDENTIFIER_NODE:
391 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
392 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
393 break;
395 case TREE_LIST:
396 dump_child ("purp", TREE_PURPOSE (t));
397 dump_child ("valu", TREE_VALUE (t));
398 dump_child ("chan", TREE_CHAIN (t));
399 break;
401 case TREE_VEC:
402 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
403 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
405 char buffer[32];
406 sprintf (buffer, "%u", i);
407 dump_child (buffer, TREE_VEC_ELT (t, i));
409 break;
411 case INTEGER_TYPE:
412 case ENUMERAL_TYPE:
413 dump_int (di, "prec", TYPE_PRECISION (t));
414 if (TREE_UNSIGNED (t))
415 dump_string (di, "unsigned");
416 dump_child ("min", TYPE_MIN_VALUE (t));
417 dump_child ("max", TYPE_MAX_VALUE (t));
419 if (code == ENUMERAL_TYPE)
420 dump_child ("csts", TYPE_VALUES (t));
421 break;
423 case REAL_TYPE:
424 dump_int (di, "prec", TYPE_PRECISION (t));
425 break;
427 case POINTER_TYPE:
428 dump_child ("ptd", TREE_TYPE (t));
429 break;
431 case REFERENCE_TYPE:
432 dump_child ("refd", TREE_TYPE (t));
433 break;
435 case METHOD_TYPE:
436 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
437 /* Fall through. */
439 case FUNCTION_TYPE:
440 dump_child ("retn", TREE_TYPE (t));
441 dump_child ("prms", TYPE_ARG_TYPES (t));
442 break;
444 case ARRAY_TYPE:
445 dump_child ("elts", TREE_TYPE (t));
446 dump_child ("domn", TYPE_DOMAIN (t));
447 break;
449 case RECORD_TYPE:
450 case UNION_TYPE:
451 if (TREE_CODE (t) == RECORD_TYPE)
452 dump_string (di, "struct");
453 else
454 dump_string (di, "union");
456 dump_child ("flds", TYPE_FIELDS (t));
457 dump_child ("fncs", TYPE_METHODS (t));
458 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
459 DUMP_BINFO);
460 break;
462 case CONST_DECL:
463 dump_child ("cnst", DECL_INITIAL (t));
464 break;
466 case VAR_DECL:
467 case PARM_DECL:
468 case FIELD_DECL:
469 case RESULT_DECL:
470 if (TREE_CODE (t) == PARM_DECL)
471 dump_child ("argt", DECL_ARG_TYPE (t));
472 else
473 dump_child ("init", DECL_INITIAL (t));
474 dump_child ("size", DECL_SIZE (t));
475 dump_int (di, "algn", DECL_ALIGN (t));
477 if (TREE_CODE (t) == FIELD_DECL)
479 if (DECL_FIELD_OFFSET (t))
480 dump_child ("bpos", bit_position (t));
482 else if (TREE_CODE (t) == VAR_DECL
483 || TREE_CODE (t) == PARM_DECL)
485 dump_int (di, "used", TREE_USED (t));
486 if (DECL_REGISTER (t))
487 dump_string (di, "register");
489 break;
491 case FUNCTION_DECL:
492 dump_child ("args", DECL_ARGUMENTS (t));
493 if (DECL_EXTERNAL (t))
494 dump_string (di, "undefined");
495 if (TREE_PUBLIC (t))
496 dump_string (di, "extern");
497 else
498 dump_string (di, "static");
499 if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
500 dump_child ("body", DECL_SAVED_TREE (t));
501 break;
503 case INTEGER_CST:
504 if (TREE_INT_CST_HIGH (t))
505 dump_int (di, "high", TREE_INT_CST_HIGH (t));
506 dump_int (di, "low", TREE_INT_CST_LOW (t));
507 break;
509 case STRING_CST:
510 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
511 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
512 break;
514 case TRUTH_NOT_EXPR:
515 case ADDR_EXPR:
516 case INDIRECT_REF:
517 case CLEANUP_POINT_EXPR:
518 case SAVE_EXPR:
519 /* These nodes are unary, but do not have code class `1'. */
520 dump_child ("op 0", TREE_OPERAND (t, 0));
521 break;
523 case TRUTH_ANDIF_EXPR:
524 case TRUTH_ORIF_EXPR:
525 case INIT_EXPR:
526 case MODIFY_EXPR:
527 case COMPONENT_REF:
528 case COMPOUND_EXPR:
529 case ARRAY_REF:
530 case PREDECREMENT_EXPR:
531 case PREINCREMENT_EXPR:
532 case POSTDECREMENT_EXPR:
533 case POSTINCREMENT_EXPR:
534 /* These nodes are binary, but do not have code class `2'. */
535 dump_child ("op 0", TREE_OPERAND (t, 0));
536 dump_child ("op 1", TREE_OPERAND (t, 1));
537 break;
539 case COND_EXPR:
540 dump_child ("op 0", TREE_OPERAND (t, 0));
541 dump_child ("op 1", TREE_OPERAND (t, 1));
542 dump_child ("op 2", TREE_OPERAND (t, 2));
543 break;
545 case CALL_EXPR:
546 dump_child ("fn", TREE_OPERAND (t, 0));
547 dump_child ("args", TREE_OPERAND (t, 1));
548 break;
550 case CONSTRUCTOR:
551 dump_child ("elts", TREE_OPERAND (t, 1));
552 break;
554 case BIND_EXPR:
555 dump_child ("vars", TREE_OPERAND (t, 0));
556 dump_child ("body", TREE_OPERAND (t, 1));
557 break;
559 case LOOP_EXPR:
560 dump_child ("body", TREE_OPERAND (t, 0));
561 break;
563 case EXIT_EXPR:
564 dump_child ("cond", TREE_OPERAND (t, 0));
565 break;
567 case TARGET_EXPR:
568 dump_child ("decl", TREE_OPERAND (t, 0));
569 dump_child ("init", TREE_OPERAND (t, 1));
570 dump_child ("clnp", TREE_OPERAND (t, 2));
571 /* There really are two possible places the initializer can be.
572 After RTL expansion, the second operand is moved to the
573 position of the fourth operand, and the second operand
574 becomes NULL. */
575 dump_child ("init", TREE_OPERAND (t, 3));
576 break;
578 case EXPR_WITH_FILE_LOCATION:
579 dump_child ("expr", EXPR_WFL_NODE (t));
580 break;
582 default:
583 /* There are no additional fields to print. */
584 break;
587 done:
588 if (dump_flag (di, TDF_ADDRESS, NULL))
589 dump_pointer (di, "addr", (void *)t);
591 /* Terminate the line. */
592 fprintf (di->stream, "\n");
595 /* Return nonzero if FLAG has been specified for the dump, and NODE
596 is not the root node of the dump. */
598 int dump_flag (di, flag, node)
599 dump_info_p di;
600 int flag;
601 tree node;
603 return (di->flags & flag) && (node != di->node);
606 /* Dump T, and all its children, on STREAM. */
608 void
609 dump_node (t, flags, stream)
610 tree t;
611 int flags;
612 FILE *stream;
614 struct dump_info di;
615 dump_queue_p dq;
616 dump_queue_p next_dq;
618 /* Initialize the dump-information structure. */
619 di.stream = stream;
620 di.index = 0;
621 di.column = 0;
622 di.queue = 0;
623 di.queue_end = 0;
624 di.free_list = 0;
625 di.flags = flags;
626 di.node = t;
627 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
628 (splay_tree_delete_value_fn) &free);
630 /* Queue up the first node. */
631 queue (&di, t, DUMP_NONE);
633 /* Until the queue is empty, keep dumping nodes. */
634 while (di.queue)
635 dequeue_and_dump (&di);
637 /* Now, clean up. */
638 for (dq = di.free_list; dq; dq = next_dq)
640 next_dq = dq->next;
641 free (dq);
643 splay_tree_delete (di.nodes);
646 /* Define a tree dump switch. */
647 struct dump_file_info
649 const char *const suffix; /* suffix to give output file. */
650 const char *const swtch; /* command line switch */
651 int flags; /* user flags */
652 int state; /* state of play */
655 /* Table of tree dump switches. This must be consistent with the
656 TREE_DUMP_INDEX enumeration in tree.h */
657 static struct dump_file_info dump_files[TDI_end] =
659 {".tu", "dump-translation-unit", 0, 0},
660 {".class", "dump-class-hierarchy", 0, 0},
661 {".original", "dump-tree-original", 0, 0},
662 {".optimized", "dump-tree-optimized", 0, 0},
663 {".inlined", "dump-tree-inlined", 0, 0},
666 /* Define a name->number mapping for a dump flag value. */
667 struct dump_option_value_info
669 const char *const name; /* the name of the value */
670 const int value; /* the value of the name */
673 /* Table of dump options. This must be consistent with the TDF_* flags
674 in tree.h */
675 static const struct dump_option_value_info dump_options[] =
677 {"address", TDF_ADDRESS},
678 {"slim", TDF_SLIM},
679 {"all", ~0},
680 {NULL, 0}
683 /* Begin a tree dump for PHASE. Stores any user supplied flag in
684 *FLAG_PTR and returns a stream to write to. If the dump is not
685 enabled, returns NULL.
686 Multiple calls will reopen and append to the dump file. */
688 FILE *
689 dump_begin (phase, flag_ptr)
690 enum tree_dump_index phase;
691 int *flag_ptr;
693 FILE *stream;
694 char *name;
696 if (!dump_files[phase].state)
697 return NULL;
699 name = concat (dump_base_name, dump_files[phase].suffix, NULL);
700 stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
701 if (!stream)
702 error ("could not open dump file `%s'", name);
703 else
704 dump_files[phase].state = 1;
705 free (name);
706 if (flag_ptr)
707 *flag_ptr = dump_files[phase].flags;
709 return stream;
712 /* Returns nonzero if tree dump PHASE is enabled. */
715 dump_enabled_p (phase)
716 enum tree_dump_index phase;
718 return dump_files[phase].state;
721 /* Returns the switch name of PHASE. */
723 const char *
724 dump_flag_name (phase)
725 enum tree_dump_index phase;
727 return dump_files[phase].swtch;
730 /* Finish a tree dump for PHASE. STREAM is the stream created by
731 dump_begin. */
733 void
734 dump_end (phase, stream)
735 enum tree_dump_index phase ATTRIBUTE_UNUSED;
736 FILE *stream;
738 fclose (stream);
741 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
742 relevant details in the dump_files array. */
745 dump_switch_p (arg)
746 const char *arg;
748 unsigned ix;
749 const char *option_value;
751 for (ix = 0; ix != TDI_end; ix++)
752 if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
754 const char *ptr = option_value;
755 int flags = 0;
757 while (*ptr)
759 const struct dump_option_value_info *option_ptr;
760 const char *end_ptr;
761 unsigned length;
763 while (*ptr == '-')
764 ptr++;
765 end_ptr = strchr (ptr, '-');
766 if (!end_ptr)
767 end_ptr = ptr + strlen (ptr);
768 length = end_ptr - ptr;
770 for (option_ptr = dump_options; option_ptr->name;
771 option_ptr++)
772 if (strlen (option_ptr->name) == length
773 && !memcmp (option_ptr->name, ptr, length))
775 flags |= option_ptr->value;
776 goto found;
778 warning ("ignoring unknown option `%.*s' in `-f%s'",
779 length, ptr, dump_files[ix].swtch);
780 found:;
781 ptr = end_ptr;
784 dump_files[ix].state = -1;
785 dump_files[ix].flags = flags;
787 return 1;
789 return 0;