NetBSD/gnu/usr.bin/g++/cc1plus/print-tree.c

674 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Prints out tree in human readable form - GNU C-compiler
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "tree.h"
#include <stdio.h>
extern char **tree_code_name;
extern char *mode_name[];
extern char spaces[];
#define MIN(x,y) ((x < y) ? x : y)
static FILE *outfile;
extern int tree_node_counter;
/* markvec[i] is 1 if node number i has been seen already. */
static char *markvec;
static void dump ();
void dump_tree ();
void
debug_dump_tree (root)
tree root;
{
dump_tree (stderr, root);
}
void
dump_tree (outf, root)
FILE *outf;
tree root;
{
markvec = (char *) alloca (tree_node_counter + 1);
bzero (markvec, tree_node_counter + 1);
outfile = outf;
dump (root, 0);
fflush (outf);
}
static
void
wruid (node)
tree node;
{
if (node == NULL)
fputs ("<>", outfile);
else {
fprintf (outfile, "%1d", TREE_UID (node));
}
}
static
void
part (title, node)
char title[];
tree node;
{
fprintf (outfile, " %s = ", title);
wruid (node);
putc (';', outfile);
}
/* Similar to `part' but prefix with @ if value is not constant
and print the constant value if it is constant. */
static
void
cpart (title, ct, punct)
char *title;
tree ct;
char punct;
{
fprintf (outfile, " %s = ", title);
if (ct == NULL)
fputs ("<>", outfile);
else
{
if (!TREE_LITERAL (ct))
{
putc ('@', outfile);
wruid (ct);
}
else
fprintf (outfile, "%ld", TREE_INT_CST_LOW (ct));
}
putc (punct, outfile);
}
static void
walk (node, leaf, indent)
tree node;
tree leaf;
int indent;
{
if (node != NULL
/* Don't walk any global nodes reached from local nodes!
The global nodes will be dumped at the end, all together.
Also don't mention a FUNCTION_DECL node that is marked local
since it was fully described when it was dumped locally. */
&& (TREE_CODE (node) != FUNCTION_DECL
|| TREE_PERMANENT (node))
&& (TREE_PERMANENT (leaf) == TREE_PERMANENT (node)))
dump (node, indent+1);
}
static void
cwalk (s, leaf, indent)
tree s;
tree leaf;
int indent;
{
if (s != NULL)
if (!TREE_LITERAL (s))
walk (s, leaf, indent);
}
static void
prtypeinfo (node)
register tree node;
{
int first;
part ("type", TREE_TYPE (node));
first = 1;
fputs (" [", outfile);
if (TREE_EXTERNAL (node))
{
if (!first) putc (' ', outfile);
fputs ("external", outfile);
first = 0;
}
if (TREE_PUBLIC (node))
{
if (!first) putc (' ', outfile);
fputs ("public", outfile);
first = 0;
}
if (TREE_STATIC (node))
{
if (!first) putc (' ', outfile);
fputs ("static", outfile);
first = 0;
}
if (TREE_VOLATILE (node))
{
if (!first) putc (' ', outfile);
fputs ("volatile", outfile);
first = 0;
}
if (TREE_PACKED (node))
{
if (!first) putc (' ', outfile);
fputs ("packed", outfile);
first = 0;
}
if (TREE_READONLY (node))
{
if (!first) putc (' ', outfile);
fputs ("readonly", outfile);
first = 0;
}
if (TREE_LITERAL (node))
{
if (!first) putc (' ', outfile);
fputs ("literal", outfile);
first = 0;
}
if (TREE_NONLOCAL (node))
{
if (!first) putc (' ', outfile);
fputs ("nonlocal", outfile);
first = 0;
}
if (TREE_ADDRESSABLE (node))
{
if (!first) putc (' ', outfile);
fputs ("addressable", outfile);
first = 0;
}
if (TREE_REGDECL (node))
{
if (!first) putc (' ', outfile);
fputs ("regdecl", outfile);
first = 0;
}
if (TREE_THIS_VOLATILE (node))
{
if (!first) putc (' ', outfile);
fputs ("this_vol", outfile);
first = 0;
}
if (TREE_UNSIGNED (node))
{
if (!first) putc (' ', outfile);
fputs ("unsigned", outfile);
first = 0;
}
if (TREE_ASM_WRITTEN (node))
{
if (!first) putc (' ', outfile);
fputs ("asm_written", outfile);
first = 0;
}
if (TREE_INLINE (node))
{
if (!first) putc (' ', outfile);
fputs ("inline", outfile);
first = 0;
}
if (TREE_USED (node))
{
if (!first) putc (' ', outfile);
fputs ("used", outfile);
first = 0;
}
if (TREE_PERMANENT (node))
{
if (!first) putc (' ', outfile);
fputs ("permanent", outfile);
first = 0;
}
if (TREE_LANG_FLAG_1 (node))
{
if (!first) putc (' ', outfile);
fputs ("lang_flag_1", outfile);
first = 0;
}
if (TREE_LANG_FLAG_2 (node))
{
if (!first) putc (' ', outfile);
fputs ("lang_flag_2", outfile);
first = 0;
}
if (TREE_LANG_FLAG_3 (node))
{
if (!first) putc (' ', outfile);
fputs ("lang_flag_3", outfile);
first = 0;
}
if (TREE_LANG_FLAG_4 (node))
{
if (!first) putc (' ', outfile);
fputs ("lang_flag_4", outfile);
first = 0;
}
fputs ("] ", outfile);
}
static void
prdeclmodeinfo (node)
tree node;
{
register enum machine_mode mode = DECL_MODE (node);
fprintf (outfile, " %s;", mode_name[(int) mode]);
cpart ("size", DECL_SIZE (node), '*');
fprintf (outfile, "%d;", DECL_SIZE_UNIT (node));
fprintf (outfile, " alignment = %1d;", DECL_ALIGN (node));
}
static void
prtypemodeinfo (node)
tree node;
{
register enum machine_mode mode = TYPE_MODE (node);
fprintf (outfile, " %s;", mode_name[(int) mode]);
cpart ("size", TYPE_SIZE (node), '*');
fprintf (outfile, "%d;", TYPE_SIZE_UNIT (node));
fprintf (outfile, " alignment = %1d;", TYPE_ALIGN (node));
}
static void
skip (indent)
int indent;
{
putc ('\n',outfile);
fputs (spaces + (strlen (spaces) - (12 + MIN (40,(indent+1)*2))), outfile);
}
/* Output a description of the tree node NODE
if its description has not been output already. */
static
void
dump (node, indent)
tree node;
int indent;
{
register enum tree_code code = TREE_CODE (node);
register int i;
register int len, first_rtl;
int nochain = 0;
if (markvec[TREE_UID (node)])
return;
markvec[TREE_UID (node)] = 1;
fputs (" ", outfile);
fprintf (outfile, "%5d", TREE_UID (node));
fputs (spaces + (strlen (spaces) - MIN (40, (indent+1)*2)), outfile);
fputs (tree_code_name[(int) code], outfile);
switch (*tree_code_type[(int) code])
{
case 'd':
fputs (" name = ", outfile);
if (DECL_NAME (node) == NULL)
fputs ("<>;", outfile);
else
fprintf (outfile, "%s;",
IDENTIFIER_POINTER (DECL_NAME (node)));
if (code != PARM_DECL)
fprintf (outfile, " at %s line %d;",
DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
skip (indent);
prdeclmodeinfo (node);
prtypeinfo (node);
#ifdef PRINT_LANG_DECL
print_lang_decl (node);
#endif
skip (indent);
fprintf (outfile, " offset = %1d;", DECL_OFFSET (node));
if (DECL_VOFFSET (node) != NULL)
{
fputs ("voffset = ", outfile);
wruid (DECL_VOFFSET (node));
fprintf (outfile, "*%1d;", DECL_VOFFSET_UNIT (node));
}
part ("context", DECL_CONTEXT (node));
if (code == FUNCTION_DECL)
{
if (DECL_ARGUMENTS (node) || DECL_RESULT (node)
|| DECL_INITIAL (node))
{
skip (indent);
part ("arguments", DECL_ARGUMENTS (node));
part ("result", DECL_RESULT (node));
if ((int) (DECL_INITIAL (node)) == 1)
fprintf (outfile, " initial = const 1;");
else
part ("initial", DECL_INITIAL (node));
}
}
else if (DECL_INITIAL (node))
{
if ((int) (DECL_INITIAL (node)) == 1)
fprintf (outfile, " initial = const 1;");
else
part ("initial", DECL_INITIAL (node));
}
#ifdef PRINT_LANG_DECL
walk_lang_decl (node);
#endif
part ("chain", TREE_CHAIN (node));
/* A Decl's chain contents is not part of the decl. */
nochain = 1;
fputc ('\n', outfile);
cwalk (DECL_SIZE (node), node, indent);
walk (TREE_TYPE (node), node, indent);
walk (DECL_VOFFSET (node), node, indent);
walk (DECL_CONTEXT (node), node, indent);
if (code == FUNCTION_DECL)
{
walk (DECL_ARGUMENTS (node), node, indent);
walk (DECL_RESULT (node), node, indent);
}
if ((int) (DECL_INITIAL (node)) != 1)
walk (DECL_INITIAL (node), node, indent);
break;
case 't':
prtypemodeinfo (node);
prtypeinfo (node);
#ifdef PRINT_LANG_TYPE
print_lang_type (node);
#endif
skip (indent);
part ("pointers_to_this", TYPE_POINTER_TO (node));
if (code == ARRAY_TYPE || code == SET_TYPE)
{
part ("domain", TYPE_DOMAIN (node));
cpart ("separation", TYPE_SEP (node), '*');
fprintf (outfile, "%d;", TYPE_SEP_UNIT (node));
}
else if (code == INTEGER_TYPE)
{
cpart ("min", TYPE_MIN_VALUE (node), ';');
cpart ("max", TYPE_MAX_VALUE (node), ';');
fprintf (outfile, "precision = %d;", TYPE_PRECISION (node));
}
else if (code == ENUMERAL_TYPE)
{
cpart ("min", TYPE_MIN_VALUE (node), ';');
cpart ("max", TYPE_MAX_VALUE (node), ';');
part ("values", TYPE_VALUES (node));
fprintf (outfile, "precision = %d;", TYPE_PRECISION (node));
}
else if (code == REAL_TYPE)
{
fprintf (outfile, "precision = %d;", TYPE_PRECISION (node));
}
else if (code == RECORD_TYPE
|| code == UNION_TYPE)
{
part ("fields", TYPE_FIELDS (node));
}
else if (code == FUNCTION_TYPE)
{
part ("arg_types", TYPE_ARG_TYPES (node));
}
else if (code == METHOD_TYPE)
{
part ("arg_types", TYPE_ARG_TYPES (node));
}
#ifdef PRINT_LANG_TYPE
walk_lang_type (node);
#endif
part ("chain", TREE_CHAIN (node));
/* A type's chain's contents are not printed because the chain of types
is not part of the meaning of any particular type. */
nochain = 1;
fputc ('\n', outfile);
cwalk (TYPE_SIZE (node), node, indent);
walk (TREE_TYPE (node), node, indent);
walk (TYPE_VALUES (node), node, indent);
walk (TYPE_SEP (node), node, indent);
walk (TYPE_POINTER_TO (node), node, indent);
walk (TYPE_REFERENCE_TO (node), node, indent);
break;
case 'e':
case 'r':
prtypeinfo (node);
fputs (" ops =", outfile);
first_rtl = len = tree_code_length[(int) code];
/* These kinds of nodes contain rtx's, not trees,
after a certain point. Print the rtx's as rtx's. */
switch (code)
{
case SAVE_EXPR:
first_rtl = 1;
break;
case CALL_EXPR:
first_rtl = 2;
break;
case METHOD_CALL_EXPR:
first_rtl = 3;
break;
case WITH_CLEANUP_EXPR:
/* Should be defined to be 2. */
first_rtl = 1;
break;
case RTL_EXPR:
first_rtl = 0;
}
for (i = 0; i < len; i++)
{
if (i >= first_rtl)
{
skip (indent);
if (TREE_OPERAND (node, i))
print_rtl (outfile, TREE_OPERAND (node, i));
else
fprintf (outfile, "(nil)");
fprintf (outfile, "\n");
}
else
{
fputs (" ", outfile);
wruid (TREE_OPERAND (node, i));
fputs (";", outfile);
}
}
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
for (i = 0; i < len && i < first_rtl; i++)
walk (TREE_OPERAND (node, i), node, indent);
break;
case 's':
prtypeinfo (node);
fprintf (outfile, " at %s line %d;",
STMT_SOURCE_FILE (node), STMT_SOURCE_LINE (node));
switch (TREE_CODE (node))
{
case IF_STMT:
part ("cond", STMT_COND (node));
part ("then", STMT_THEN (node));
part ("else", STMT_ELSE (node));
break;
case LET_STMT:
case WITH_STMT:
part ("vars", STMT_VARS (node));
part ("tags", STMT_TYPE_TAGS (node));
part ("supercontext", STMT_SUPERCONTEXT (node));
part ("bind_size", STMT_BIND_SIZE (node));
part ("body", STMT_BODY (node));
part ("subblocks", STMT_SUBBLOCKS (node));
break;
case CASE_STMT:
part ("case_index", STMT_CASE_INDEX (node));
part ("case_list", STMT_CASE_LIST (node));
break;
default:
part ("body", STMT_BODY (node));
break;
}
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
switch (TREE_CODE (node))
{
case IF_STMT:
walk (STMT_COND (node), node, indent);
walk (STMT_THEN (node), node, indent);
walk (STMT_ELSE (node), node, indent);
break;
case LET_STMT:
case WITH_STMT:
walk (STMT_VARS (node), node, indent);
walk (STMT_TYPE_TAGS (node), node, indent);
walk (STMT_SUPERCONTEXT (node), node, indent);
walk (STMT_BIND_SIZE (node), node, indent);
walk (STMT_BODY (node), node, indent);
walk (STMT_SUBBLOCKS (node), node, indent);
break;
case CASE_STMT:
walk (STMT_CASE_INDEX (node), node, indent);
walk (STMT_CASE_LIST (node), node, indent);
break;
default:
walk (STMT_BODY (node), node, indent);
break;
}
break;
case 'c':
switch (code)
{
case INTEGER_CST:
if (TREE_INT_CST_HIGH (node) == 0)
fprintf (outfile, " = %1u;", TREE_INT_CST_LOW (node));
else if (TREE_INT_CST_HIGH (node) == -1
&& TREE_INT_CST_LOW (node) != 0)
fprintf (outfile, " = -%1u;", -TREE_INT_CST_LOW (node));
else
fprintf (outfile, " = 0x%x%08x;",
TREE_INT_CST_HIGH (node),
TREE_INT_CST_LOW (node));
break;
case REAL_CST:
#ifndef REAL_IS_NOT_DOUBLE
fprintf (outfile, " = %e;", TREE_REAL_CST (node));
#else
{
int i;
char *p = (char *) &TREE_REAL_CST (node);
fprintf (outfile, " = 0x");
for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
fprintf (outfile, "%02x", *p++);
fprintf (outfile, ";");
}
#endif /* REAL_IS_NOT_DOUBLE */
break;
case COMPLEX_CST:
part ("realpart", TREE_REALPART (node));
part ("imagpart", TREE_IMAGPART (node));
walk (TREE_REALPART (node), node, indent);
walk (TREE_IMAGPART (node), node, indent);
break;
case STRING_CST:
fprintf (outfile, " = \"%s\";", TREE_STRING_POINTER (node));
}
prtypeinfo (node);
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
break;
case 'x':
if (code == IDENTIFIER_NODE)
{
fprintf (outfile, " = %s;\n", IDENTIFIER_POINTER (node));
nochain = 1;
}
else if (code == TREE_LIST)
{
prtypeinfo (node);
part ("purpose", TREE_PURPOSE (node));
part ("value", TREE_VALUE (node));
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
walk (TREE_PURPOSE (node), node, indent);
walk (TREE_VALUE (node), node, indent);
}
else if (code == TREE_VEC)
{
prtypeinfo (node);
len = TREE_VEC_LENGTH (node);
fprintf (outfile, "length = %d\n", len);
for (i = 0; i < len; i++)
{
fputs (" ", outfile);
wruid (TREE_VEC_ELT (node, i));
fputs (";", outfile);
}
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
for (i = 0; i < len; i++)
walk (TREE_VEC_ELT (node, i), node, indent);
}
else if (code == OP_IDENTIFIER)
{
prtypeinfo (node);
part ("op1", TREE_PURPOSE (node));
part ("op2", TREE_VALUE (node));
part ("chain", TREE_CHAIN (node));
fputc ('\n', outfile);
walk (TREE_TYPE (node), node, indent);
walk (TREE_PURPOSE (node), node, indent);
walk (TREE_VALUE (node), node, indent);
}
else if (code == ERROR_MARK)
fputc ('\n', outfile);
else abort ();
break;
default:
abort ();
} /* switch */
if (TREE_CHAIN (node) != NULL && ! nochain)
dump (TREE_CHAIN (node), indent);
}