flags.h: Add flag_eliminate_unused_debug_types.

* flags.h: Add flag_eliminate_unused_debug_types.
        * toplev.c: Add flag_eliminate_unused_debug_types.
        (f_options): Add -feliminate-unused-debug-types.
        * dwarf2out.c (struct file_table): Add emitted member.
        (splice_child_die): Fix the parent pointer for the child being
        spliced.
        (lookup_filename): Maintain file_table.emitted array.  Don't
        output .file directive here.
        (maybe_emit_file): (new)
        (init_file_table): Set up file_table.emitted.
        (dwarf2out_source_line): Use maybe_emit_file.
        (dwarf2out_start_source_file): Use maybe_emit_file.
        (dwarf2out_init): Use maybe_emit_file.
        (prune_unused_types_walk_attribs): (new)
        (prune_unused_types_mark): (new)
        (prune_unused_types_walk): (new)
        (prune_unused_types_prune): (new)
        (prune_unused_types): (new)
        (dwarf2out_finish): Call prune_unused_types if
        flag_eliminate_unused_debug_types is set.
        * doc/invoke.texi (Option Summary): Add
        -feliminate-unused-debug-types.
        (Debugging Options): Likewise.

From-SVN: r63588
This commit is contained in:
Scott Snyder 2003-02-28 15:57:50 -08:00 committed by Richard Henderson
parent d8fad4ea49
commit 73c68f614d
5 changed files with 445 additions and 153 deletions

View File

@ -1,3 +1,29 @@
2003-02-28 scott snyder <snyder@fnal.gov>
* flags.h: Add flag_eliminate_unused_debug_types.
* toplev.c: Add flag_eliminate_unused_debug_types.
(f_options): Add -feliminate-unused-debug-types.
* dwarf2out.c (struct file_table): Add emitted member.
(splice_child_die): Fix the parent pointer for the child being
spliced.
(lookup_filename): Maintain file_table.emitted array. Don't
output .file directive here.
(maybe_emit_file): (new)
(init_file_table): Set up file_table.emitted.
(dwarf2out_source_line): Use maybe_emit_file.
(dwarf2out_start_source_file): Use maybe_emit_file.
(dwarf2out_init): Use maybe_emit_file.
(prune_unused_types_walk_attribs): (new)
(prune_unused_types_mark): (new)
(prune_unused_types_walk): (new)
(prune_unused_types_prune): (new)
(prune_unused_types): (new)
(dwarf2out_finish): Call prune_unused_types if
flag_eliminate_unused_debug_types is set.
* doc/invoke.texi (Option Summary): Add
-feliminate-unused-debug-types.
(Debugging Options): Likewise.
2003-02-28 Geoffrey Keating <geoffk@apple.com> 2003-02-28 Geoffrey Keating <geoffk@apple.com>
* doc/invoke.texi: Change .pch to .gch. * doc/invoke.texi: Change .pch to .gch.

View File

@ -258,6 +258,7 @@ in the following sections.
-p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol -p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol
-print-multi-directory -print-multi-lib @gol -print-multi-directory -print-multi-lib @gol
-print-prog-name=@var{program} -print-search-dirs -Q @gol -print-prog-name=@var{program} -print-search-dirs -Q @gol
-feliminate-unused-debug-types @gol
-save-temps -time} -save-temps -time}
@item Optimization Options @item Optimization Options
@ -3412,6 +3413,18 @@ anything else.
@opindex dumpspecs @opindex dumpspecs
Print the compiler's built-in specs---and don't do anything else. (This Print the compiler's built-in specs---and don't do anything else. (This
is used when GCC itself is being built.) @xref{Spec Files}. is used when GCC itself is being built.) @xref{Spec Files}.
@item -feliminate-unused-debug-types
@opindex feliminate-unused-debug-types
Normally, when producing DWARF2 output, GCC will emit debugging
information for all types declared in a compilation
unit, regardless of whether or not they are actually used
in that compilation unit. Sometimes this is useful, such as
if, in the debugger, you want to cast a value to a type that is
not actually used in your program (but is declared). More often,
however, this results in a significant amount of wasted space.
With this option, GCC will avoid producing debug symbol output
for types that are nowhere used in the source file being compiled.
@end table @end table
@node Optimize Options @node Optimize Options

