1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999-2013 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 3, or (at your option) any later
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
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
26 #include "splay-tree.h"
27 #include "filenames.h"
28 #include "tree-dump.h"
29 #include "langhooks.h"
30 #include "tree-iterator.h"
31 #include "tree-pretty-print.h"
32 #include "tree-flow.h"
34 static unsigned int queue (dump_info_p
, const_tree
, int);
35 static void dump_index (dump_info_p
, unsigned int);
36 static void dequeue_and_dump (dump_info_p
);
37 static void dump_new_line (dump_info_p
);
38 static void dump_maybe_newline (dump_info_p
);
40 /* Add T to the end of the queue of nodes to dump. Returns the index
44 queue (dump_info_p di
, const_tree t
, int flags
)
50 /* Assign the next available index to T. */
53 /* Obtain a new queue node. */
57 di
->free_list
= dq
->next
;
60 dq
= XNEW (struct dump_queue
);
62 /* Create a new entry in the splay-tree. */
63 dni
= XNEW (struct dump_node_info
);
65 dni
->binfo_p
= ((flags
& DUMP_BINFO
) != 0);
66 dq
->node
= splay_tree_insert (di
->nodes
, (splay_tree_key
) t
,
67 (splay_tree_value
) dni
);
69 /* Add it to the end of the queue. */
74 di
->queue_end
->next
= dq
;
77 /* Return the index. */
82 dump_index (dump_info_p di
, unsigned int index
)
84 fprintf (di
->stream
, "@%-6u ", index
);
88 /* If T has not already been output, queue it for subsequent output.
89 FIELD is a string to print before printing the index. Then, the
90 index of T is printed. */
93 queue_and_dump_index (dump_info_p di
, const char *field
, const_tree t
, int flags
)
98 /* If there's no node, just return. This makes for fewer checks in
103 /* See if we've already queued or dumped this node. */
104 n
= splay_tree_lookup (di
->nodes
, (splay_tree_key
) t
);
106 index
= ((dump_node_info_p
) n
->value
)->index
;
108 /* If we haven't, add it to the queue. */
109 index
= queue (di
, t
, flags
);
111 /* Print the index of the node. */
112 dump_maybe_newline (di
);
113 fprintf (di
->stream
, "%-4s: ", field
);
115 dump_index (di
, index
);
118 /* Dump the type of T. */
121 queue_and_dump_type (dump_info_p di
, const_tree t
)
123 queue_and_dump_index (di
, "type", TREE_TYPE (t
), DUMP_NONE
);
126 /* Dump column control */
127 #define SOL_COLUMN 25 /* Start of line column. */
128 #define EOL_COLUMN 55 /* End of line column. */
129 #define COLUMN_ALIGNMENT 15 /* Alignment. */
131 /* Insert a new line in the dump output, and indent to an appropriate
132 place to start printing more fields. */
135 dump_new_line (dump_info_p di
)
137 fprintf (di
->stream
, "\n%*s", SOL_COLUMN
, "");
138 di
->column
= SOL_COLUMN
;
141 /* If necessary, insert a new line. */
144 dump_maybe_newline (dump_info_p di
)
148 /* See if we need a new line. */
149 if (di
->column
> EOL_COLUMN
)
151 /* See if we need any padding. */
152 else if ((extra
= (di
->column
- SOL_COLUMN
) % COLUMN_ALIGNMENT
) != 0)
154 fprintf (di
->stream
, "%*s", COLUMN_ALIGNMENT
- extra
, "");
155 di
->column
+= COLUMN_ALIGNMENT
- extra
;
159 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
162 dump_function (int phase
, tree fn
)
167 stream
= dump_begin (phase
, &flags
);
170 dump_function_to_file (fn
, stream
, flags
);
171 dump_end (phase
, stream
);
175 /* Dump pointer PTR using FIELD to identify it. */
178 dump_pointer (dump_info_p di
, const char *field
, void *ptr
)
180 dump_maybe_newline (di
);
181 fprintf (di
->stream
, "%-4s: %-8" HOST_WIDE_INT_PRINT
"x ", field
,
182 (unsigned HOST_WIDE_INT
) (uintptr_t) ptr
);
186 /* Dump integer I using FIELD to identify it. */
189 dump_int (dump_info_p di
, const char *field
, int i
)
191 dump_maybe_newline (di
);
192 fprintf (di
->stream
, "%-4s: %-7d ", field
, i
);
196 /* Dump the floating point value R, using FIELD to identify it. */
199 dump_real (dump_info_p di
, const char *field
, const REAL_VALUE_TYPE
*r
)
202 real_to_decimal (buf
, r
, sizeof (buf
), 0, true);
203 dump_maybe_newline (di
);
204 fprintf (di
->stream
, "%-4s: %s ", field
, buf
);
205 di
->column
+= strlen (buf
) + 7;
208 /* Dump the fixed-point value F, using FIELD to identify it. */
211 dump_fixed (dump_info_p di
, const char *field
, const FIXED_VALUE_TYPE
*f
)
214 fixed_to_decimal (buf
, f
, sizeof (buf
));
215 dump_maybe_newline (di
);
216 fprintf (di
->stream
, "%-4s: %s ", field
, buf
);
217 di
->column
+= strlen (buf
) + 7;
221 /* Dump the string S. */
224 dump_string (dump_info_p di
, const char *string
)
226 dump_maybe_newline (di
);
227 fprintf (di
->stream
, "%-13s ", string
);
228 if (strlen (string
) > 13)
229 di
->column
+= strlen (string
) + 1;
234 /* Dump the string field S. */
237 dump_string_field (dump_info_p di
, const char *field
, const char *string
)
239 dump_maybe_newline (di
);
240 fprintf (di
->stream
, "%-4s: %-7s ", field
, string
);
241 if (strlen (string
) > 7)
242 di
->column
+= 6 + strlen (string
) + 1;
247 /* Dump the next node in the queue. */
250 dequeue_and_dump (dump_info_p di
)
254 dump_node_info_p dni
;
258 enum tree_code_class code_class
;
259 const char* code_name
;
261 /* Get the next node from the queue. */
265 dni
= (dump_node_info_p
) stn
->value
;
268 /* Remove the node from the queue, and put it on the free list. */
269 di
->queue
= dq
->next
;
272 dq
->next
= di
->free_list
;
275 /* Print the node index. */
276 dump_index (di
, index
);
277 /* And the type of node this is. */
281 code_name
= tree_code_name
[(int) TREE_CODE (t
)];
282 fprintf (di
->stream
, "%-16s ", code_name
);
285 /* Figure out what kind of node this is. */
286 code
= TREE_CODE (t
);
287 code_class
= TREE_CODE_CLASS (code
);
289 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
295 vec
<tree
, va_gc
> *accesses
= BINFO_BASE_ACCESSES (t
);
297 dump_child ("type", BINFO_TYPE (t
));
299 if (BINFO_VIRTUAL_P (t
))
300 dump_string_field (di
, "spec", "virt");
302 dump_int (di
, "bases", BINFO_N_BASE_BINFOS (t
));
303 for (ix
= 0; BINFO_BASE_ITERATE (t
, ix
, base
); ix
++)
305 tree access
= (accesses
? (*accesses
)[ix
] : access_public_node
);
306 const char *string
= NULL
;
308 if (access
== access_public_node
)
310 else if (access
== access_protected_node
)
312 else if (access
== access_private_node
)
317 dump_string_field (di
, "accs", string
);
318 queue_and_dump_index (di
, "binf", base
, DUMP_BINFO
);
324 /* We can knock off a bunch of expression nodes in exactly the same
326 if (IS_EXPR_CODE_CLASS (code_class
))
328 /* If we're dumping children, dump them now. */
329 queue_and_dump_type (di
, t
);
334 dump_child ("op 0", TREE_OPERAND (t
, 0));
339 dump_child ("op 0", TREE_OPERAND (t
, 0));
340 dump_child ("op 1", TREE_OPERAND (t
, 1));
347 /* These nodes are handled explicitly below. */
356 expanded_location xloc
;
357 /* All declarations have names. */
359 dump_child ("name", DECL_NAME (t
));
360 if (DECL_ASSEMBLER_NAME_SET_P (t
)
361 && DECL_ASSEMBLER_NAME (t
) != DECL_NAME (t
))
362 dump_child ("mngl", DECL_ASSEMBLER_NAME (t
));
363 if (DECL_ABSTRACT_ORIGIN (t
))
364 dump_child ("orig", DECL_ABSTRACT_ORIGIN (t
));
366 queue_and_dump_type (di
, t
);
367 dump_child ("scpe", DECL_CONTEXT (t
));
368 /* And a source position. */
369 xloc
= expand_location (DECL_SOURCE_LOCATION (t
));
372 const char *filename
= lbasename (xloc
.file
);
374 dump_maybe_newline (di
);
375 fprintf (di
->stream
, "srcp: %s:%-6d ", filename
,
377 di
->column
+= 6 + strlen (filename
) + 8;
379 /* And any declaration can be compiler-generated. */
380 if (CODE_CONTAINS_STRUCT (TREE_CODE (t
), TS_DECL_COMMON
)
381 && DECL_ARTIFICIAL (t
))
382 dump_string_field (di
, "note", "artificial");
383 if (DECL_CHAIN (t
) && !dump_flag (di
, TDF_SLIM
, NULL
))
384 dump_child ("chain", DECL_CHAIN (t
));
386 else if (code_class
== tcc_type
)
388 /* All types have qualifiers. */
389 int quals
= lang_hooks
.tree_dump
.type_quals (t
);
391 if (quals
!= TYPE_UNQUALIFIED
)
393 fprintf (di
->stream
, "qual: %c%c%c%c%c%c ",
394 (quals
& TYPE_QUAL_CONST
) ? 'c' : ' ',
395 (quals
& TYPE_QUAL_VOLATILE
) ? 'v' : ' ',
396 (quals
& TYPE_QUAL_RESTRICT
) ? 'r' : ' ',
397 (quals
& TYPE_QUAL_SHARED
) ? 's' : ' ',
398 (quals
& TYPE_QUAL_STRICT
) ? 't' : ' ',
399 (quals
& TYPE_QUAL_RELAXED
) ? 'x' : ' ');
403 /* All types have associated declarations. */
404 dump_child ("name", TYPE_NAME (t
));
406 /* All types have a main variant. */
407 if (TYPE_MAIN_VARIANT (t
) != t
)
408 dump_child ("unql", TYPE_MAIN_VARIANT (t
));
411 dump_child ("size", TYPE_SIZE (t
));
413 /* All types have alignments. */
414 dump_int (di
, "algn", TYPE_ALIGN (t
));
416 else if (code_class
== tcc_constant
)
417 /* All constants can have types. */
418 queue_and_dump_type (di
, t
);
420 /* Give the language-specific code a chance to print something. If
421 it's completely taken care of things, don't bother printing
422 anything more ourselves. */
423 if (lang_hooks
.tree_dump
.dump_tree (di
, t
))
426 /* Now handle the various kinds of nodes. */
431 case IDENTIFIER_NODE
:
432 dump_string_field (di
, "strg", IDENTIFIER_POINTER (t
));
433 dump_int (di
, "lngt", IDENTIFIER_LENGTH (t
));
437 dump_child ("purp", TREE_PURPOSE (t
));
438 dump_child ("valu", TREE_VALUE (t
));
439 dump_child ("chan", TREE_CHAIN (t
));
444 tree_stmt_iterator it
;
445 for (i
= 0, it
= tsi_start (t
); !tsi_end_p (it
); tsi_next (&it
), i
++)
448 sprintf (buffer
, "%u", i
);
449 dump_child (buffer
, tsi_stmt (it
));
455 dump_int (di
, "lngt", TREE_VEC_LENGTH (t
));
456 for (i
= 0; i
< TREE_VEC_LENGTH (t
); ++i
)
459 sprintf (buffer
, "%u", i
);
460 dump_child (buffer
, TREE_VEC_ELT (t
, i
));
466 dump_int (di
, "prec", TYPE_PRECISION (t
));
467 dump_string_field (di
, "sign", TYPE_UNSIGNED (t
) ? "unsigned": "signed");
468 dump_child ("min", TYPE_MIN_VALUE (t
));
469 dump_child ("max", TYPE_MAX_VALUE (t
));
471 if (code
== ENUMERAL_TYPE
)
472 dump_child ("csts", TYPE_VALUES (t
));
476 dump_int (di
, "prec", TYPE_PRECISION (t
));
479 case FIXED_POINT_TYPE
:
480 dump_int (di
, "prec", TYPE_PRECISION (t
));
481 dump_string_field (di
, "sign", TYPE_UNSIGNED (t
) ? "unsigned": "signed");
482 dump_string_field (di
, "saturating",
483 TYPE_SATURATING (t
) ? "saturating": "non-saturating");
487 dump_child ("ptd", TREE_TYPE (t
));
491 dump_child ("refd", TREE_TYPE (t
));
495 dump_child ("clas", TYPE_METHOD_BASETYPE (t
));
499 dump_child ("retn", TREE_TYPE (t
));
500 dump_child ("prms", TYPE_ARG_TYPES (t
));
504 dump_child ("elts", TREE_TYPE (t
));
505 dump_child ("domn", TYPE_DOMAIN (t
));
510 if (TREE_CODE (t
) == RECORD_TYPE
)
511 dump_string_field (di
, "tag", "struct");
513 dump_string_field (di
, "tag", "union");
515 dump_child ("flds", TYPE_FIELDS (t
));
516 dump_child ("fncs", TYPE_METHODS (t
));
517 queue_and_dump_index (di
, "binf", TYPE_BINFO (t
),
522 dump_child ("cnst", DECL_INITIAL (t
));
525 case DEBUG_EXPR_DECL
:
526 dump_int (di
, "-uid", DEBUG_TEMP_UID (t
));
533 if (TREE_CODE (t
) == PARM_DECL
)
534 dump_child ("argt", DECL_ARG_TYPE (t
));
536 dump_child ("init", DECL_INITIAL (t
));
537 dump_child ("size", DECL_SIZE (t
));
538 dump_int (di
, "algn", DECL_ALIGN (t
));
540 if (TREE_CODE (t
) == FIELD_DECL
)
542 if (DECL_FIELD_OFFSET (t
))
543 dump_child ("bpos", bit_position (t
));
545 else if (TREE_CODE (t
) == VAR_DECL
546 || TREE_CODE (t
) == PARM_DECL
)
548 dump_int (di
, "used", TREE_USED (t
));
549 if (DECL_REGISTER (t
))
550 dump_string_field (di
, "spec", "register");
555 dump_child ("args", DECL_ARGUMENTS (t
));
556 if (DECL_EXTERNAL (t
))
557 dump_string_field (di
, "body", "undefined");
559 dump_string_field (di
, "link", "extern");
561 dump_string_field (di
, "link", "static");
562 if (DECL_SAVED_TREE (t
) && !dump_flag (di
, TDF_SLIM
, t
))
563 dump_child ("body", DECL_SAVED_TREE (t
));
567 if (TREE_INT_CST_HIGH (t
))
568 dump_int (di
, "high", TREE_INT_CST_HIGH (t
));
569 dump_int (di
, "low", TREE_INT_CST_LOW (t
));
573 fprintf (di
->stream
, "strg: %-7s ", TREE_STRING_POINTER (t
));
574 dump_int (di
, "lngt", TREE_STRING_LENGTH (t
));
578 dump_real (di
, "valu", TREE_REAL_CST_PTR (t
));
582 dump_fixed (di
, "valu", TREE_FIXED_CST_PTR (t
));
588 case CLEANUP_POINT_EXPR
:
592 /* These nodes are unary, but do not have code class `1'. */
593 dump_child ("op 0", TREE_OPERAND (t
, 0));
596 case TRUTH_ANDIF_EXPR
:
597 case TRUTH_ORIF_EXPR
:
601 case PREDECREMENT_EXPR
:
602 case PREINCREMENT_EXPR
:
603 case POSTDECREMENT_EXPR
:
604 case POSTINCREMENT_EXPR
:
605 /* These nodes are binary, but do not have code class `2'. */
606 dump_child ("op 0", TREE_OPERAND (t
, 0));
607 dump_child ("op 1", TREE_OPERAND (t
, 1));
612 dump_child ("op 0", TREE_OPERAND (t
, 0));
613 dump_child ("op 1", TREE_OPERAND (t
, 1));
614 dump_child ("op 2", TREE_OPERAND (t
, 2));
618 case ARRAY_RANGE_REF
:
619 dump_child ("op 0", TREE_OPERAND (t
, 0));
620 dump_child ("op 1", TREE_OPERAND (t
, 1));
621 dump_child ("op 2", TREE_OPERAND (t
, 2));
622 dump_child ("op 3", TREE_OPERAND (t
, 3));
626 dump_child ("op 0", TREE_OPERAND (t
, 0));
627 dump_child ("op 1", TREE_OPERAND (t
, 1));
628 dump_child ("op 2", TREE_OPERAND (t
, 2));
631 case TRY_FINALLY_EXPR
:
632 dump_child ("op 0", TREE_OPERAND (t
, 0));
633 dump_child ("op 1", TREE_OPERAND (t
, 1));
640 call_expr_arg_iterator iter
;
641 dump_child ("fn", CALL_EXPR_FN (t
));
642 FOR_EACH_CALL_EXPR_ARG (arg
, iter
, t
)
645 sprintf (buffer
, "%u", i
);
646 dump_child (buffer
, arg
);
654 unsigned HOST_WIDE_INT cnt
;
656 dump_int (di
, "lngt", vec_safe_length (CONSTRUCTOR_ELTS (t
)));
657 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t
), cnt
, index
, value
)
659 dump_child ("idx", index
);
660 dump_child ("val", value
);
666 dump_child ("vars", TREE_OPERAND (t
, 0));
667 dump_child ("body", TREE_OPERAND (t
, 1));
671 dump_child ("body", TREE_OPERAND (t
, 0));
675 dump_child ("cond", TREE_OPERAND (t
, 0));
679 dump_child ("expr", TREE_OPERAND (t
, 0));
683 dump_child ("decl", TREE_OPERAND (t
, 0));
684 dump_child ("init", TREE_OPERAND (t
, 1));
685 dump_child ("clnp", TREE_OPERAND (t
, 2));
686 /* There really are two possible places the initializer can be.
687 After RTL expansion, the second operand is moved to the
688 position of the fourth operand, and the second operand
690 dump_child ("init", TREE_OPERAND (t
, 3));
693 case CASE_LABEL_EXPR
:
694 dump_child ("name", CASE_LABEL (t
));
697 dump_child ("low ", CASE_LOW (t
));
699 dump_child ("high", CASE_HIGH (t
));
703 dump_child ("name", TREE_OPERAND (t
,0));
706 dump_child ("labl", TREE_OPERAND (t
, 0));
709 dump_child ("cond", TREE_OPERAND (t
, 0));
710 dump_child ("body", TREE_OPERAND (t
, 1));
711 if (TREE_OPERAND (t
, 2))
713 dump_child ("labl", TREE_OPERAND (t
,2));
719 fprintf (di
->stream
, "%s\n", omp_clause_code_name
[OMP_CLAUSE_CODE (t
)]);
720 for (i
= 0; i
< omp_clause_num_ops
[OMP_CLAUSE_CODE (t
)]; i
++)
721 dump_child ("op: ", OMP_CLAUSE_OPERAND (t
, i
));
725 /* There are no additional fields to print. */
730 if (dump_flag (di
, TDF_ADDRESS
, NULL
))
731 dump_pointer (di
, "addr", (void *)t
);
733 /* Terminate the line. */
734 fprintf (di
->stream
, "\n");
737 /* Return nonzero if FLAG has been specified for the dump, and NODE
738 is not the root node of the dump. */
740 int dump_flag (dump_info_p di
, int flag
, const_tree node
)
742 return (di
->flags
& flag
) && (node
!= di
->node
);
745 /* Dump T, and all its children, on STREAM. */
748 dump_node (const_tree t
, int flags
, FILE *stream
)
752 dump_queue_p next_dq
;
754 /* Initialize the dump-information structure. */
763 di
.nodes
= splay_tree_new (splay_tree_compare_pointers
, 0,
764 (splay_tree_delete_value_fn
) &free
);
766 /* Queue up the first node. */
767 queue (&di
, t
, DUMP_NONE
);
769 /* Until the queue is empty, keep dumping nodes. */
771 dequeue_and_dump (&di
);
774 for (dq
= di
.free_list
; dq
; dq
= next_dq
)
779 splay_tree_delete (di
.nodes
);