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:
parent
d8fad4ea49
commit
73c68f614d
@ -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>
|
||||
|
||||
* doc/invoke.texi: Change .pch to .gch.
|
||||
|
@ -258,6 +258,7 @@ in the following sections.
|
||||
-p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol
|
||||
-print-multi-directory -print-multi-lib @gol
|
||||
-print-prog-name=@var{program} -print-search-dirs -Q @gol
|
||||
-feliminate-unused-debug-types @gol
|
||||
-save-temps -time}
|
||||
|
||||
@item Optimization Options
|
||||
@ -3412,6 +3413,18 @@ anything else.
|
||||
@opindex dumpspecs
|
||||
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}.
|
||||
|
||||
@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
|
||||
|
||||
@node Optimize Options
|
||||
|
549
gcc/dwarf2out.c
549
gcc/dwarf2out.c
@ -337,7 +337,7 @@ static void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *));
|
||||
/* Support for complex CFA locations. */
|
||||
static void output_cfa_loc PARAMS ((dw_cfi_ref));
|
||||
static void get_cfa_from_loc_descr PARAMS ((dw_cfa_location *,
|
||||
struct dw_loc_descr_struct *));
|
||||
struct dw_loc_descr_struct *));
|
||||
static struct dw_loc_descr_struct *build_cfa_loc
|
||||
PARAMS ((dw_cfa_location *));
|
||||
static void def_cfa_1 PARAMS ((const char *,
|
||||
@ -1236,7 +1236,7 @@ static dw_cfa_location cfa_temp;
|
||||
Rule 1:
|
||||
(set <reg1> <reg2>:cfa.reg)
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa.offset unchanged
|
||||
cfa.offset unchanged
|
||||
cfa_temp.reg = <reg1>
|
||||
cfa_temp.offset = cfa.offset
|
||||
|
||||
@ -1357,7 +1357,7 @@ dwarf2out_frame_debug_expr (expr, label)
|
||||
case REG:
|
||||
/* Rule 1 */
|
||||
/* Update the CFA rule wrt SP or FP. Make sure src is
|
||||
relative to the current CFA register. */
|
||||
relative to the current CFA register. */
|
||||
switch (GET_CODE (src))
|
||||
{
|
||||
/* Setting FP from SP. */
|
||||
@ -1620,7 +1620,7 @@ dwarf2out_frame_debug_expr (expr, label)
|
||||
else
|
||||
{
|
||||
/* Otherwise, we'll need to look in the stack to
|
||||
calculate the CFA. */
|
||||
calculate the CFA. */
|
||||
rtx x = XEXP (dest, 0);
|
||||
|
||||
if (GET_CODE (x) != REG)
|
||||
@ -2123,13 +2123,13 @@ output_call_frame_info (for_eh)
|
||||
dw2_asm_output_data_uleb128 (size, "Augmentation size");
|
||||
|
||||
if (fde->uses_eh_lsda)
|
||||
{
|
||||
ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA",
|
||||
{
|
||||
ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA",
|
||||
fde->funcdef_number);
|
||||
dw2_asm_output_encoded_addr_rtx (
|
||||
dw2_asm_output_encoded_addr_rtx (
|
||||
lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1),
|
||||
"Language Specific Data Area");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lsda_encoding == DW_EH_PE_aligned)
|
||||
@ -2151,7 +2151,7 @@ output_call_frame_info (for_eh)
|
||||
|
||||
/* Pad the FDE out to an address sized boundary. */
|
||||
ASM_OUTPUT_ALIGN (asm_out_file,
|
||||
floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
|
||||
floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
|
||||
ASM_OUTPUT_LABEL (asm_out_file, l2);
|
||||
}
|
||||
|
||||
@ -2953,9 +2953,9 @@ output_loc_operands (loc)
|
||||
case DW_OP_skip:
|
||||
case DW_OP_bra:
|
||||
/* We currently don't make any attempt to make sure these are
|
||||
aligned properly like we do for the main unwind info, so
|
||||
don't support emitting things larger than a byte if we're
|
||||
only doing unwinding. */
|
||||
aligned properly like we do for the main unwind info, so
|
||||
don't support emitting things larger than a byte if we're
|
||||
only doing unwinding. */
|
||||
abort ();
|
||||
#endif
|
||||
case DW_OP_const1u:
|
||||
@ -3458,6 +3458,7 @@ static GTY(()) limbo_die_node *limbo_die_list;
|
||||
|
||||
/* Filenames referenced by this compilation unit. */
|
||||
static GTY(()) varray_type file_table;
|
||||
static GTY(()) varray_type file_table_emitted;
|
||||
static GTY(()) size_t file_table_last_lookup_index;
|
||||
|
||||
/* 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 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. */
|
||||
#ifndef DEBUG_INFO_SECTION
|
||||
#define DEBUG_INFO_SECTION ".debug_info"
|
||||
@ -5217,6 +5226,7 @@ splice_child_die (parent, child)
|
||||
break;
|
||||
}
|
||||
|
||||
child->die_parent = parent;
|
||||
child->die_sib = parent->die_child;
|
||||
parent->die_child = child;
|
||||
}
|
||||
@ -5699,12 +5709,12 @@ same_dw_val_p (v1, v2, mark)
|
||||
return v1->v.val_unsigned == v2->v.val_unsigned;
|
||||
case dw_val_class_long_long:
|
||||
return v1->v.val_long_long.hi == v2->v.val_long_long.hi
|
||||
&& v1->v.val_long_long.low == v2->v.val_long_long.low;
|
||||
&& v1->v.val_long_long.low == v2->v.val_long_long.low;
|
||||
case dw_val_class_float:
|
||||
if (v1->v.val_float.length != v2->v.val_float.length)
|
||||
return 0;
|
||||
for (i = 0; i < v1->v.val_float.length; i++)
|
||||
if (v1->v.val_float.array[i] != v2->v.val_float.array[i])
|
||||
if (v1->v.val_float.array[i] != v2->v.val_float.array[i])
|
||||
return 0;
|
||||
return 1;
|
||||
case dw_val_class_flag:
|
||||
@ -6145,7 +6155,7 @@ break_out_includes (die)
|
||||
if (is_dupl)
|
||||
*pnode = node->next;
|
||||
else
|
||||
{
|
||||
{
|
||||
pnode = &node->next;
|
||||
record_comdat_symbol_number (node->die, cu_hash_table,
|
||||
comdat_symbol_number);
|
||||
@ -7078,7 +7088,7 @@ output_aranges ()
|
||||
if (DWARF_ARANGES_PAD_SIZE)
|
||||
{
|
||||
/* Pad using a 2 byte words so that padding is correct for any
|
||||
pointer size. */
|
||||
pointer size. */
|
||||
dw2_asm_output_data (2, 0, "Pad to %d byte boundary",
|
||||
2 * DWARF2_ADDR_SIZE);
|
||||
for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2)
|
||||
@ -7582,8 +7592,8 @@ output_line_info ()
|
||||
prologue. */
|
||||
|
||||
/* Don't emit anything for redundant notes. Just updating the
|
||||
address doesn't accomplish anything, because we already assume
|
||||
that anything after the last address is this line. */
|
||||
address doesn't accomplish anything, because we already assume
|
||||
that anything after the last address is this line. */
|
||||
if (line_info->dw_line_num == current_line
|
||||
&& line_info->dw_file_num == current_file)
|
||||
continue;
|
||||
@ -7609,7 +7619,7 @@ output_line_info ()
|
||||
else
|
||||
{
|
||||
/* This can handle any delta. This takes
|
||||
4+DWARF2_ADDR_SIZE bytes. */
|
||||
4+DWARF2_ADDR_SIZE bytes. */
|
||||
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
||||
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
||||
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
||||
@ -7831,9 +7841,9 @@ base_type_die (type)
|
||||
{
|
||||
case INTEGER_TYPE:
|
||||
/* Carefully distinguish the C character types, without messing
|
||||
up if the language is not C. Note that we check only for the names
|
||||
that contain spaces; other names might occur by coincidence in other
|
||||
languages. */
|
||||
up if the language is not C. Note that we check only for the names
|
||||
that contain spaces; other names might occur by coincidence in other
|
||||
languages. */
|
||||
if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE
|
||||
&& (type == char_type_node
|
||||
|| ! strcmp (type_name, "signed char")
|
||||
@ -8284,28 +8294,28 @@ mem_loc_descriptor (rtl, mode)
|
||||
|
||||
case SUBREG:
|
||||
/* The case of a subreg may arise when we have a local (register)
|
||||
variable or a formal (register) parameter which doesn't quite fill
|
||||
up an entire register. For now, just assume that it is
|
||||
legitimate to make the Dwarf info refer to the whole register which
|
||||
contains the given subreg. */
|
||||
variable or a formal (register) parameter which doesn't quite fill
|
||||
up an entire register. For now, just assume that it is
|
||||
legitimate to make the Dwarf info refer to the whole register which
|
||||
contains the given subreg. */
|
||||
rtl = SUBREG_REG (rtl);
|
||||
|
||||
/* ... fall through ... */
|
||||
|
||||
case REG:
|
||||
/* Whenever a register number forms a part of the description of the
|
||||
method for calculating the (dynamic) address of a memory resident
|
||||
object, DWARF rules require the register number be referred to as
|
||||
a "base register". This distinction is not based in any way upon
|
||||
what category of register the hardware believes the given register
|
||||
belongs to. This is strictly DWARF terminology we're dealing with
|
||||
here. Note that in cases where the location of a memory-resident
|
||||
data object could be expressed as: OP_ADD (OP_BASEREG (basereg),
|
||||
OP_CONST (0)) the actual DWARF location descriptor that we generate
|
||||
may just be OP_BASEREG (basereg). This may look deceptively like
|
||||
the object in question was allocated to a register (rather than in
|
||||
memory) so DWARF consumers need to be aware of the subtle
|
||||
distinction between OP_REG and OP_BASEREG. */
|
||||
method for calculating the (dynamic) address of a memory resident
|
||||
object, DWARF rules require the register number be referred to as
|
||||
a "base register". This distinction is not based in any way upon
|
||||
what category of register the hardware believes the given register
|
||||
belongs to. This is strictly DWARF terminology we're dealing with
|
||||
here. Note that in cases where the location of a memory-resident
|
||||
data object could be expressed as: OP_ADD (OP_BASEREG (basereg),
|
||||
OP_CONST (0)) the actual DWARF location descriptor that we generate
|
||||
may just be OP_BASEREG (basereg). This may look deceptively like
|
||||
the object in question was allocated to a register (rather than in
|
||||
memory) so DWARF consumers need to be aware of the subtle
|
||||
distinction between OP_REG and OP_BASEREG. */
|
||||
if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
|
||||
mem_loc_result = based_loc_descr (reg_number (rtl), 0);
|
||||
break;
|
||||
@ -8354,7 +8364,7 @@ mem_loc_descriptor (rtl, mode)
|
||||
|
||||
case PRE_MODIFY:
|
||||
/* Extract the PLUS expression nested inside and fall into
|
||||
PLUS code below. */
|
||||
PLUS code below. */
|
||||
rtl = XEXP (rtl, 1);
|
||||
goto plus;
|
||||
|
||||
@ -8475,10 +8485,10 @@ loc_descriptor (rtl)
|
||||
{
|
||||
case SUBREG:
|
||||
/* The case of a subreg may arise when we have a local (register)
|
||||
variable or a formal (register) parameter which doesn't quite fill
|
||||
up an entire register. For now, just assume that it is
|
||||
legitimate to make the Dwarf info refer to the whole register which
|
||||
contains the given subreg. */
|
||||
variable or a formal (register) parameter which doesn't quite fill
|
||||
up an entire register. For now, just assume that it is
|
||||
legitimate to make the Dwarf info refer to the whole register which
|
||||
contains the given subreg. */
|
||||
rtl = SUBREG_REG (rtl);
|
||||
|
||||
/* ... fall through ... */
|
||||
@ -9199,9 +9209,9 @@ add_const_value_attribute (die, rtl)
|
||||
|
||||
case CONST_DOUBLE:
|
||||
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
|
||||
floating-point constant. A CONST_DOUBLE is used whenever the
|
||||
constant requires more than one word in order to be adequately
|
||||
represented. We output CONST_DOUBLEs as blocks. */
|
||||
floating-point constant. A CONST_DOUBLE is used whenever the
|
||||
constant requires more than one word in order to be adequately
|
||||
represented. We output CONST_DOUBLEs as blocks. */
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (rtl);
|
||||
|
||||
@ -9258,16 +9268,16 @@ add_const_value_attribute (die, rtl)
|
||||
|
||||
case PLUS:
|
||||
/* In cases where an inlined instance of an inline function is passed
|
||||
the address of an `auto' variable (which is local to the caller) we
|
||||
can get a situation where the DECL_RTL of the artificial local
|
||||
variable (for the inlining) which acts as a stand-in for the
|
||||
corresponding formal parameter (of the inline function) will look
|
||||
like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not
|
||||
exactly a compile-time constant expression, but it isn't the address
|
||||
of the (artificial) local variable either. Rather, it represents the
|
||||
*value* which the artificial local variable always has during its
|
||||
lifetime. We currently have no way to represent such quasi-constant
|
||||
values in Dwarf, so for now we just punt and generate nothing. */
|
||||
the address of an `auto' variable (which is local to the caller) we
|
||||
can get a situation where the DECL_RTL of the artificial local
|
||||
variable (for the inlining) which acts as a stand-in for the
|
||||
corresponding formal parameter (of the inline function) will look
|
||||
like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not
|
||||
exactly a compile-time constant expression, but it isn't the address
|
||||
of the (artificial) local variable either. Rather, it represents the
|
||||
*value* which the artificial local variable always has during its
|
||||
lifetime. We currently have no way to represent such quasi-constant
|
||||
values in Dwarf, so for now we just punt and generate nothing. */
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -9366,7 +9376,7 @@ rtl_for_decl_location (decl)
|
||||
if (rtl
|
||||
&& (CONSTANT_P (rtl)
|
||||
|| (GET_CODE (rtl) == MEM
|
||||
&& CONSTANT_P (XEXP (rtl, 0)))))
|
||||
&& CONSTANT_P (XEXP (rtl, 0)))))
|
||||
{
|
||||
rtl = (*targetm.delegitimize_address) (rtl);
|
||||
return rtl;
|
||||
@ -9653,23 +9663,23 @@ add_bound_info (subrange_die, bound_attr, bound)
|
||||
|
||||
case SAVE_EXPR:
|
||||
/* If optimization is turned on, the SAVE_EXPRs that describe how to
|
||||
access the upper bound values may be bogus. If they refer to a
|
||||
register, they may only describe how to get at these values at the
|
||||
points in the generated code right after they have just been
|
||||
computed. Worse yet, in the typical case, the upper bound values
|
||||
will not even *be* computed in the optimized code (though the
|
||||
number of elements will), so these SAVE_EXPRs are entirely
|
||||
bogus. In order to compensate for this fact, we check here to see
|
||||
if optimization is enabled, and if so, we don't add an attribute
|
||||
for the (unknown and unknowable) upper bound. This should not
|
||||
cause too much trouble for existing (stupid?) debuggers because
|
||||
they have to deal with empty upper bounds location descriptions
|
||||
anyway in order to be able to deal with incomplete array types.
|
||||
Of course an intelligent debugger (GDB?) should be able to
|
||||
comprehend that a missing upper bound specification in an array
|
||||
type used for a storage class `auto' local array variable
|
||||
indicates that the upper bound is both unknown (at compile- time)
|
||||
and unknowable (at run-time) due to optimization.
|
||||
access the upper bound values may be bogus. If they refer to a
|
||||
register, they may only describe how to get at these values at the
|
||||
points in the generated code right after they have just been
|
||||
computed. Worse yet, in the typical case, the upper bound values
|
||||
will not even *be* computed in the optimized code (though the
|
||||
number of elements will), so these SAVE_EXPRs are entirely
|
||||
bogus. In order to compensate for this fact, we check here to see
|
||||
if optimization is enabled, and if so, we don't add an attribute
|
||||
for the (unknown and unknowable) upper bound. This should not
|
||||
cause too much trouble for existing (stupid?) debuggers because
|
||||
they have to deal with empty upper bounds location descriptions
|
||||
anyway in order to be able to deal with incomplete array types.
|
||||
Of course an intelligent debugger (GDB?) should be able to
|
||||
comprehend that a missing upper bound specification in an array
|
||||
type used for a storage class `auto' local array variable
|
||||
indicates that the upper bound is both unknown (at compile- time)
|
||||
and unknowable (at run-time) due to optimization.
|
||||
|
||||
We assume that a MEM rtx is safe because gcc wouldn't put the
|
||||
value there unless it was going to be used repeatedly in the
|
||||
@ -9790,7 +9800,7 @@ add_subscript_info (type_die, type)
|
||||
|
||||
/* Arrays come in three flavors: Unspecified bounds, fixed bounds,
|
||||
and (in GNU C only) variable bounds. Handle all three forms
|
||||
here. */
|
||||
here. */
|
||||
subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
|
||||
if (domain)
|
||||
{
|
||||
@ -9852,9 +9862,9 @@ add_byte_size_attribute (die, tree_node)
|
||||
break;
|
||||
case FIELD_DECL:
|
||||
/* For a data member of a struct or union, the DW_AT_byte_size is
|
||||
generally given as the number of bytes normally allocated for an
|
||||
object of the *declared* type of the member itself. This is true
|
||||
even for bit-fields. */
|
||||
generally given as the number of bytes normally allocated for an
|
||||
object of the *declared* type of the member itself. This is true
|
||||
even for bit-fields. */
|
||||
size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT;
|
||||
break;
|
||||
default:
|
||||
@ -9979,7 +9989,7 @@ add_abstract_origin_attribute (die, origin)
|
||||
function, if we're in an exception handler or some such; make
|
||||
sure that the abstract function has been written out.
|
||||
|
||||
Doing this for nested functions is wrong, however; functions are
|
||||
Doing this for nested functions is wrong, however; functions are
|
||||
distinct units, and our context might not even be inline. */
|
||||
tree fn = origin;
|
||||
|
||||
@ -10239,8 +10249,8 @@ type_tag (type)
|
||||
t = TYPE_NAME (type);
|
||||
|
||||
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
|
||||
a TYPE_DECL node, regardless of whether or not a `typedef' was
|
||||
involved. */
|
||||
a TYPE_DECL node, regardless of whether or not a `typedef' was
|
||||
involved. */
|
||||
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
||||
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
|
||||
t = DECL_NAME (TYPE_NAME (type));
|
||||
@ -10888,8 +10898,8 @@ gen_subprogram_die (decl, context_die)
|
||||
#endif
|
||||
|
||||
/* Define the "frame base" location for this routine. We use the
|
||||
frame pointer or stack pointer registers, since the RTL for local
|
||||
variables is relative to one of them. */
|
||||
frame pointer or stack pointer registers, since the RTL for local
|
||||
variables is relative to one of them. */
|
||||
fp_reg
|
||||
= frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
|
||||
add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
|
||||
@ -10927,7 +10937,7 @@ gen_subprogram_die (decl, context_die)
|
||||
tree parm;
|
||||
|
||||
/* When generating DIEs, generate the unspecified_parameters DIE
|
||||
instead if we come across the arg "__builtin_va_alist" */
|
||||
instead if we come across the arg "__builtin_va_alist" */
|
||||
for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
|
||||
if (TREE_CODE (parm) == PARM_DECL)
|
||||
{
|
||||
@ -10940,11 +10950,11 @@ gen_subprogram_die (decl, context_die)
|
||||
}
|
||||
|
||||
/* Decide whether we need an unspecified_parameters DIE at the end.
|
||||
There are 2 more cases to do this for: 1) the ansi ... declaration -
|
||||
this is detectable when the end of the arg list is not a
|
||||
void_type_node 2) an unprototyped function declaration (not a
|
||||
definition). This just means that we have no info about the
|
||||
parameters at all. */
|
||||
There are 2 more cases to do this for: 1) the ansi ... declaration -
|
||||
this is detectable when the end of the arg list is not a
|
||||
void_type_node 2) an unprototyped function declaration (not a
|
||||
definition). This just means that we have no info about the
|
||||
parameters at all. */
|
||||
fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
||||
if (fn_arg_types != NULL)
|
||||
{
|
||||
@ -11495,7 +11505,7 @@ gen_struct_or_union_type_die (type, context_die)
|
||||
if (complete)
|
||||
{
|
||||
/* Prevent infinite recursion in cases where the type of some member of
|
||||
this type is expressed in terms of this type itself. */
|
||||
this type is expressed in terms of this type itself. */
|
||||
TREE_ASM_WRITTEN (type) = 1;
|
||||
add_byte_size_attribute (type_die, type);
|
||||
if (TYPE_STUB_DECL (type) != NULL_TREE)
|
||||
@ -11645,7 +11655,7 @@ gen_type_die (type, context_die)
|
||||
TREE_ASM_WRITTEN (type) = 1;
|
||||
|
||||
/* For these types, all that is required is that we output a DIE (or a
|
||||
set of DIEs) to represent the "basis" type. */
|
||||
set of DIEs) to represent the "basis" type. */
|
||||
gen_type_die (TREE_TYPE (type), context_die);
|
||||
break;
|
||||
|
||||
@ -11658,7 +11668,7 @@ gen_type_die (type, context_die)
|
||||
gen_type_die (TREE_TYPE (type), context_die);
|
||||
|
||||
/* Now output a DIE to represent this pointer-to-data-member type
|
||||
itself. */
|
||||
itself. */
|
||||
gen_ptr_to_mbr_type_die (type, context_die);
|
||||
break;
|
||||
|
||||
@ -11703,11 +11713,11 @@ gen_type_die (type, context_die)
|
||||
case UNION_TYPE:
|
||||
case QUAL_UNION_TYPE:
|
||||
/* If this is a nested type whose containing class hasn't been written
|
||||
out yet, writing it out will cover this one, too. This does not apply
|
||||
to instantiations of member class templates; they need to be added to
|
||||
the containing class as they are generated. FIXME: This hurts the
|
||||
idea of combining type decls from multiple TUs, since we can't predict
|
||||
what set of template instantiations we'll get. */
|
||||
out yet, writing it out will cover this one, too. This does not apply
|
||||
to instantiations of member class templates; they need to be added to
|
||||
the containing class as they are generated. FIXME: This hurts the
|
||||
idea of combining type decls from multiple TUs, since we can't predict
|
||||
what set of template instantiations we'll get. */
|
||||
if (TYPE_CONTEXT (type)
|
||||
&& AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
|
||||
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
|
||||
@ -11850,12 +11860,12 @@ gen_block_die (stmt, context_die, depth)
|
||||
else
|
||||
{
|
||||
/* In the case where the current block represents an inlining of the
|
||||
"body block" of an inline function, we must *NOT* output any DIE for
|
||||
this block because we have already output a DIE to represent the whole
|
||||
inlined function scope and the "body block" of any function doesn't
|
||||
really represent a different scope according to ANSI C rules. So we
|
||||
check here to make sure that this block does not represent a "body
|
||||
block inlining" before trying to set the MUST_OUTPUT_DIE flag. */
|
||||
"body block" of an inline function, we must *NOT* output any DIE for
|
||||
this block because we have already output a DIE to represent the whole
|
||||
inlined function scope and the "body block" of any function doesn't
|
||||
really represent a different scope according to ANSI C rules. So we
|
||||
check here to make sure that this block does not represent a "body
|
||||
block inlining" before trying to set the MUST_OUTPUT_DIE flag. */
|
||||
if (! is_body_block (origin ? origin : stmt))
|
||||
{
|
||||
/* Determine if this block directly contains any "significant"
|
||||
@ -11980,7 +11990,7 @@ gen_decl_die (decl, context_die)
|
||||
|
||||
case CONST_DECL:
|
||||
/* The individual enumerators of an enum type get output when we output
|
||||
the Dwarf representation of the relevant enum type itself. */
|
||||
the Dwarf representation of the relevant enum type itself. */
|
||||
break;
|
||||
|
||||
case FUNCTION_DECL:
|
||||
@ -12030,16 +12040,16 @@ gen_decl_die (decl, context_die)
|
||||
|
||||
case TYPE_DECL:
|
||||
/* If we are in terse mode, don't generate any DIEs to represent any
|
||||
actual typedefs. */
|
||||
actual typedefs. */
|
||||
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
||||
break;
|
||||
|
||||
/* In the special case of a TYPE_DECL node representing the declaration
|
||||
of some type tag, if the given TYPE_DECL is marked as having been
|
||||
instantiated from some other (original) TYPE_DECL node (e.g. one which
|
||||
was generated within the original definition of an inline function) we
|
||||
have to generate a special (abbreviated) DW_TAG_structure_type,
|
||||
DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */
|
||||
of some type tag, if the given TYPE_DECL is marked as having been
|
||||
instantiated from some other (original) TYPE_DECL node (e.g. one which
|
||||
was generated within the original definition of an inline function) we
|
||||
have to generate a special (abbreviated) DW_TAG_structure_type,
|
||||
DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */
|
||||
if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE)
|
||||
{
|
||||
gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
|
||||
@ -12060,12 +12070,12 @@ gen_decl_die (decl, context_die)
|
||||
|
||||
case VAR_DECL:
|
||||
/* If we are in terse mode, don't generate any DIEs to represent any
|
||||
variable declarations or definitions. */
|
||||
variable declarations or definitions. */
|
||||
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
||||
break;
|
||||
|
||||
/* Output any DIEs that are needed to specify the type of this data
|
||||
object. */
|
||||
object. */
|
||||
gen_type_die (TREE_TYPE (decl), context_die);
|
||||
|
||||
/* And its containing type. */
|
||||
@ -12074,9 +12084,9 @@ gen_decl_die (decl, context_die)
|
||||
gen_type_die_for_member (origin, decl, context_die);
|
||||
|
||||
/* Now output the DIE to represent the data object itself. This gets
|
||||
complicated because of the possibility that the VAR_DECL really
|
||||
represents an inlined instance of a formal parameter for an inline
|
||||
function. */
|
||||
complicated because of the possibility that the VAR_DECL really
|
||||
represents an inlined instance of a formal parameter for an inline
|
||||
function. */
|
||||
origin = decl_ultimate_origin (decl);
|
||||
if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
|
||||
gen_formal_parameter_die (decl, context_die);
|
||||
@ -12163,32 +12173,32 @@ dwarf2out_decl (decl)
|
||||
|
||||
case FUNCTION_DECL:
|
||||
/* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a
|
||||
builtin function. Explicit programmer-supplied declarations of
|
||||
these same functions should NOT be ignored however. */
|
||||
builtin function. Explicit programmer-supplied declarations of
|
||||
these same functions should NOT be ignored however. */
|
||||
if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl))
|
||||
return;
|
||||
|
||||
/* What we would really like to do here is to filter out all mere
|
||||
file-scope declarations of file-scope functions which are never
|
||||
referenced later within this translation unit (and keep all of ones
|
||||
that *are* referenced later on) but we aren't clairvoyant, so we have
|
||||
no idea which functions will be referenced in the future (i.e. later
|
||||
on within the current translation unit). So here we just ignore all
|
||||
file-scope function declarations which are not also definitions. If
|
||||
and when the debugger needs to know something about these functions,
|
||||
it will have to hunt around and find the DWARF information associated
|
||||
with the definition of the function.
|
||||
file-scope declarations of file-scope functions which are never
|
||||
referenced later within this translation unit (and keep all of ones
|
||||
that *are* referenced later on) but we aren't clairvoyant, so we have
|
||||
no idea which functions will be referenced in the future (i.e. later
|
||||
on within the current translation unit). So here we just ignore all
|
||||
file-scope function declarations which are not also definitions. If
|
||||
and when the debugger needs to know something about these functions,
|
||||
it will have to hunt around and find the DWARF information associated
|
||||
with the definition of the function.
|
||||
|
||||
We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL
|
||||
nodes represent definitions and which ones represent mere
|
||||
declarations. We have to check DECL_INITIAL instead. That's because
|
||||
the C front-end supports some weird semantics for "extern inline"
|
||||
function definitions. These can get inlined within the current
|
||||
translation unit (an thus, we need to generate Dwarf info for their
|
||||
abstract instances so that the Dwarf info for the concrete inlined
|
||||
instances can have something to refer to) but the compiler never
|
||||
generates any out-of-lines instances of such things (despite the fact
|
||||
that they *are* definitions).
|
||||
nodes represent definitions and which ones represent mere
|
||||
declarations. We have to check DECL_INITIAL instead. That's because
|
||||
the C front-end supports some weird semantics for "extern inline"
|
||||
function definitions. These can get inlined within the current
|
||||
translation unit (an thus, we need to generate Dwarf info for their
|
||||
abstract instances so that the Dwarf info for the concrete inlined
|
||||
instances can have something to refer to) but the compiler never
|
||||
generates any out-of-lines instances of such things (despite the fact
|
||||
that they *are* definitions).
|
||||
|
||||
The important point is that the C front-end marks these "extern
|
||||
inline" functions as DECL_EXTERNAL, but we need to generate DWARF for
|
||||
@ -12207,18 +12217,18 @@ dwarf2out_decl (decl)
|
||||
|
||||
case VAR_DECL:
|
||||
/* Ignore this VAR_DECL if it refers to a file-scope extern data object
|
||||
declaration and if the declaration was never even referenced from
|
||||
within this entire compilation unit. We suppress these DIEs in
|
||||
order to save space in the .debug section (by eliminating entries
|
||||
which are probably useless). Note that we must not suppress
|
||||
block-local extern declarations (whether used or not) because that
|
||||
would screw-up the debugger's name lookup mechanism and cause it to
|
||||
miss things which really ought to be in scope at a given point. */
|
||||
declaration and if the declaration was never even referenced from
|
||||
within this entire compilation unit. We suppress these DIEs in
|
||||
order to save space in the .debug section (by eliminating entries
|
||||
which are probably useless). Note that we must not suppress
|
||||
block-local extern declarations (whether used or not) because that
|
||||
would screw-up the debugger's name lookup mechanism and cause it to
|
||||
miss things which really ought to be in scope at a given point. */
|
||||
if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
|
||||
return;
|
||||
|
||||
/* If we are in terse mode, don't generate any DIEs to represent any
|
||||
variable declarations or definitions. */
|
||||
variable declarations or definitions. */
|
||||
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
||||
return;
|
||||
break;
|
||||
@ -12229,11 +12239,11 @@ dwarf2out_decl (decl)
|
||||
return;
|
||||
|
||||
/* Don't bother trying to generate any DIEs to represent any of the
|
||||
normal built-in types for the language we are compiling. */
|
||||
normal built-in types for the language we are compiling. */
|
||||
if (DECL_SOURCE_LINE (decl) == 0)
|
||||
{
|
||||
/* OK, we need to generate one for `bool' so GDB knows what type
|
||||
comparisons have. */
|
||||
comparisons have. */
|
||||
if ((get_AT_unsigned (comp_unit_die, DW_AT_language)
|
||||
== DW_LANG_C_plus_plus)
|
||||
&& TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE
|
||||
@ -12336,7 +12346,7 @@ lookup_filename (file_name)
|
||||
const char *last
|
||||
= VARRAY_CHAR_PTR (file_table, file_table_last_lookup_index);
|
||||
if (strcmp (file_name, last) == 0)
|
||||
return file_table_last_lookup_index;
|
||||
return file_table_last_lookup_index;
|
||||
}
|
||||
|
||||
/* Didn't match the previous lookup, search the table */
|
||||
@ -12352,25 +12362,43 @@ lookup_filename (file_name)
|
||||
file_table_last_lookup_index = n;
|
||||
save_file_name = (char *) ggc_strdup (file_name);
|
||||
VARRAY_PUSH_CHAR_PTR (file_table, save_file_name);
|
||||
|
||||
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);
|
||||
}
|
||||
VARRAY_PUSH_UINT (file_table_emitted, 0);
|
||||
|
||||
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
|
||||
init_file_table ()
|
||||
{
|
||||
/* Allocate the initial hunk of the 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. */
|
||||
VARRAY_PUSH_CHAR_PTR (file_table, NULL);
|
||||
VARRAY_PUSH_UINT (file_table_emitted, 0);
|
||||
file_table_last_lookup_index = 0;
|
||||
}
|
||||
|
||||
@ -12396,6 +12424,8 @@ dwarf2out_source_line (line, filename)
|
||||
{
|
||||
unsigned file_num = lookup_filename (filename);
|
||||
|
||||
file_num = maybe_emit_file (file_num);
|
||||
|
||||
/* Emit the .loc directive understood by GNU as. */
|
||||
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_uleb128 (lineno, "Included from line number %d",
|
||||
lineno);
|
||||
maybe_emit_file (lookup_filename (filename));
|
||||
dw2_asm_output_data_uleb128 (lookup_filename (filename),
|
||||
"Filename we just started");
|
||||
}
|
||||
@ -12646,6 +12677,215 @@ output_indirect_string (h, v)
|
||||
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,
|
||||
and generate the DWARF-2 debugging info. */
|
||||
|
||||
@ -12740,6 +12980,9 @@ dwarf2out_finish (input_filename)
|
||||
if (flag_eliminate_dwarf2_dups)
|
||||
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
|
||||
that have children. */
|
||||
add_sibling_attributes (comp_unit_die);
|
||||
|
@ -641,6 +641,10 @@ extern int flag_gcse_sm;
|
||||
|
||||
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
|
||||
and to print them when we are done. */
|
||||
extern int flag_detailed_statistics;
|
||||
|
@ -378,6 +378,10 @@ tree current_function_func_begin_label;
|
||||
|
||||
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. */
|
||||
|
||||
int profile_flag = 0;
|
||||
@ -999,6 +1003,8 @@ static const lang_independent_options f_options[] =
|
||||
{
|
||||
{"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
|
||||
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,
|
||||
N_("Do not store floats in registers") },
|
||||
{"defer-pop", &flag_defer_pop, 1,
|
||||
|
Loading…
Reference in New Issue
Block a user