View File

@ -3458,6 +3458,7 @@ static GTY(()) limbo_die_node *limbo_die_list;
/* Filenames referenced by this compilation unit. */ /* Filenames referenced by this compilation unit. */
static GTY(()) varray_type file_table; static GTY(()) varray_type file_table;
static GTY(()) varray_type file_table_emitted;
static GTY(()) size_t file_table_last_lookup_index; static GTY(()) size_t file_table_last_lookup_index;
/* A pointer to the base of a table of references to DIE's that describe /* A pointer to the base of a table of references to DIE's that describe
@ -3844,6 +3845,14 @@ static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *,
static void output_loc_list PARAMS ((dw_loc_list_ref)); static void output_loc_list PARAMS ((dw_loc_list_ref));
static char *gen_internal_sym PARAMS ((const char *)); static char *gen_internal_sym PARAMS ((const char *));
static void prune_unmark_dies PARAMS ((dw_die_ref));
static void prune_unused_types_mark PARAMS ((dw_die_ref, int));
static void prune_unused_types_walk PARAMS ((dw_die_ref));
static void prune_unused_types_walk_attribs PARAMS ((dw_die_ref));
static void prune_unused_types_prune PARAMS ((dw_die_ref));
static void prune_unused_types PARAMS ((void));
static int maybe_emit_file PARAMS ((int));
/* Section names used to hold DWARF debugging information. */ /* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION #ifndef DEBUG_INFO_SECTION
#define DEBUG_INFO_SECTION ".debug_info" #define DEBUG_INFO_SECTION ".debug_info"
@ -5217,6 +5226,7 @@ splice_child_die (parent, child)
break; break;
} }
child->die_parent = parent;
child->die_sib = parent->die_child; child->die_sib = parent->die_child;
parent->die_child = child; parent->die_child = child;
} }
@ -12352,25 +12362,43 @@ lookup_filename (file_name)
file_table_last_lookup_index = n; file_table_last_lookup_index = n;
save_file_name = (char *) ggc_strdup (file_name); save_file_name = (char *) ggc_strdup (file_name);
VARRAY_PUSH_CHAR_PTR (file_table, save_file_name); VARRAY_PUSH_CHAR_PTR (file_table, save_file_name);
VARRAY_PUSH_UINT (file_table_emitted, 0);
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
fprintf (asm_out_file, "\t.file %lu ", (unsigned long) i);
output_quoted_string (asm_out_file, file_name);
fputc ('\n', asm_out_file);
}
return i; return i;
} }
static int
maybe_emit_file (fileno)
int fileno;
{
static int emitcount = 0;
if (DWARF2_ASM_LINE_DEBUG_INFO && fileno > 0)
{
if (!VARRAY_UINT (file_table_emitted, fileno))
{
VARRAY_UINT (file_table_emitted, fileno) = ++emitcount;
fprintf (asm_out_file, "\t.file %u ",
VARRAY_UINT (file_table_emitted, fileno));
output_quoted_string (asm_out_file,
VARRAY_CHAR_PTR (file_table, fileno));
fputc ('\n', asm_out_file);
}
return VARRAY_UINT (file_table_emitted, fileno);
}
else
return fileno;
}
static void static void
init_file_table () init_file_table ()
{ {
/* Allocate the initial hunk of the file_table. */ /* Allocate the initial hunk of the file_table. */
VARRAY_CHAR_PTR_INIT (file_table, 64, "file_table"); VARRAY_CHAR_PTR_INIT (file_table, 64, "file_table");
VARRAY_UINT_INIT (file_table_emitted, 64, "file_table_emitted");
/* Skip the first entry - file numbers begin at 1. */ /* Skip the first entry - file numbers begin at 1. */
VARRAY_PUSH_CHAR_PTR (file_table, NULL); VARRAY_PUSH_CHAR_PTR (file_table, NULL);
VARRAY_PUSH_UINT (file_table_emitted, 0);
file_table_last_lookup_index = 0; file_table_last_lookup_index = 0;
} }
@ -12396,6 +12424,8 @@ dwarf2out_source_line (line, filename)
{ {
unsigned file_num = lookup_filename (filename); unsigned file_num = lookup_filename (filename);
file_num = maybe_emit_file (file_num);
/* Emit the .loc directive understood by GNU as. */ /* Emit the .loc directive understood by GNU as. */
fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line);
@ -12487,6 +12517,7 @@ dwarf2out_start_source_file (lineno, filename)
dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", dw2_asm_output_data_uleb128 (lineno, "Included from line number %d",
lineno); lineno);
maybe_emit_file (lookup_filename (filename));
dw2_asm_output_data_uleb128 (lookup_filename (filename), dw2_asm_output_data_uleb128 (lookup_filename (filename),
"Filename we just started"); "Filename we just started");
} }
@ -12646,6 +12677,215 @@ output_indirect_string (h, v)
return 1; return 1;
} }
/* Clear the marks for a die and its children.
Be cool if the mark isn't set. */
static void
prune_unmark_dies (die)
dw_die_ref die;
{
dw_die_ref c;
die->die_mark = 0;
for (c = die->die_child; c; c = c->die_sib)
prune_unmark_dies (c);
}
/* Given DIE that we're marking as used, find any other dies
it references as attributes and mark them as used. */
static void
prune_unused_types_walk_attribs (die)
dw_die_ref die;
{
dw_attr_ref a;
for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
{
if (a->dw_attr_val.val_class == dw_val_class_die_ref)
{
/* A reference to another DIE.
Make sure that it will get emitted. */
prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
}
else if (a->dw_attr == DW_AT_decl_file)
{
/* A reference to a file. Make sure the file name is emitted. */
a->dw_attr_val.v.val_unsigned =
maybe_emit_file (a->dw_attr_val.v.val_unsigned);
}
}
}
/* Mark DIE as being used. If DOKIDS is true, then walk down
to DIE's children. */
static void
prune_unused_types_mark (die, dokids)
dw_die_ref die;
int dokids;
{
dw_die_ref c;
if (die->die_mark == 0)
{
/* We haven't done this node yet. Mark it as used. */
die->die_mark = 1;
/* We also have to mark its parents as used.
(But we don't want to mark our parents' kids due to this.) */
if (die->die_parent)
prune_unused_types_mark (die->die_parent, 0);
/* Mark any referenced nodes. */
prune_unused_types_walk_attribs (die);
}
if (dokids && die->die_mark != 2)
{
/* We need to walk the children, but haven't done so yet.
Remember that we've walked the kids. */
die->die_mark = 2;
/* Walk them. */
for (c = die->die_child; c; c = c->die_sib)
{
/* If this is an array type, we need to make sure our
kids get marked, even if they're types. */
if (die->die_tag == DW_TAG_array_type)
prune_unused_types_mark (c, 1);
else
prune_unused_types_walk (c);
}
}
}
/* Walk the tree DIE and mark types that we actually use. */
static void
prune_unused_types_walk (die)
dw_die_ref die;
{
dw_die_ref c;
/* Don't do anything if this node is already marked. */
if (die->die_mark)
return;
switch (die->die_tag) {
case DW_TAG_const_type:
case DW_TAG_packed_type:
case DW_TAG_pointer_type:
case DW_TAG_reference_type:
case DW_TAG_volatile_type:
case DW_TAG_typedef:
case DW_TAG_array_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
case DW_TAG_friend:
case DW_TAG_variant_part:
case DW_TAG_enumeration_type:
case DW_TAG_subroutine_type:
case DW_TAG_string_type:
case DW_TAG_set_type:
case DW_TAG_subrange_type:
case DW_TAG_ptr_to_member_type:
case DW_TAG_file_type:
/* It's a type node --- don't mark it. */
return;
default:
/* Mark everything else. */
break;
}
die->die_mark = 1;
/* Now, mark any dies referenced from here. */
prune_unused_types_walk_attribs (die);
/* Mark children. */
for (c = die->die_child; c; c = c->die_sib)
prune_unused_types_walk (c);
}
/* Remove from the tree DIE any dies that aren't marked. */
static void
prune_unused_types_prune (die)
dw_die_ref die;
{
dw_die_ref c, p, n;
if (!die->die_mark)
abort();
p = NULL;
for (c = die->die_child; c; c = n)
{
n = c->die_sib;
if (c->die_mark)
{
prune_unused_types_prune (c);
p = c;
}
else
{
if (p)
p->die_sib = n;
else
die->die_child = n;
free_die (c);
}
}
}
/* Remove dies representing declarations that we never use. */
static void
prune_unused_types ()
{
unsigned int i;
limbo_die_node *node;
/* Clear all the marks. */
prune_unmark_dies (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unmark_dies (node->die);
/* Set the mark on nodes that are actually used. */
prune_unused_types_walk (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_walk (node->die);
/* Also set the mark on nodes referenced from the
pubname_table or arange_table. */
for (i=0; i < pubname_table_in_use; i++)
{
prune_unused_types_mark (pubname_table[i].die, 1);
}
for (i=0; i < arange_table_in_use; i++)
{
prune_unused_types_mark (arange_table[i], 1);
}
/* Get rid of nodes that aren't marked. */
prune_unused_types_prune (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_prune (node->die);
/* Leave the marks clear. */
prune_unmark_dies (comp_unit_die);
for (node = limbo_die_list; node; node = node->next)
prune_unmark_dies (node->die);
}
/* Output stuff that dwarf requires at the end of every file, /* Output stuff that dwarf requires at the end of every file,
and generate the DWARF-2 debugging info. */ and generate the DWARF-2 debugging info. */
@ -12740,6 +12980,9 @@ dwarf2out_finish (input_filename)
if (flag_eliminate_dwarf2_dups) if (flag_eliminate_dwarf2_dups)
break_out_includes (comp_unit_die); break_out_includes (comp_unit_die);
if (flag_eliminate_unused_debug_types)
prune_unused_types ();
/* Traverse the DIE's and add add sibling attributes to those DIE's /* Traverse the DIE's and add add sibling attributes to those DIE's
that have children. */ that have children. */
add_sibling_attributes (comp_unit_die); add_sibling_attributes (comp_unit_die);

View File

@ -641,6 +641,10 @@ extern int flag_gcse_sm;
extern int flag_eliminate_dwarf2_dups; extern int flag_eliminate_dwarf2_dups;
/* Nonzero means we should do unused type elimination. */
extern int flag_eliminate_unused_debug_types;
/* Nonzero means to collect statistics which might be expensive /* Nonzero means to collect statistics which might be expensive
and to print them when we are done. */ and to print them when we are done. */
extern int flag_detailed_statistics; extern int flag_detailed_statistics;

View File

@ -378,6 +378,10 @@ tree current_function_func_begin_label;
int flag_eliminate_dwarf2_dups = 0; int flag_eliminate_dwarf2_dups = 0;
/* Nonzero if doing unused type elimination. */
int flag_eliminate_unused_debug_types = 0;
/* Nonzero if generating code to do profiling. */ /* Nonzero if generating code to do profiling. */
int profile_flag = 0; int profile_flag = 0;
@ -999,6 +1003,8 @@ static const lang_independent_options f_options[] =
{ {
{"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1, {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
N_("Perform DWARF2 duplicate elimination") }, N_("Perform DWARF2 duplicate elimination") },
{"eliminate-unused-debug-types", &flag_eliminate_unused_debug_types, 1,
N_("Perform unused type elimination in debug info") },
{"float-store", &flag_float_store, 1, {"float-store", &flag_float_store, 1,
N_("Do not store floats in registers") }, N_("Do not store floats in registers") },
{"defer-pop", &flag_defer_pop, 1, {"defer-pop", &flag_defer_pop, 1,