This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Add more tree dump options, remove inconsistencies
- To: Mark Mitchell <mark at codesourcery dot com>
- Subject: Re: Add more tree dump options, remove inconsistencies
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 04 Jun 2001 14:58:44 +0100
- CC: gcc-patches at gcc dot gnu dot org
- Organization: Codesourcery LLC
- References: <3B1132E3.22473214@codesourcery.com> <20010603235934A.mitchell@codesourcery.com>
Mark Mitchell wrote:
>
> This is definite goodness. OK for mainline.
Since then I've done some changes to that;
1) Added a bit more documentation, as suggested by rth
2) changed the names of the tree dump flags to '-dump-ast-foo' (at some
future time we might process AST for global variable initialization for
instance).
3) I'd actually documented the names wrongly anyway
4) rather than `preoptimize' & `postoptimize' I've named them `raw' &
`cooked'. If you have a better suggestion, please make it.
5) Added more information to the class hierarchy dumper. Namely dump the
vtables & vtt.
booted & tested on i686-pc-linux-gnu. is this goodness too?
> I don't think there's any need to put this on the trunk.
I'd like to put it on the branch too, for the following reasons;
1) the command switch parsing is inconsistent in the C & C++ frontends,
and it appears the class-heirarchy cannot be dumped to a named file.
2) I added the functionality of the first version of this patch to help
track down a tree-based optimizer bug in 3.0. I've now added the additional
class information for bug 3006 (an ABI problem). Without this patch in the
branch, I'd have to apply and unapply the patch locally, which I suspect
would be more error prone in the long run.
3) This is a relatively low risk patch, as, if it breaks, it is much more
likely to break our debugging dump than normal user usage of the compiler.
I think this falls into the
- Some other miscellaneous, but worthwhile goal.
you gave in the 3.0 guidelines.
So, I'm requesting a `management decision' on this one :-)
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-06-04 Nathan Sidwell <nathan@codesourcery.com>
* c-common.h (flag_dump_translation_unit): Remove.
(enum tree_dump_index): Define.
(TDF_ADDRESS, TDF_SLIM): New #defines.
(dump_node_to_file): Remove.
(dump_node): Make extern. Add flags.
(dump_flag, dump_enabled_p, dump_begin, dump_end,
dump_switch_p): Prototype.
* c-common.c (flag_dump_translation_unit): Remove.
* c-decl.c (c_decode_option): Remove -fdump-translation-unit
logic. Use dump_switch_p.
* c-dump.h (struct dump_info): Add node and user fields.
(dump_pointer): Declare.
* c-dump.c (dump_node): Make extern. Add flags.
(SOL_COLUMN, EOL_COLUMN, COLUMN_ALIGNMENT): New #defines.
(dump_new_line, dump_maybe_newline): Use them.
(dump_pointer): New function.
(dequeue_and_dump): Check TDF_SLIM before dumping a _DECL's
chain or function's body. Dump address, if TDF_ADDRESS set.
(dump_flag): Define.
(dump_node_to_file): Remove.
(struct dump_file_info): New struct.
(dump_files): New array.
(dump_begin, dump_end, dump_enabled_p, dump_switch_p): Define.
* c-lang.c (finish_file): Adjust dumping.
* toplev.h (dump_base_name): Make extern.
* invoke.texi: Document new flags.
2001-06-04 Nathan Sidwell <nathan@codesourcery.com>
* class.c (maybe_indent_hierarchy): New function.
(dump_class_hierarchy_r): Add flags. Dump extra binfo
information, if enabled. Use maybe_indent_hierarchy. Adjust
output format.
(dump_class_hierarchy): Adjust prototype. Adjust output format.
(dump_array, dump_vtable, dump_vtt): New functions.
(finish_struct_1): Adjust hierarchy dumping.
(initialize_vtable): Call dump_vtable.
(build_vtt): Call dump_vtt.
(build_ctor_vtbl_group): Call dump_vtable.
* decl2.c (flag_dump_class_layout): Remove.
(cxx_decode_option): Remove dump translation unit
and dump class hierarchy check. Call dump_switch_p.
(finish_file): Adjust dumping.
(dump.c): Only dump base classes if not TDF_SLIM.
Only dump namespace members if not TDF_SLIM.
* optimize.c (dump_function): New function.
(optimize_function): Call dump_function.
* semantics.c (expand_body): Use dump_enabled_p.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.c,v
retrieving revision 1.226.2.3
diff -c -3 -p -r1.226.2.3 c-common.c
*** c-common.c 2001/05/28 08:33:38 1.226.2.3
--- c-common.c 2001/06/04 08:15:14
*************** int flag_short_double;
*** 191,201 ****
int flag_short_wchar;
- /* If non-NULL, dump the tree structure for the entire translation
- unit to this file. */
-
- const char *flag_dump_translation_unit;
-
/* Nonzero means warn about possible violations of sequence point rules. */
int warn_sequence_point;
--- 191,196 ----
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.64.4.2
diff -c -3 -p -r1.64.4.2 c-common.h
*** c-common.h 2001/05/01 00:09:48 1.64.4.2
--- c-common.h 2001/06/04 08:15:14
*************** extern int flag_no_builtin;
*** 422,432 ****
extern int flag_no_nonansi_builtin;
- /* If non-NULL, dump the tree structure for the entire translation
- unit to this file. */
-
- extern const char *flag_dump_translation_unit;
-
/* Nonzero means warn about suggesting putting in ()'s. */
extern int warn_parentheses;
--- 422,427 ----
*************** extern int c_unsafe_for_reeval PARAMS
*** 802,807 ****
--- 797,816 ----
/* In dump.c */
+ /* Different tree dump places. */
+ enum tree_dump_index
+ {
+ TDI_all, /* dump the whole translation unit */
+ TDI_raw, /* dump each function before optimizing it */
+ TDI_cooked, /* dump each function after optimizing it */
+ TDI_class, /* dump class heirarchy */
+ TDI_end
+ };
+
+ /* Bit masks to control tree dumping. */
+ #define TDF_ADDRESS (1 << 0) /* dump node addresses */
+ #define TDF_SLIM (1 << 1) /* don't go wild following links */
+
typedef struct dump_info *dump_info_p;
/* A callback function used dump language-specific parts of tree
*************** typedef int (*dump_tree_fn) PARAMS ((dum
*** 812,818 ****
extern dump_tree_fn lang_dump_tree;
! extern void dump_node_to_file PARAMS ((tree, const char *));
/* Information recorded about each file examined during compilation. */
--- 821,832 ----
extern dump_tree_fn lang_dump_tree;
! extern int dump_flag PARAMS ((dump_info_p, int, tree));
! extern int dump_enabled_p PARAMS ((enum tree_dump_index));
! extern FILE *dump_begin PARAMS ((enum tree_dump_index, int *));
! extern void dump_end PARAMS ((enum tree_dump_index, FILE *));
! extern void dump_node PARAMS ((tree, int, FILE *));
! extern int dump_switch_p PARAMS ((const char *));
/* Information recorded about each file examined during compilation. */
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.207.2.10
diff -c -3 -p -r1.207.2.10 c-decl.c
*** c-decl.c 2001/05/21 18:08:50 1.207.2.10
--- c-decl.c 2001/06/04 08:15:17
*************** c_decode_option (argc, argv)
*** 452,458 ****
char **argv;
{
int strings_processed;
- const char *option_value = NULL;
char *p = argv[0];
strings_processed = cpp_handle_option (parse_in, argc, argv);
--- 452,457 ----
*************** c_decode_option (argc, argv)
*** 598,611 ****
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
! else if ((option_value
! = skip_leading_substring (p, "-fdump-translation-unit-")))
! {
! if (p[22] == '\0')
! error ("no file specified with -fdump-translation-unit");
! else
! flag_dump_translation_unit = option_value;
! }
else if (!strcmp (p, "-ansi"))
goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
--- 597,604 ----
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
! else if (dump_switch_p (p))
! ;
else if (!strcmp (p, "-ansi"))
goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
Index: c-dump.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-dump.c,v
retrieving revision 1.2.4.1
diff -c -3 -p -r1.2.4.1 c-dump.c
*** c-dump.c 2001/04/16 00:31:44 1.2.4.1
--- c-dump.c 2001/06/04 08:15:18
*************** static void dequeue_and_dump PARAMS ((du
*** 40,46 ****
static void dump_new_line PARAMS ((dump_info_p));
static void dump_maybe_newline PARAMS ((dump_info_p));
static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
- static void dump_node PARAMS ((tree, FILE *));
/* Add T to the end of the queue of nodes to dump. Returns the index
assigned to T. */
--- 40,45 ----
*************** queue_and_dump_type (di, t)
*** 139,144 ****
--- 138,148 ----
queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
}
+ /* Dump column control */
+ #define SOL_COLUMN 25 /* Start of line column. */
+ #define EOL_COLUMN 55 /* End of line column. */
+ #define COLUMN_ALIGNMENT 15 /* Alignment. */
+
/* Insert a new line in the dump output, and indent to an appropriate
place to start printing more fields. */
*************** static void
*** 146,153 ****
dump_new_line (di)
dump_info_p di;
{
! fprintf (di->stream, "\n%25s", "");
! di->column = 25;
}
/* If necessary, insert a new line. */
--- 150,157 ----
dump_new_line (di)
dump_info_p di;
{
! fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
! di->column = SOL_COLUMN;
}
/* If necessary, insert a new line. */
*************** static void
*** 156,173 ****
dump_maybe_newline (di)
dump_info_p di;
{
/* See if we need a new line. */
! if (di->column > 53)
dump_new_line (di);
/* See if we need any padding. */
! else if ((di->column - 25) % 14 != 0)
{
! fprintf (di->stream, "%*s", 14 - ((di->column - 25) % 14), "");
! di->column += 14 - (di->column - 25) % 14;
}
}
! /* Dump I using FIELD to identity it. */
void
dump_int (di, field, i)
--- 160,192 ----
dump_maybe_newline (di)
dump_info_p di;
{
+ int extra;
+
/* See if we need a new line. */
! if (di->column > EOL_COLUMN)
dump_new_line (di);
/* See if we need any padding. */
! else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
{
! fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
! di->column += COLUMN_ALIGNMENT - extra;
}
}
+
+ /* Dump pointer PTR using FIELD to identify it. */
+
+ void
+ dump_pointer (di, field, ptr)
+ dump_info_p di;
+ const char *field;
+ void *ptr;
+ {
+ dump_maybe_newline (di);
+ fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
+ di->column += 15;
+ }
! /* Dump integer I using FIELD to identify it. */
void
dump_int (di, field, i)
*************** dequeue_and_dump (di)
*** 349,355 ****
/* And any declaration can be compiler-generated. */
if (DECL_ARTIFICIAL (t))
dump_string (di, "artificial");
! if (TREE_CHAIN (t))
dump_child ("chan", TREE_CHAIN (t));
}
else if (code_class == 't')
--- 368,374 ----
/* And any declaration can be compiler-generated. */
if (DECL_ARTIFICIAL (t))
dump_string (di, "artificial");
! if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
dump_child ("chan", TREE_CHAIN (t));
}
else if (code_class == 't')
*************** dequeue_and_dump (di)
*** 504,510 ****
dump_string (di, "extern");
else
dump_string (di, "static");
! if (DECL_LANG_SPECIFIC (t))
dump_child ("body", DECL_SAVED_TREE (t));
break;
--- 523,529 ----
dump_string (di, "extern");
else
dump_string (di, "static");
! if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
dump_child ("body", DECL_SAVED_TREE (t));
break;
*************** dequeue_and_dump (di)
*** 709,723 ****
}
done:
/* Terminate the line. */
fprintf (di->stream, "\n");
}
/* Dump T, and all its children, on STREAM. */
! static void
! dump_node (t, stream)
tree t;
FILE *stream;
{
struct dump_info di;
--- 728,757 ----
}
done:
+ if (dump_flag (di, TDF_ADDRESS, NULL))
+ dump_pointer (di, "addr", (void *)t);
+
/* Terminate the line. */
fprintf (di->stream, "\n");
}
+ /* Return non-zero if FLAG has been specified for the dump, and NODE
+ is not the root node of the dump. */
+
+ int dump_flag (di, flag, node)
+ dump_info_p di;
+ int flag;
+ tree node;
+ {
+ return (di->flags & flag) && (node != di->node);
+ }
+
/* Dump T, and all its children, on STREAM. */
! void
! dump_node (t, flags, stream)
tree t;
+ int flags;
FILE *stream;
{
struct dump_info di;
*************** dump_node (t, stream)
*** 731,736 ****
--- 765,772 ----
di.queue = 0;
di.queue_end = 0;
di.free_list = 0;
+ di.flags = flags;
+ di.node = t;
di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
(splay_tree_delete_value_fn) &free);
*************** dump_node (t, stream)
*** 750,770 ****
splay_tree_delete (di.nodes);
}
! /* Dump T, and all its children, to FILE. */
! void
! dump_node_to_file (t, file)
! tree t;
! const char *file;
{
! FILE *f;
! f = fopen (file, "w");
! if (!f)
! error ("could not open dump file `%s'", file);
! else
! {
! dump_node (t, f);
! fclose (f);
! }
}
--- 786,877 ----
splay_tree_delete (di.nodes);
}
! /* Define a tree dump switch. */
! struct dump_file_info
! {
! const char *suffix; /* suffix to give output file. */
! const char *swtch; /* command line switch */
! int flags; /* user flags */
! int state; /* state of play */
! };
!
! /* Table of tree dump switches. */
! static struct dump_file_info dump_files[TDI_end] =
! {
! {".tu", "dump-translation-unit", 0, 0},
! {".raw", "dump-ast-raw", 0, 0},
! {".cooked", "dump-ast-cooked", 0, 0},
! {".class", "dump-class-hierarchy", 0, 0},
! };
!
! /* Begin a tree dump for PHASE. Stores any user supplied flag in
! *FLAG_PTR and returns a stream to write to. If the dump is not
! enabled, returns NULL.
! Multiple calls will reopen and append to the dump file. */
!
! FILE *
! dump_begin (phase, flag_ptr)
! enum tree_dump_index phase;
! int *flag_ptr;
! {
! FILE *stream;
! char *name;
!
! if (!dump_files[phase].state)
! return NULL;
!
! name = concat (dump_base_name, dump_files[phase].suffix, NULL);
! stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
! if (!stream)
! error ("could not open dump file `%s'", name);
! else
! dump_files[phase].state = 1;
! free (name);
! if (flag_ptr)
! *flag_ptr = dump_files[phase].flags;
!
! return stream;
! }
! /* Returns non-zero if tree dump PHASE is enabled. */
!
! int dump_enabled_p (phase)
! enum tree_dump_index phase;
{
! return dump_files[phase].state;
! }
! /* Finish a tree dump for PHASE. STREAM is the stream created by
! dump_begin. */
!
! void dump_end (phase, stream)
! enum tree_dump_index phase ATTRIBUTE_UNUSED;
! FILE *stream;
! {
! fclose (stream);
! }
!
! /* Parse ARG as a dump switch. Return non-zero if it is, and store the
! relevant details in the dump_files array. */
!
! int dump_switch_p (arg)
! const char *arg;
! {
! unsigned ix;
! const char *option_value;
!
! for (ix = 0; ix != TDI_end; ix++)
! if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
! {
! dump_files[ix].state = -1;
! if (*option_value == '-')
! dump_files[ix].flags
! = read_integral_parameter (option_value + 1, arg, 0);
! else if (*option_value)
! warning ("ignoring `%s' at end of `-f%s'",
! option_value, dump_files[ix].swtch);
!
! return 1;
! }
! return 0;
}
Index: c-dump.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-dump.h,v
retrieving revision 1.1
diff -c -3 -p -r1.1 c-dump.h
*** c-dump.h 2000/11/10 16:29:34 1.1
--- c-dump.h 2001/06/04 08:15:18
*************** struct dump_info
*** 50,55 ****
--- 50,59 ----
{
/* The stream on which to dump the information. */
FILE *stream;
+ /* The original node. */
+ tree node;
+ /* User flags. */
+ int flags;
/* The next unused node index. */
unsigned int index;
/* The next column. */
*************** struct dump_info
*** 70,75 ****
--- 74,81 ----
#define dump_child(field, child) \
queue_and_dump_index (di, field, child, DUMP_NONE)
+ extern void dump_pointer
+ PARAMS ((dump_info_p, const char *, void *));
extern void dump_int
PARAMS ((dump_info_p, const char *, int));
extern void dump_string
Index: c-lang.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-lang.c,v
retrieving revision 1.47
diff -c -3 -p -r1.47 c-lang.c
*** c-lang.c 2001/01/29 18:57:19 1.47
--- c-lang.c 2001/06/04 08:15:18
*************** finish_file ()
*** 255,263 ****
if (back_end_hook)
(*back_end_hook) (getdecls ());
! if (flag_dump_translation_unit)
! dump_node_to_file (getdecls (), flag_dump_translation_unit);
}
/* Called during diagnostic message formatting process to print a
--- 255,271 ----
if (back_end_hook)
(*back_end_hook) (getdecls ());
+
+ {
+ int flags;
+ FILE *stream = dump_begin (TDI_all, &flags);
! if (stream)
! {
! dump_node (getdecls (), flags & ~TDF_SLIM, stream);
! dump_end (TDI_all, stream);
! }
! }
}
/* Called during diagnostic message formatting process to print a
Index: invoke.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/invoke.texi,v
retrieving revision 1.273.2.27
diff -c -3 -p -r1.273.2.27 invoke.texi
*** invoke.texi 2001/06/01 22:23:17 1.273.2.27
--- invoke.texi 2001/06/04 08:15:23
*************** in the following sections.
*** 234,241 ****
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@gccoptlist{
-a -ax -d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
! -fdump-unnumbered -fdump-translation-unit=@var{file} @gol
! -fdump-class-layout=@var{file} -fmem-report -fpretend-float @gol
-fprofile-arcs -ftest-coverage -ftime-report @gol
-g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2 @gol
-ggdb -gstabs -gstabs+ -gxcoff -gxcoff+ @gol
--- 234,242 ----
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@gccoptlist{
-a -ax -d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
! -fdump-unnumbered -fdump-translation-unit@r{[}-@var{n}@r{]} -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
! -fdump-ast-raw@r{[}-@var{n}@r{]} -fdump-ast-cooked@r{[}-@var{n}@r{]} @gol
! -fmem-report -fpretend-float @gol
-fprofile-arcs -ftest-coverage -ftime-report @gol
-g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2 @gol
-ggdb -gstabs -gstabs+ -gxcoff -gxcoff+ @gol
*************** numbers and line number note output. Th
*** 2747,2760 ****
use diff on debugging dumps for compiler invocations with different
options, in particular with and without -g.
! @item -fdump-translation-unit=@var{file} (C and C++ only)
Dump a representation of the tree structure for the entire translation
! unit to @var{file}.
! @item -fdump-class_layout=@var{file} (C++ only)
! @item -fdump-class_layout (C++ only)
! Dump a representation of each class's heirarchy to @var{file}, or
! @code{stderr} if not specified.
@item -fpretend-float
When running a cross-compiler, pretend that the target machine uses the
--- 2748,2793 ----
use diff on debugging dumps for compiler invocations with different
options, in particular with and without -g.
! @item -fdump-translation-unit (C and C++ only)
! @item -fdump-translation-unit-@var{number} (C and C++ only)
Dump a representation of the tree structure for the entire translation
! unit to a file. The file name is made by appending @file{.tu} to the
! source file name. If the -@var{number} form is used, @var{number}
! controls the details of the dump as described for the -fdump-tree options.
!
! @item -fdump-class-hierarchy (C++ only)
! @item -fdump-class-hierarchy-@var{number} (C++ only)
! Dump a representation of each class's hierarchy and virtual function
! table layout to a file. The file name is made by appending @file{.class}
! to the source file name. If the -@var{number} form is used, @var{number}
! controls the details of the dump as described for the -fdump-tree
! options.
!
! @item -fdump-ast-@var{switch} (C++ only)
! @item -fdump-ast-@var{switch}-@var{number} (C++ only)
! Control the dumping at various stages of processing the abstract syntax
! tree to a file. The file name is generated by appending a switch
! specific suffix to the source file name. If the -@var{number} form is
! used, @var{number} is a bit mask which controls the details of the
! dump. The following bits are meaningful (these are not set symbolically,
! as the primary function of these dumps is for debugging gcc itself):
! @table @samp
! @item bit0 (1)
! Print the address of each node. Usually this is not meaningful as it
! changes according to the environment and source file.
! @item bit1 (2)
! Inhibit dumping of members of a scope or body of a function, unless they
! are reachable by some other path.
! @end table
!
! The following tree dumps are possible:
! @table @samp
! @item raw
! Dump before any tree based optimization, to @file{@var{file}.raw}.
! @item cooked
! Dump after all tree based optimization, to @file{@var{file}.cooked}.
! @end table
@item -fpretend-float
When running a cross-compiler, pretend that the target machine uses the
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.h,v
retrieving revision 1.52.2.3
diff -c -3 -p -r1.52.2.3 toplev.h
*** toplev.h 2001/04/19 19:51:15 1.52.2.3
--- toplev.h 2001/06/04 08:15:23
*************** extern int warningcount;
*** 138,143 ****
--- 138,144 ----
extern int sorrycount;
extern const char *progname;
+ extern const char *dump_base_name;
/* Language-specific hooks. Can be NULL unless otherwise specified. */
struct lang_hooks
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.358.2.18
diff -c -3 -p -r1.358.2.18 class.c
*** class.c 2001/05/19 01:25:42 1.358.2.18
--- class.c 2001/06/04 08:15:28
*************** static void layout_vtable_decl PARAMS ((
*** 171,178 ****
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static int make_new_vtable PARAMS ((tree, tree));
! static void dump_class_hierarchy_r PARAMS ((FILE *, tree, tree, int));
! extern void dump_class_hierarchy PARAMS ((const char *, tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
--- 171,182 ----
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static int make_new_vtable PARAMS ((tree, tree));
! static int maybe_indent_hierarchy PARAMS ((FILE *, int, int));
! static void dump_class_hierarchy_r PARAMS ((FILE *, int, tree, tree, int));
! static void dump_class_hierarchy PARAMS ((tree));
! static void dump_array PARAMS ((FILE *, tree));
! static void dump_vtable PARAMS ((tree, tree, tree));
! static void dump_vtt PARAMS ((tree, tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
*************** finish_struct_1 (t)
*** 5323,5333 ****
layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
- if (flag_dump_class_layout)
- dump_class_hierarchy (*flag_dump_class_layout
- ? flag_dump_class_layout : NULL,
- t);
-
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
might need to know it for setting up the offsets in the vtable
(or in thunks) below. */
--- 5327,5332 ----
*************** finish_struct_1 (t)
*** 5483,5488 ****
--- 5482,5489 ----
maybe_suppress_debug_info (t);
+ dump_class_hierarchy (t);
+
/* Finish debugging output for this type. */
rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
}
*************** get_primary_binfo (binfo)
*** 6822,6843 ****
return result;
}
/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
dominated by T) to stderr. INDENT should be zero when called from
the top level; it is incremented recursively. */
static void
! dump_class_hierarchy_r (stream, t, binfo, indent)
FILE *stream;
tree t;
tree binfo;
int indent;
{
int i;
!
! fprintf (stream, "%*s0x%lx (%s) ", indent, "",
! (unsigned long) binfo,
! type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
if (is_empty_class (BINFO_TYPE (binfo)))
--- 6823,6860 ----
return result;
}
+ /* If INDENTED_P is zero, indent to INDENT. Return non-zero. */
+
+ static int
+ maybe_indent_hierarchy (stream, indent, indented_p)
+ FILE *stream;
+ int indent;
+ int indented_p;
+ {
+ if (!indented_p)
+ fprintf (stream, "%*s", indent, "");
+ return 1;
+ }
+
/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
dominated by T) to stderr. INDENT should be zero when called from
the top level; it is incremented recursively. */
static void
! dump_class_hierarchy_r (stream, flags, t, binfo, indent)
FILE *stream;
+ int flags;
tree t;
tree binfo;
int indent;
{
int i;
! int indented = 0;
!
! indented = maybe_indent_hierarchy (stream, indent, 0);
! fprintf (stream, "%s (0x%lx) ",
! type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
! (unsigned long) binfo);
fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
if (is_empty_class (BINFO_TYPE (binfo)))
*************** dump_class_hierarchy_r (stream, t, binfo
*** 6847,6899 ****
if (TREE_VIA_VIRTUAL (binfo))
{
tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
!
if (canonical == binfo)
! fprintf (stream, " virtual-canonical");
else
! fprintf (stream, " virtual-non-canonical");
}
- if (BINFO_PRIMARY_P (binfo))
- fprintf (stream, " primary-for 0x%lx (%s)",
- (unsigned long)BINFO_PRIMARY_BASE_OF (binfo),
- type_as_string (BINFO_PRIMARY_BASE_OF (binfo), TFF_PLAIN_IDENTIFIER));
- if (BINFO_LOST_PRIMARY_P (binfo))
- fprintf (stream, " lost-primary");
fprintf (stream, "\n");
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
! dump_class_hierarchy_r (stream, t, BINFO_BASETYPE (binfo, i), indent + 2);
}
/* Dump the BINFO hierarchy for T. */
! void
! dump_class_hierarchy (name, t)
! const char *name;
tree t;
{
! FILE *stream = stderr;
! if (name)
{
! static int append = 0;
! stream = fopen (name, append++ ? "a" : "w");
! if (!stream)
! error ("could not open dump file `%s'", name);
! return;
}
! fprintf (stream, "%s size=", type_as_string (t, TFF_PLAIN_IDENTIFIER));
! fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
! tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT);
! fprintf (stream, " align=%lu\n",
! (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
! dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0);
! fprintf (stream, "\n");
! if (name)
! fclose (stream);
}
/* Virtual function table initialization. */
/* Create all the necessary vtables for T and its base classes. */
--- 6864,7039 ----
if (TREE_VIA_VIRTUAL (binfo))
{
tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
!
! fprintf (stream, " virtual");
if (canonical == binfo)
! fprintf (stream, " canonical");
else
! fprintf (stream, " non-canonical");
}
fprintf (stream, "\n");
+ indented = 0;
+ if (BINFO_PRIMARY_BASE_OF (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " primary-for %s (0x%lx)",
+ type_as_string (BINFO_PRIMARY_BASE_OF (binfo),
+ TFF_PLAIN_IDENTIFIER),
+ (unsigned long)BINFO_PRIMARY_BASE_OF (binfo));
+ }
+ if (BINFO_LOST_PRIMARY_P (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " lost-primary");
+ }
+ if (indented)
+ fprintf (stream, "\n");
+
+ if (!(flags & TDF_SLIM))
+ {
+ int indented = 0;
+
+ if (BINFO_SUBVTT_INDEX (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " subvttidx=%s",
+ expr_as_string (BINFO_SUBVTT_INDEX (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VPTR_INDEX (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vptridx=%s",
+ expr_as_string (BINFO_VPTR_INDEX (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VPTR_FIELD (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vbaseoffset=%s",
+ expr_as_string (BINFO_VPTR_FIELD (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VTABLE (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vptr=%s",
+ expr_as_string (BINFO_VTABLE (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+
+ if (indented)
+ fprintf (stream, "\n");
+ }
+
+
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
! dump_class_hierarchy_r (stream, flags,
! t, BINFO_BASETYPE (binfo, i),
! indent + 2);
}
/* Dump the BINFO hierarchy for T. */
! static void
! dump_class_hierarchy (t)
tree t;
{
! int flags;
! FILE *stream = dump_begin (TDI_class, &flags);
!
! if (!stream)
! return;
! fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER));
! fprintf (stream, " size=%lu align=%lu\n",
! (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
! (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
! dump_class_hierarchy_r (stream, flags, t, TYPE_BINFO (t), 0);
! fprintf (stream, "\n");
! dump_end (TDI_class, stream);
! }
!
! static void
! dump_array (stream, decl)
! FILE *stream;
! tree decl;
! {
! tree inits;
! int ix;
! HOST_WIDE_INT elt;
! tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl)));
!
! elt = (tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))), 0)
! / BITS_PER_UNIT);
! fprintf (stream, "%s:", decl_as_string (decl, TFF_PLAIN_IDENTIFIER));
! fprintf (stream, " %s entries",
! expr_as_string (size_binop (PLUS_EXPR, size, size_one_node),
! TFF_PLAIN_IDENTIFIER));
! fprintf (stream, "\n");
!
! for (ix = 0, inits = TREE_OPERAND (DECL_INITIAL (decl), 1);
! inits; ix++, inits = TREE_CHAIN (inits))
! fprintf (stream, "%-4d %s\n", ix * elt,
! expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER));
! }
!
! static void
! dump_vtable (t, binfo, vtable)
! tree t;
! tree binfo;
! tree vtable;
! {
! int flags;
! FILE *stream = dump_begin (TDI_class, &flags);
!
! if (!stream)
! return;
!
! if (!(flags & TDF_SLIM))
{
! int ctor_vtbl_p = TYPE_BINFO (t) != binfo;
! fprintf (stream, "%s for %s",
! ctor_vtbl_p ? "Construction vtable" : "Vtable",
! type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
! if (ctor_vtbl_p)
! {
! if (!TREE_VIA_VIRTUAL (binfo))
! fprintf (stream, " (0x%lx instance)", (unsigned long)binfo);
! fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER));
! }
! fprintf (stream, "\n");
! dump_array (stream, vtable);
! fprintf (stream, "\n");
}
!
! dump_end (TDI_class, stream);
}
+ static void
+ dump_vtt (t, vtt)
+ tree t;
+ tree vtt;
+ {
+ int flags;
+ FILE *stream = dump_begin (TDI_class, &flags);
+
+ if (!stream)
+ return;
+
+ if (!(flags & TDF_SLIM))
+ {
+ fprintf (stream, "VTT for %s\n",
+ type_as_string (t, TFF_PLAIN_IDENTIFIER));
+ dump_array (stream, vtt);
+ fprintf (stream, "\n");
+ }
+
+ dump_end (TDI_class, stream);
+ }
+
/* Virtual function table initialization. */
/* Create all the necessary vtables for T and its base classes. */
*************** initialize_vtable (binfo, inits)
*** 6974,6979 ****
--- 7114,7120 ----
layout_vtable_decl (binfo, list_length (inits));
decl = get_vtbl_decl_for_binfo (binfo);
initialize_array (decl, inits);
+ dump_vtable (BINFO_TYPE (binfo), binfo, decl);
}
/* Initialize DECL (a declaration for a namespace-scope array) with
*************** build_vtt (t)
*** 7031,7036 ****
--- 7172,7179 ----
vtt = build_vtable (t, get_vtt_name (t), type);
pushdecl_top_level (vtt);
initialize_array (vtt, inits);
+
+ dump_vtt (t, vtt);
}
/* The type corresponding to BASE_BINFO is a base of the type of BINFO, but
*************** build_ctor_vtbl_group (binfo, t)
*** 7348,7353 ****
--- 7491,7497 ----
/* Initialize the construction vtable. */
pushdecl_top_level (vtbl);
initialize_array (vtbl, inits);
+ dump_vtable (t, binfo, vtbl);
}
/* Add the vtbl initializers for BINFO (and its bases other than
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.437.2.23
diff -c -3 -p -r1.437.2.23 decl2.c
*** decl2.c 2001/06/01 11:57:55 1.437.2.23
--- decl2.c 2001/06/04 08:15:30
*************** int flag_operator_names = 1;
*** 383,392 ****
int flag_check_new;
- /* Nonnull if we want to dump class heirarchies. */
-
- const char *flag_dump_class_layout;
-
/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
initialization variables.
0: Old rules, set by -fno-for-scope.
--- 383,388 ----
*************** cxx_decode_option (argc, argv)
*** 604,628 ****
{
warning ("-fname-mangling-version is no longer supported");
return 1;
- }
- else if ((option_value
- = skip_leading_substring (p, "dump-translation-unit=")))
- {
- if (!*option_value)
- error ("no file specified with -fdump-translation-unit");
- else
- flag_dump_translation_unit = option_value;
- }
- else if ((option_value
- = skip_leading_substring (p, "dump-class-layout=")))
- {
- if (!*option_value)
- error ("no file specified with -fdump-class-layout");
- else
- flag_dump_class_layout = option_value;
}
! else if (!strcmp (p, "dump-class-layout"))
! flag_dump_class_layout = ""; /* empty string for stderr */
else
{
int found = 0;
--- 600,608 ----
{
warning ("-fname-mangling-version is no longer supported");
return 1;
}
! else if (dump_switch_p (p))
! ;
else
{
int found = 0;
*************** finish_file ()
*** 3731,3739 ****
/* The entire file is now complete. If requested, dump everything
to a file. */
! if (flag_dump_translation_unit)
! dump_node_to_file (global_namespace, flag_dump_translation_unit);
/* If there's some tool that wants to examine the entire translation
unit, let it do so now. */
if (back_end_hook)
--- 3711,3727 ----
/* The entire file is now complete. If requested, dump everything
to a file. */
! {
! int flags;
! FILE *stream = dump_begin (TDI_all, &flags);
+ if (stream)
+ {
+ dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_all, stream);
+ }
+ }
+
/* If there's some tool that wants to examine the entire translation
unit, let it do so now. */
if (back_end_hook)
Index: cp/dump.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/dump.c,v
retrieving revision 1.52.4.3
diff -c -3 -p -r1.52.4.3 dump.c
*** dump.c 2001/05/13 07:10:21 1.52.4.3
--- dump.c 2001/06/04 08:15:31
*************** cp_dump_tree (di, t)
*** 101,119 ****
}
dump_child ("vfld", TYPE_VFIELD (t));
-
- {
- int i;
! for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
! {
! tree base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
! dump_child ("base", BINFO_TYPE (base_binfo));
! if (TREE_VIA_VIRTUAL (base_binfo))
! dump_string (di, "virtual");
! dump_access (di, base_binfo);
! }
! }
break;
case FIELD_DECL:
--- 101,120 ----
}
dump_child ("vfld", TYPE_VFIELD (t));
! if (!dump_flag (di, TDF_SLIM, t))
! {
! int i;
!
! for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
! {
! tree base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
! dump_child ("base", BINFO_TYPE (base_binfo));
! if (TREE_VIA_VIRTUAL (base_binfo))
! dump_string (di, "virtual");
! dump_access (di, base_binfo);
! }
! }
break;
case FIELD_DECL:
*************** cp_dump_tree (di, t)
*** 163,169 ****
break;
if (DECL_NAMESPACE_ALIAS (t))
dump_child ("alis", DECL_NAMESPACE_ALIAS (t));
! else
dump_child ("dcls", cp_namespace_decls (t));
break;
--- 164,170 ----
break;
if (DECL_NAMESPACE_ALIAS (t))
dump_child ("alis", DECL_NAMESPACE_ALIAS (t));
! else if (!dump_flag (di, TDF_SLIM, t))
dump_child ("dcls", cp_namespace_decls (t));
break;
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.51.2.19
diff -c -3 -p -r1.51.2.19 optimize.c
*** optimize.c 2001/05/30 08:41:01 1.51.2.19
--- optimize.c 2001/06/04 08:15:31
*************** static void remap_block PARAMS ((tree, t
*** 100,105 ****
--- 100,106 ----
static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
static void update_cloned_parm PARAMS ((tree, tree));
+ static void dump_function PARAMS ((enum tree_dump_index, tree));
/* The approximate number of instructions per statement. This number
need not be particularly accurate; it is used only to make
*************** expand_calls_inline (tp, id)
*** 933,944 ****
walk_tree (tp, expand_call_inline, id, id->tree_pruner);
}
! /* Optimize the body of FN. */
void
optimize_function (fn)
tree fn;
{
/* While in this function, we may choose to go off and compile
another function. For example, we might instantiate a function
in the hopes of inlining it. Normally, that wouldn't trigger any
--- 934,947 ----
walk_tree (tp, expand_call_inline, id, id->tree_pruner);
}
! /* Optimize the body of FN. */
void
optimize_function (fn)
tree fn;
{
+ dump_function (TDI_raw, fn);
+
/* While in this function, we may choose to go off and compile
another function. For example, we might instantiate a function
in the hopes of inlining it. Normally, that wouldn't trigger any
*************** optimize_function (fn)
*** 1010,1015 ****
--- 1013,1020 ----
/* Undo the call to ggc_push_context above. */
--function_depth;
+
+ dump_function (TDI_cooked, fn);
}
/* Called from calls_setjmp_p via walk_tree. */
*************** maybe_clone_body (fn)
*** 1226,1229 ****
--- 1231,1257 ----
/* We don't need to process the original function any further. */
return 1;
+ }
+
+ /* Dump FUNCTION_DECL FN as tree dump PHASE. */
+
+ static void
+ dump_function (phase, fn)
+ enum tree_dump_index phase;
+ tree fn;
+ {
+ FILE *stream;
+ int flags;
+
+ stream = dump_begin (phase, &flags);
+ if (stream)
+ {
+ fprintf (stream, "\n;; Function %s",
+ decl_as_string (fn, TFF_DECL_SPECIFIERS));
+ fprintf (stream, " (%s)", decl_as_string (DECL_ASSEMBLER_NAME (fn), 0));
+ fprintf (stream, "\n\n");
+
+ dump_node (fn, TDF_SLIM | flags, stream);
+ dump_end (phase, stream);
+ }
}
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.189.2.12
diff -c -3 -p -r1.189.2.12 semantics.c
*** semantics.c 2001/05/26 19:13:56 1.189.2.12
--- semantics.c 2001/06/04 08:15:32
*************** expand_body (fn)
*** 2454,2460 ****
/* If possible, obliterate the body of the function so that it can
be garbage collected. */
! if (flag_dump_translation_unit)
/* Keep the body; we're going to dump it. */
;
else if (DECL_INLINE (fn) && flag_inline_trees)
--- 2454,2460 ----
/* If possible, obliterate the body of the function so that it can
be garbage collected. */
! if (dump_enabled_p (TDI_all))
/* Keep the body; we're going to dump it. */
;
else if (DECL_INLINE (fn) && flag_inline_trees)