summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c411
1 files changed, 317 insertions, 94 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 8bbf95477a7..1e5e335cdb3 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2473,7 +2473,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
const char * GTY ((tag ("0"))) die_symbol;
comdat_type_node_ref GTY ((tag ("1"))) die_type_node;
}
- GTY ((desc ("use_debug_types"))) die_id;
+ GTY ((desc ("%0.comdat_type_p"))) die_id;
VEC(dw_attr_node,gc) * die_attr;
dw_die_ref die_parent;
dw_die_ref die_child;
@@ -2482,10 +2482,12 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
dw_offset die_offset;
unsigned long die_abbrev;
int die_mark;
- /* Die is used and must not be pruned as unused. */
- int die_perennial_p;
unsigned int decl_id;
enum dwarf_tag die_tag;
+ /* Die is used and must not be pruned as unused. */
+ BOOL_BITFIELD die_perennial_p : 1;
+ BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
+ /* Lots of spare bits. */
}
die_node;
@@ -2984,7 +2986,7 @@ static void htab_cu_del (void *);
static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
static void add_sibling_attributes (dw_die_ref);
-static void build_abbrev_table (dw_die_ref);
+static void build_abbrev_table (dw_die_ref, htab_t);
static void output_location_lists (dw_die_ref);
static int constant_size (unsigned HOST_WIDE_INT);
static unsigned long size_of_die (dw_die_ref);
@@ -3716,6 +3718,16 @@ add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_
add_dwarf_attr (die, &attr);
}
+/* Change DIE reference REF to point to NEW_DIE instead. */
+
+static inline void
+change_AT_die_ref (dw_attr_ref ref, dw_die_ref new_die)
+{
+ gcc_assert (ref->dw_attr_val.val_class == dw_val_class_die_ref);
+ ref->dw_attr_val.v.val_die_ref.die = new_die;
+ ref->dw_attr_val.v.val_die_ref.external = 0;
+}
+
/* Add an AT_specification attribute to a DIE, and also make the back
pointer from the specification to the definition. */
@@ -4767,7 +4779,7 @@ print_die (dw_die_ref die, FILE *outfile)
fprintf (outfile, " offset: %ld", die->die_offset);
fprintf (outfile, " mark: %d\n", die->die_mark);
- if (use_debug_types && die->die_id.die_type_node)
+ if (die->comdat_type_p)
{
print_spaces (outfile);
fprintf (outfile, " signature: ");
@@ -4819,13 +4831,13 @@ print_die (dw_die_ref die, FILE *outfile)
case dw_val_class_die_ref:
if (AT_ref (a) != NULL)
{
- if (use_debug_types && AT_ref (a)->die_id.die_type_node)
+ if (AT_ref (a)->comdat_type_p)
{
fprintf (outfile, "die -> signature: ");
print_signature (outfile,
AT_ref (a)->die_id.die_type_node->signature);
}
- else if (! use_debug_types && AT_ref (a)->die_id.die_symbol)
+ else if (AT_ref (a)->die_id.die_symbol)
fprintf (outfile, "die -> label: %s",
AT_ref (a)->die_id.die_symbol);
else
@@ -5653,13 +5665,17 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
type node together. */
memcpy (type_node->signature, &checksum[16 - DWARF_TYPE_SIGNATURE_SIZE],
DWARF_TYPE_SIGNATURE_SIZE);
+ die->comdat_type_p = true;
die->die_id.die_type_node = type_node;
type_node->type_die = die;
/* If the DIE is a specification, link its declaration to the type node
as well. */
if (decl != NULL)
- decl->die_id.die_type_node = type_node;
+ {
+ decl->comdat_type_p = true;
+ decl->die_id.die_type_node = type_node;
+ }
}
/* Do the location expressions look same? */
@@ -5966,7 +5982,7 @@ assign_symbol_names (dw_die_ref die)
{
dw_die_ref c;
- if (is_symbol_die (die))
+ if (is_symbol_die (die) && !die->comdat_type_p)
{
if (comdat_symbol_id)
{
@@ -6271,7 +6287,12 @@ clone_as_declaration (dw_die_ref die)
/* If the DIE is a specification, just clone its declaration DIE. */
decl = get_AT_ref (die, DW_AT_specification);
if (decl != NULL)
- return clone_die (decl);
+ {
+ clone = clone_die (decl);
+ if (die->comdat_type_p)
+ add_AT_die_ref (clone, DW_AT_signature, die);
+ return clone;
+ }
clone = ggc_alloc_cleared_die_node ();
clone->die_tag = die->die_tag;
@@ -6300,7 +6321,7 @@ clone_as_declaration (dw_die_ref die)
}
}
- if (die->die_id.die_type_node)
+ if (die->comdat_type_p)
add_AT_die_ref (clone, DW_AT_signature, die);
add_AT_flag (clone, DW_AT_declaration, 1);
@@ -6335,6 +6356,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
/* Copy the type node pointer from the new DIE to the original
declaration DIE so we can forward references later. */
+ decl->comdat_type_p = true;
decl->die_id.die_type_node = die->die_id.die_type_node;
remove_AT (die, DW_AT_specification);
@@ -6469,6 +6491,7 @@ remove_child_or_replace_with_skeleton (dw_die_ref unit, dw_die_ref child,
remove_child_with_prev (child, prev);
else
{
+ skeleton->comdat_type_p = true;
skeleton->die_id.die_type_node = child->die_id.die_type_node;
/* If the original DIE was a specification, we need to put
@@ -6684,11 +6707,10 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
if (AT_class (a) == dw_val_class_die_ref)
{
dw_die_ref targ = AT_ref (a);
- comdat_type_node_ref type_node = targ->die_id.die_type_node;
void **slot;
struct decl_table_entry *entry;
- if (targ->die_mark != 0 || type_node != NULL)
+ if (targ->die_mark != 0 || targ->comdat_type_p)
continue;
slot = htab_find_slot_with_hash (decl_table, targ,
@@ -6809,13 +6831,159 @@ output_location_lists (dw_die_ref die)
FOR_EACH_CHILD (die, c, output_location_lists (c));
}
+/* We want to limit the number of external references, because they are
+ larger than local references: a relocation takes multiple words, and
+ even a sig8 reference is always eight bytes, whereas a local reference
+ can be as small as one byte (though DW_FORM_ref is usually 4 in GCC).
+ So if we encounter multiple external references to the same type DIE, we
+ make a local typedef stub for it and redirect all references there.
+
+ This is the element of the hash table for keeping track of these
+ references. */
+
+struct external_ref
+{
+ dw_die_ref type;
+ dw_die_ref stub;
+ unsigned n_refs;
+};
+
+/* Hash an external_ref. */
+
+static hashval_t
+hash_external_ref (const void *p)
+{
+ const struct external_ref *r = (const struct external_ref *)p;
+ return htab_hash_pointer (r->type);
+}
+
+/* Compare external_refs. */
+
+static int
+external_ref_eq (const void *p1, const void *p2)
+{
+ const struct external_ref *r1 = (const struct external_ref *)p1;
+ const struct external_ref *r2 = (const struct external_ref *)p2;
+ return r1->type == r2->type;
+}
+
+/* Return a pointer to the external_ref for references to DIE. */
+
+static struct external_ref *
+lookup_external_ref (htab_t map, dw_die_ref die)
+{
+ struct external_ref ref, *ref_p;
+ void ** slot;
+
+ ref.type = die;
+ slot = htab_find_slot (map, &ref, INSERT);
+ if (*slot != HTAB_EMPTY_ENTRY)
+ return (struct external_ref *) *slot;
+
+ ref_p = XCNEW (struct external_ref);
+ ref_p->type = die;
+ *slot = ref_p;
+ return ref_p;
+}
+
+/* Subroutine of optimize_external_refs, below.
+
+ If we see a type skeleton, record it as our stub. If we see external
+ references, remember how many we've seen. */
+
+static void
+optimize_external_refs_1 (dw_die_ref die, htab_t map)
+{
+ dw_die_ref c;
+ dw_attr_ref a;
+ unsigned ix;
+ struct external_ref *ref_p;
+
+ if (is_type_die (die)
+ && (c = get_AT_ref (die, DW_AT_signature)))
+ {
+ /* This is a local skeleton; use it for local references. */
+ ref_p = lookup_external_ref (map, c);
+ ref_p->stub = die;
+ }
+
+ /* Scan the DIE references, and remember any that refer to DIEs from
+ other CUs (i.e. those which are not marked). */
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+ if (AT_class (a) == dw_val_class_die_ref
+ && (c = AT_ref (a))->die_mark == 0
+ && is_type_die (c))
+ {
+ ref_p = lookup_external_ref (map, c);
+ ref_p->n_refs++;
+ }
+
+ FOR_EACH_CHILD (die, c, optimize_external_refs_1 (c, map));
+}
+
+/* htab_traverse callback function for optimize_external_refs, below. SLOT
+ points to an external_ref, DATA is the CU we're processing. If we don't
+ already have a local stub, and we have multiple refs, build a stub. */
+
+static int
+build_local_stub (void **slot, void *data)
+{
+ struct external_ref *ref_p = (struct external_ref *)*slot;
+ dw_die_ref cu = (dw_die_ref) data;
+ dw_die_ref type = ref_p->type;
+ dw_die_ref stub = NULL;
+
+ if (ref_p->stub == NULL && ref_p->n_refs > 1)
+ {
+ if (!dwarf_strict)
+ {
+ /* If we aren't being strict, use a typedef with no name
+ to just forward to the real type. In strict DWARF, a
+ typedef must have a name. */
+ stub = new_die (DW_TAG_typedef, cu, NULL_TREE);
+ add_AT_die_ref (stub, DW_AT_type, type);
+ }
+ else if (type->comdat_type_p)
+ {
+ /* If we refer to this type via sig8, we can use a simple
+ declaration; this is larger than the typedef, but strictly
+ correct. */
+ stub = new_die (type->die_tag, cu, NULL_TREE);
+ add_AT_string (stub, DW_AT_name, get_AT_string (type, DW_AT_name));
+ add_AT_flag (stub, DW_AT_declaration, 1);
+ add_AT_die_ref (stub, DW_AT_signature, type);
+ }
+
+ if (stub)
+ {
+ stub->die_mark++;
+ ref_p->stub = stub;
+ }
+ }
+ return 1;
+}
+
+/* DIE is a unit; look through all the DIE references to see if there are
+ any external references to types, and if so, create local stubs for
+ them which will be applied in build_abbrev_table. This is useful because
+ references to local DIEs are smaller. */
+
+static htab_t
+optimize_external_refs (dw_die_ref die)
+{
+ htab_t map = htab_create (10, hash_external_ref, external_ref_eq, free);
+ optimize_external_refs_1 (die, map);
+ htab_traverse (map, build_local_stub, die);
+ return map;
+}
+
/* The format of each DIE (and its attribute value pairs) is encoded in an
abbreviation table. This routine builds the abbreviation table and assigns
a unique abbreviation id for each abbreviation entry. The children of each
die are visited recursively. */
static void
-build_abbrev_table (dw_die_ref die)
+build_abbrev_table (dw_die_ref die, htab_t extern_map)
{
unsigned long abbrev_id;
unsigned int n_alloc;
@@ -6823,14 +6991,22 @@ build_abbrev_table (dw_die_ref die)
dw_attr_ref a;
unsigned ix;
- /* Scan the DIE references, and mark as external any that refer to
- DIEs from other CUs (i.e. those which are not marked). */
+ /* Scan the DIE references, and replace any that refer to
+ DIEs from other CUs (i.e. those which are not marked) with
+ the local stubs we built in optimize_external_refs. */
FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (AT_class (a) == dw_val_class_die_ref
- && AT_ref (a)->die_mark == 0)
+ && (c = AT_ref (a))->die_mark == 0)
{
- gcc_assert (use_debug_types || AT_ref (a)->die_id.die_symbol);
- set_AT_ref_external (a, 1);
+ struct external_ref *ref_p;
+ gcc_assert (AT_ref (a)->comdat_type_p || AT_ref (a)->die_id.die_symbol);
+
+ ref_p = lookup_external_ref (extern_map, c);
+ if (ref_p->stub && ref_p->stub != die)
+ change_AT_die_ref (a, ref_p->stub);
+ else
+ /* We aren't changing this reference, so mark it external. */
+ set_AT_ref_external (a, 1);
}
for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
@@ -6881,7 +7057,7 @@ build_abbrev_table (dw_die_ref die)
}
die->die_abbrev = abbrev_id;
- FOR_EACH_CHILD (die, c, build_abbrev_table (c));
+ FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
}
/* Return the power-of-two number of bytes necessary to represent VALUE. */
@@ -7398,6 +7574,8 @@ output_die_symbol (dw_die_ref die)
{
const char *sym = die->die_id.die_symbol;
+ gcc_assert (!die->comdat_type_p);
+
if (sym == 0)
return;
@@ -7522,7 +7700,7 @@ output_die (dw_die_ref die)
/* If someone in another CU might refer to us, set up a symbol for
them to point to. */
- if (! use_debug_types && die->die_id.die_symbol)
+ if (! die->comdat_type_p && die->die_id.die_symbol)
output_die_symbol (die);
dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
@@ -7668,7 +7846,7 @@ output_die (dw_die_ref die)
case dw_val_class_die_ref:
if (AT_ref_external (a))
{
- if (use_debug_types)
+ if (AT_ref (a)->comdat_type_p)
{
comdat_type_node_ref type_node =
AT_ref (a)->die_id.die_type_node;
@@ -7802,6 +7980,7 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
{
const char *secname, *oldsym;
char *tmp;
+ htab_t extern_map;
/* Unless we are outputting main CU, we may throw away empty ones. */
if (!output_if_empty && die->die_child == NULL)
@@ -7814,7 +7993,11 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
this CU so we know which get local refs. */
mark_dies (die);
- build_abbrev_table (die);
+ extern_map = optimize_external_refs (die);
+
+ build_abbrev_table (die, extern_map);
+
+ htab_delete (extern_map);
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
@@ -7861,11 +8044,16 @@ output_comdat_type_unit (comdat_type_node *node)
#if defined (OBJECT_FORMAT_ELF)
tree comdat_key;
#endif
+ htab_t extern_map;
/* First mark all the DIEs in this CU so we know which get local refs. */
mark_dies (node->root_die);
- build_abbrev_table (node->root_die);
+ extern_map = optimize_external_refs (node->root_die);
+
+ build_abbrev_table (node->root_die, extern_map);
+
+ htab_delete (extern_map);
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
@@ -8085,6 +8273,8 @@ output_aranges (unsigned long aranges_length)
FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
{
+ if (DECL_IGNORED_P (fde->decl))
+ continue;
if (!fde->in_std_section)
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
@@ -9019,6 +9209,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
tree item_type = NULL;
tree qualified_type;
tree name, low, high;
+ dw_die_ref mod_scope;
if (code == ERROR_MARK)
return NULL;
@@ -9079,6 +9270,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
/* Else cv-qualified version of named type; fall through. */
}
+ mod_scope = scope_die_for (type, context_die);
+
if (is_const_type
/* If both is_const_type and is_volatile_type, prefer the path
which leads to a qualified type. */
@@ -9086,17 +9279,17 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
|| get_qualified_type (type, TYPE_QUAL_CONST) == NULL_TREE
|| get_qualified_type (type, TYPE_QUAL_VOLATILE) != NULL_TREE))
{
- mod_type_die = new_die (DW_TAG_const_type, comp_unit_die (), type);
+ mod_type_die = new_die (DW_TAG_const_type, mod_scope, type);
sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
}
else if (is_volatile_type)
{
- mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die (), type);
+ mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type);
sub_die = modified_type_die (type, is_const_type, 0, context_die);
}
else if (code == POINTER_TYPE)
{
- mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die (), type);
+ mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
simple_type_size_in_bits (type) / BITS_PER_UNIT);
item_type = TREE_TYPE (type);
@@ -9107,10 +9300,10 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
else if (code == REFERENCE_TYPE)
{
if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
- mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die (),
+ mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
type);
else
- mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die (), type);
+ mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
simple_type_size_in_bits (type) / BITS_PER_UNIT);
item_type = TREE_TYPE (type);
@@ -10778,17 +10971,6 @@ parameter_ref_descriptor (rtx rtl)
return ret;
}
-/* Helper function to get mode of MEM's address. */
-
-enum machine_mode
-get_address_mode (rtx mem)
-{
- enum machine_mode mode = GET_MODE (XEXP (mem, 0));
- if (mode != VOIDmode)
- return mode;
- return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
-}
-
/* The following routine converts the RTL for a variable or parameter
(resident in memory) into an equivalent Dwarf representation of a
mechanism for getting the address of that same variable onto the top of a
@@ -14093,11 +14275,12 @@ rtl_for_decl_location (tree decl)
&& (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
< UNITS_PER_WORD))
{
+ enum machine_mode addr_mode = get_address_mode (rtl);
int offset = (UNITS_PER_WORD
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
- plus_constant (XEXP (rtl, 0), offset));
+ plus_constant (addr_mode, XEXP (rtl, 0), offset));
}
}
else if (TREE_CODE (decl) == VAR_DECL
@@ -14106,6 +14289,7 @@ rtl_for_decl_location (tree decl)
&& GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl))
&& BYTES_BIG_ENDIAN)
{
+ enum machine_mode addr_mode = get_address_mode (rtl);
int rsize = GET_MODE_SIZE (GET_MODE (rtl));
int dsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)));
@@ -14117,7 +14301,8 @@ rtl_for_decl_location (tree decl)
else gdb will not be able to display it. */
if (rsize > dsize)
rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
- plus_constant (XEXP (rtl, 0), rsize-dsize));
+ plus_constant (addr_mode, XEXP (rtl, 0),
+ rsize - dsize));
}
/* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
@@ -14971,6 +15156,7 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
static void
add_byte_size_attribute (dw_die_ref die, tree tree_node)
{
+ dw_die_ref decl_die;
unsigned size;
switch (TREE_CODE (tree_node))
@@ -14982,6 +15168,12 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
+ if (TREE_CODE (TYPE_SIZE_UNIT (tree_node)) == VAR_DECL
+ && (decl_die = lookup_decl_die (TYPE_SIZE_UNIT (tree_node))))
+ {
+ add_AT_die_ref (die, DW_AT_byte_size, decl_die);
+ return;
+ }
size = int_size_in_bytes (tree_node);
break;
case FIELD_DECL:
@@ -15299,10 +15491,36 @@ pop_decl_scope (void)
VEC_pop (tree, decl_scope_table);
}
+/* walk_tree helper function for uses_local_type, below. */
+
+static tree
+uses_local_type_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+ if (!TYPE_P (*tp))
+ *walk_subtrees = 0;
+ else
+ {
+ tree name = TYPE_NAME (*tp);
+ if (name && DECL_P (name) && decl_function_context (name))
+ return *tp;
+ }
+ return NULL_TREE;
+}
+
+/* If TYPE involves a function-local type (including a local typedef to a
+ non-local type), returns that type; otherwise returns NULL_TREE. */
+
+static tree
+uses_local_type (tree type)
+{
+ tree used = walk_tree_without_duplicates (&type, uses_local_type_r, NULL);
+ return used;
+}
+
/* Return the DIE for the scope that immediately contains this type.
- Non-named types get global scope. Named types nested in other
- types get their containing scope if it's open, or global scope
- otherwise. All other types (i.e. function-local named types) get
+ Non-named types that do not involve a function-local type get global
+ scope. Named types nested in namespaces or other types get their
+ containing scope. All other types (i.e. function-local named types) get
the current active scope. */
static dw_die_ref
@@ -15310,18 +15528,24 @@ scope_die_for (tree t, dw_die_ref context_die)
{
dw_die_ref scope_die = NULL;
tree containing_scope;
- int i;
/* Non-types always go in the current scope. */
gcc_assert (TYPE_P (t));
- containing_scope = TYPE_CONTEXT (t);
+ /* Use the scope of the typedef, rather than the scope of the type
+ it refers to. */
+ if (TYPE_NAME (t) && DECL_P (TYPE_NAME (t)))
+ containing_scope = DECL_CONTEXT (TYPE_NAME (t));
+ else
+ containing_scope = TYPE_CONTEXT (t);
- /* Use the containing namespace if it was passed in (for a declaration). */
+ /* Use the containing namespace if there is one. */
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
{
if (context_die == lookup_decl_die (containing_scope))
/* OK */;
+ else if (debug_info_level > DINFO_LEVEL_TERSE)
+ context_die = get_context_die (containing_scope);
else
containing_scope = NULL_TREE;
}
@@ -15333,30 +15557,25 @@ scope_die_for (tree t, dw_die_ref context_die)
containing_scope = NULL_TREE;
if (SCOPE_FILE_SCOPE_P (containing_scope))
- scope_die = comp_unit_die ();
+ {
+ /* If T uses a local type keep it local as well, to avoid references
+ to function-local DIEs from outside the function. */
+ if (current_function_decl && uses_local_type (t))
+ scope_die = context_die;
+ else
+ scope_die = comp_unit_die ();
+ }
else if (TYPE_P (containing_scope))
{
- /* For types, we can just look up the appropriate DIE. But
- first we check to see if we're in the middle of emitting it
- so we know where the new DIE should go. */
- for (i = VEC_length (tree, decl_scope_table) - 1; i >= 0; --i)
- if (VEC_index (tree, decl_scope_table, i) == containing_scope)
- break;
-
- if (i < 0)
+ /* For types, we can just look up the appropriate DIE. */
+ if (debug_info_level > DINFO_LEVEL_TERSE)
+ scope_die = get_context_die (containing_scope);
+ else
{
- gcc_assert (debug_info_level <= DINFO_LEVEL_TERSE
- || TREE_ASM_WRITTEN (containing_scope));
- /*We are not in the middle of emitting the type
- CONTAINING_SCOPE. Let's see if it's emitted already. */
- scope_die = lookup_type_die (containing_scope);
-
- /* If none of the current dies are suitable, we get file scope. */
+ scope_die = lookup_type_die_strip_naming_typedef (containing_scope);
if (scope_die == NULL)
scope_die = comp_unit_die ();
}
- else
- scope_die = lookup_type_die_strip_naming_typedef (containing_scope);
}
else
scope_die = context_die;
@@ -17047,10 +17266,13 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
&& loc->expr->dw_loc_next == NULL
&& GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
== SYMBOL_REF)
- loc->expr->dw_loc_oprnd1.v.val_addr
- = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
- else
- loc_list_plus_const (loc, off);
+ {
+ rtx x = loc->expr->dw_loc_oprnd1.v.val_addr;
+ loc->expr->dw_loc_oprnd1.v.val_addr
+ = plus_constant (GET_MODE (x), x , off);
+ }
+ else
+ loc_list_plus_const (loc, off);
}
add_AT_location_description (var_die, DW_AT_location, loc);
remove_AT (var_die, DW_AT_declaration);
@@ -17110,8 +17332,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
&& loc->expr->dw_loc_opc == DW_OP_addr
&& loc->expr->dw_loc_next == NULL
&& GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
- loc->expr->dw_loc_oprnd1.v.val_addr
- = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
+ {
+ rtx x = loc->expr->dw_loc_oprnd1.v.val_addr;
+ loc->expr->dw_loc_oprnd1.v.val_addr
+ = plus_constant (GET_MODE (x), x, off);
+ }
else
loc_list_plus_const (loc, off);
}
@@ -18152,12 +18377,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* Prevent broken recursion; we can't hand off to the same type. */
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
- /* Use the DIE of the containing namespace as the parent DIE of
- the type description DIE we want to generate. */
- if (DECL_FILE_SCOPE_P (TYPE_NAME (type))
- || (DECL_CONTEXT (TYPE_NAME (type))
- && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL))
- context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
+ /* Give typedefs the right scope. */
+ context_die = scope_die_for (type, context_die);
TREE_ASM_WRITTEN (type) = 1;
@@ -19122,7 +19343,9 @@ dwarf2out_decl (tree decl)
return;
/* For local statics lookup proper context die. */
- if (TREE_STATIC (decl) && decl_function_context (decl))
+ if (TREE_STATIC (decl)
+ && DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
context_die = lookup_decl_die (DECL_CONTEXT (decl));
/* If we are in terse mode, don't generate any DIEs to represent any
@@ -19835,7 +20058,7 @@ dwarf2out_source_line (unsigned int line, const char *filename,
static void
dwarf2out_start_source_file (unsigned int lineno, const char *filename)
{
- if (flag_eliminate_dwarf2_dups && ! use_debug_types)
+ if (flag_eliminate_dwarf2_dups)
{
/* Record the beginning of the file for break_out_includes. */
dw_die_ref bincl_die;
@@ -19859,7 +20082,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
static void
dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
{
- if (flag_eliminate_dwarf2_dups && ! use_debug_types)
+ if (flag_eliminate_dwarf2_dups)
/* Record the end of the file for break_out_includes. */
new_die (DW_TAG_GNU_EINCL, comp_unit_die (), NULL);
@@ -20451,9 +20674,8 @@ prune_unused_types_walk_attribs (dw_die_ref die)
/* A reference to another DIE.
Make sure that it will get emitted.
If it was broken out into a comdat group, don't follow it. */
- if (! use_debug_types
- || a->dw_attr == DW_AT_specification
- || a->dw_attr_val.v.val_die_ref.die->die_id.die_type_node == NULL)
+ if (! AT_ref (a)->comdat_type_p
+ || a->dw_attr == DW_AT_specification)
prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
}
/* Set the string's refcount to 0 so that prune_unused_types_mark
@@ -21778,16 +22000,15 @@ dwarf2out_finish (const char *filename)
inlined and optimized out. In that case we are lost and
assign the empty child. This should not be big issue as
the function is likely unreachable too. */
- tree context = NULL_TREE;
-
gcc_assert (node->created_for);
if (DECL_P (node->created_for))
- context = DECL_CONTEXT (node->created_for);
+ origin = get_context_die (DECL_CONTEXT (node->created_for));
else if (TYPE_P (node->created_for))
- context = TYPE_CONTEXT (node->created_for);
+ origin = scope_die_for (node->created_for, comp_unit_die ());
+ else
+ origin = comp_unit_die ();
- origin = get_context_die (context);
add_child_die (origin, die);
}
}
@@ -21823,11 +22044,6 @@ dwarf2out_finish (const char *filename)
if (flag_eliminate_unused_debug_types)
prune_unused_types ();
- /* Generate separate CUs for each of the include files we've seen.
- They will go into limbo_die_list. */
- if (flag_eliminate_dwarf2_dups && ! use_debug_types)
- break_out_includes (comp_unit_die ());
-
/* Generate separate COMDAT sections for type DIEs. */
if (use_debug_types)
{
@@ -21851,6 +22067,11 @@ dwarf2out_finish (const char *filename)
prune_unused_types ();
}
+ /* Generate separate CUs for each of the include files we've seen.
+ They will go into limbo_die_list. */
+ if (flag_eliminate_dwarf2_dups)
+ break_out_includes (comp_unit_die ());
+
/* Traverse the DIE's and add add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die ());
@@ -21895,6 +22116,8 @@ dwarf2out_finish (const char *filename)
FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
{
+ if (DECL_IGNORED_P (fde->decl))
+ continue;
if (!fde->in_std_section)
add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin,
fde->dw_fde_end, &range_list_added);