aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.6/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorJing Yu <jingyu@google.com>2012-02-15 15:40:16 -0800
committerJing Yu <jingyu@google.com>2012-02-15 15:40:16 -0800
commit3f73d6ef90458b45bbbb33ef4c2b174d4662a22d (patch)
tree1b5f0d96c51b51168b3713058a1b62e92f1136eb /gcc-4.6/gcc/dwarf2out.c
parentd7030123e04baab5dbff9c9ee04c0de99bd9a774 (diff)
downloadtoolchain_gcc-3f73d6ef90458b45bbbb33ef4c2b174d4662a22d.tar.gz
toolchain_gcc-3f73d6ef90458b45bbbb33ef4c2b174d4662a22d.tar.bz2
toolchain_gcc-3f73d6ef90458b45bbbb33ef4c2b174d4662a22d.zip
Sync down FSF r184235@google/gcc-4_6_2-mobile branch
1) Get mostly new patches from FSF gcc-4.6 branch 2) Fix PR52129 3) Insert GNU-stack note for all ARM targets Change-Id: I2b9926981210e517e4021242908074319a91d6bd
Diffstat (limited to 'gcc-4.6/gcc/dwarf2out.c')
-rw-r--r--gcc-4.6/gcc/dwarf2out.c406
1 files changed, 321 insertions, 85 deletions
diff --git a/gcc-4.6/gcc/dwarf2out.c b/gcc-4.6/gcc/dwarf2out.c
index b78627bb8..675a68270 100644
--- a/gcc-4.6/gcc/dwarf2out.c
+++ b/gcc-4.6/gcc/dwarf2out.c
@@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "tree-pass.h"
#include "tree-flow.h"
+#include "l-ipo.h"
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
static rtx last_var_location_insn;
@@ -4435,6 +4436,11 @@ typedef struct GTY(()) dw_loc_list_struct {
const char *section; /* Section this loclist is relative to */
dw_loc_descr_ref expr;
hashval_t hash;
+ /* True if all addresses in this and subsequent lists are known to be
+ resolved. */
+ bool resolved_addr;
+ /* True if this list has been replaced by dw_loc_next. */
+ bool replaced;
bool emitted;
} dw_loc_list_node;
@@ -6095,6 +6101,19 @@ typedef struct var_loc_list_def var_loc_list;
/* Table of decl location linked lists. */
static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
+/* A cached location list. */
+struct GTY (()) cached_dw_loc_list_def {
+ /* The DECL_UID of the decl that this entry describes. */
+ unsigned int decl_id;
+
+ /* The cached location list. */
+ dw_loc_list_ref loc_list;
+};
+typedef struct cached_dw_loc_list_def cached_dw_loc_list;
+
+/* Table of cached location lists. */
+static GTY ((param_is (cached_dw_loc_list))) htab_t cached_dw_loc_list_table;
+
/* A pointer to the base of a list of references to DIE's that
are uniquely identified by their tag, presence/absence of
children DIE's, and list of attribute/value pairs. */
@@ -6394,6 +6413,7 @@ static void output_comp_unit (dw_die_ref, int);
static void output_comdat_type_unit (comdat_type_node *);
static const char *dwarf2_name (tree, int);
static void add_pubname (tree, dw_die_ref);
+static void add_enumerator_pubname (const char *, const char *, dw_die_ref);
static void add_pubname_string (const char *, dw_die_ref);
static void add_pubtype (tree, dw_die_ref);
static void output_pubnames (VEC (pubname_entry,gc) *);
@@ -6443,7 +6463,7 @@ static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
static void insert_double (double_int, unsigned char *);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
-static bool add_location_or_const_value_attribute (dw_die_ref, tree,
+static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
enum dwarf_attribute);
static bool tree_add_const_value_attribute (dw_die_ref, tree);
static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
@@ -6598,6 +6618,12 @@ static void gen_scheduled_generic_parms_dies (void);
#ifndef COLD_TEXT_SECTION_LABEL
#define COLD_TEXT_SECTION_LABEL "Ltext_cold"
#endif
+#ifndef DEBUG_PUBNAMES_SECTION_LABEL
+#define DEBUG_PUBNAMES_SECTION_LABEL "Ldebug_pubnames"
+#endif
+#ifndef DEBUG_PUBTYPES_SECTION_LABEL
+#define DEBUG_PUBTYPES_SECTION_LABEL "Ldebug_pubtypes"
+#endif
#ifndef DEBUG_LINE_SECTION_LABEL
#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
#endif
@@ -6631,6 +6657,8 @@ static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_pubnames_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_pubtypes_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
@@ -8177,6 +8205,24 @@ lookup_decl_loc (const_tree decl)
htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
}
+/* Returns a hash value for X (which really is a cached_dw_loc_list_list). */
+
+static hashval_t
+cached_dw_loc_list_table_hash (const void *x)
+{
+ return (hashval_t) ((const cached_dw_loc_list *) x)->decl_id;
+}
+
+/* Return nonzero if decl_id of cached_dw_loc_list X is the same as
+ UID of decl *Y. */
+
+static int
+cached_dw_loc_list_table_eq (const void *x, const void *y)
+{
+ return (((const cached_dw_loc_list *) x)->decl_id
+ == DECL_UID ((const_tree) y));
+}
+
/* Equate a DIE to a particular declaration. */
static void
@@ -9726,6 +9772,22 @@ is_cu_die (dw_die_ref c)
return c && c->die_tag == DW_TAG_compile_unit;
}
+/* Returns true iff C is a namespace DIE. */
+
+static inline bool
+is_namespace_die (dw_die_ref c)
+{
+ return c && c->die_tag == DW_TAG_namespace;
+}
+
+/* Returns true iff C is a class DIE. */
+
+static inline bool
+is_class_die (dw_die_ref c)
+{
+ return c && c->die_tag == DW_TAG_class_type;
+}
+
static char *
gen_internal_sym (const char *prefix)
{
@@ -10256,6 +10318,15 @@ break_out_comdat_types (dw_die_ref die)
type_node->root_die = unit;
type_node->next = comdat_type_list;
comdat_type_list = type_node;
+ if (targetm.want_debug_pub_sections)
+ {
+ /* FIXME: Should use add_AT_pubnamesptr. This works because most
+ targets don't care what the base section is. */
+ add_AT_lineptr (unit, DW_AT_GNU_pubnames,
+ debug_pubnames_section_label);
+ add_AT_lineptr (unit, DW_AT_GNU_pubtypes,
+ debug_pubtypes_section_label);
+ }
/* Generate the type signature. */
generate_type_signature (c, type_node);
@@ -10651,7 +10722,15 @@ size_of_die (dw_die_ref die)
size += size_of_sleb128 (AT_int (a));
break;
case dw_val_class_unsigned_const:
- size += constant_size (AT_unsigned (a));
+ {
+ int csize = constant_size (AT_unsigned (a));
+ if (dwarf_version == 3
+ && a->dw_attr == DW_AT_data_member_location
+ && csize >= 4)
+ size += size_of_uleb128 (AT_unsigned (a));
+ else
+ size += csize;
+ }
break;
case dw_val_class_const_double:
size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
@@ -10921,8 +11000,16 @@ value_format (dw_attr_ref a)
case 2:
return DW_FORM_data2;
case 4:
+ /* In DWARF3 DW_AT_data_member_location with
+ DW_FORM_data4 or DW_FORM_data8 is a loclistptr, not
+ constant, so we need to use DW_FORM_udata if we need
+ a large constant. */
+ if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+ return DW_FORM_udata;
return DW_FORM_data4;
case 8:
+ if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+ return DW_FORM_udata;
return DW_FORM_data8;
default:
gcc_unreachable ();
@@ -11229,8 +11316,15 @@ output_die (dw_die_ref die)
break;
case dw_val_class_unsigned_const:
- dw2_asm_output_data (constant_size (AT_unsigned (a)),
- AT_unsigned (a), "%s", name);
+ {
+ int csize = constant_size (AT_unsigned (a));
+ if (dwarf_version == 3
+ && a->dw_attr == DW_AT_data_member_location
+ && csize >= 4)
+ dw2_asm_output_data_uleb128 (AT_unsigned (a), "%s", name);
+ else
+ dw2_asm_output_data (csize, AT_unsigned (a), "%s", name);
+ }
break;
case dw_val_class_const_double:
@@ -11574,16 +11668,35 @@ add_pubname_string (const char *str, dw_die_ref die)
static void
add_pubname (tree decl, dw_die_ref die)
{
- if (!GENERATE_MINIMUM_LINE_TABLE
- && targetm.want_debug_pub_sections
- && TREE_PUBLIC (decl))
+ if (!GENERATE_MINIMUM_LINE_TABLE && targetm.want_debug_pub_sections)
{
- const char *name = dwarf2_name (decl, 1);
- if (name)
- add_pubname_string (name, die);
+ if ((TREE_PUBLIC (decl) && !is_class_die (die->die_parent))
+ || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
+ {
+ const char *name = dwarf2_name (decl, 1);
+ if (name)
+ add_pubname_string (name, die);
+ }
}
}
+/* Add an enumerator to the pubnames section. */
+
+static void
+add_enumerator_pubname (const char *scope_name, const char *sep, dw_die_ref die)
+{
+ const char *name;
+ pubname_entry e;
+
+ if (scope_name)
+ name = concat (scope_name, sep, get_AT_string (die, DW_AT_name), NULL);
+ else
+ name = xstrdup (get_AT_string (die, DW_AT_name));
+ e.name = name;
+ e.die = die;
+ VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+}
+
/* Add a new entry to .debug_pubtypes if appropriate. */
static void
@@ -11596,34 +11709,47 @@ add_pubtype (tree decl, dw_die_ref die)
e.name = NULL;
if ((TREE_PUBLIC (decl)
- || is_cu_die (die->die_parent))
+ || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
&& (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
{
- e.die = die;
+ tree scope = NULL;
+ const char *scope_name = NULL;
+ const char *sep = is_cxx () ? "::" : ".";
+ const char *name = NULL;
+
if (TYPE_P (decl))
- {
- if (TYPE_NAME (decl))
- {
- if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
- e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
- else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (decl)))
- e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
- else
- e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
- }
- }
+ name = type_tag (decl);
else
- {
- e.name = dwarf2_name (decl, 1);
- if (e.name)
- e.name = xstrdup (e.name);
- }
+ name = lang_hooks.dwarf_name (decl, 1);
/* If we don't have a name for the type, there's no point in adding
it to the table. */
- if (e.name && e.name[0] != '\0')
- VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+ if (name == NULL || name[0] == '\0')
+ return;
+
+ e.die = die;
+ e.name = xstrdup (name);
+
+ scope = TYPE_P (decl) ? TYPE_CONTEXT (decl) : NULL;
+ if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+ {
+ scope_name = lang_hooks.dwarf_name (scope, 1);
+ if (scope_name != NULL)
+ e.name = concat (scope_name, sep, e.name, NULL);
+ }
+ VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+
+ /* Although it might be more consistent to add the pubinfo for the
+ enumerators as their dies are created, they should only be added if the
+ enum type meets the criteria above. So rather than re-check the parent
+ enum type whenever an enumerator die is created, just output them all
+ here. */
+ if (die->die_tag == DW_TAG_enumeration_type)
+ {
+ dw_die_ref c;
+
+ FOR_EACH_CHILD (die, c, add_enumerator_pubname (scope_name, sep, c));
+ }
}
}
@@ -11637,6 +11763,18 @@ output_pubnames (VEC (pubname_entry, gc) * names)
unsigned long pubnames_length = size_of_pubnames (names);
pubname_ref pub;
+ if (!targetm.want_debug_pub_sections || !info_section_emitted)
+ return;
+ if (names == pubname_table)
+ {
+ switch_to_section (debug_pubnames_section);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_pubnames_section_label);
+ }
+ else
+ {
+ switch_to_section (debug_pubtypes_section);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_pubtypes_section_label);
+ }
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
@@ -12774,6 +12912,7 @@ base_type_die (tree type)
add_AT_unsigned (base_type_result, DW_AT_byte_size,
int_size_in_bytes (type));
add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
+ add_pubtype (type, base_type_result);
return base_type_result;
}
@@ -14591,7 +14730,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
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. */
- loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
+ loc_result = loc_descriptor (SUBREG_REG (rtl),
+ GET_MODE (SUBREG_REG (rtl)), initialized);
break;
case REG:
@@ -16977,15 +17117,22 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
these things can crop up in other ways also.) Note that one type of
constant value which can be passed into an inlined function is a constant
pointer. This can happen for example if an actual argument in an inlined
- function call evaluates to a compile-time constant address. */
+ function call evaluates to a compile-time constant address.
+
+ CACHE_P is true if it is worth caching the location list for DECL,
+ so that future calls can reuse it rather than regenerate it from scratch.
+ This is true for BLOCK_NONLOCALIZED_VARS in inlined subroutines,
+ since we will need to refer to them each time the function is inlined. */
static bool
-add_location_or_const_value_attribute (dw_die_ref die, tree decl,
+add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
enum dwarf_attribute attr)
{
rtx rtl;
dw_loc_list_ref list;
var_loc_list *loc_list;
+ cached_dw_loc_list *cache;
+ void **slot;
if (TREE_CODE (decl) == ERROR_MARK)
return false;
@@ -17022,7 +17169,33 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
&& add_const_value_attribute (die, rtl))
return true;
}
- list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+ /* If this decl is from BLOCK_NONLOCALIZED_VARS, we might need its
+ list several times. See if we've already cached the contents. */
+ list = NULL;
+ if (loc_list == NULL || cached_dw_loc_list_table == NULL)
+ cache_p = false;
+ if (cache_p)
+ {
+ cache = (cached_dw_loc_list *)
+ htab_find_with_hash (cached_dw_loc_list_table, decl, DECL_UID (decl));
+ if (cache)
+ list = cache->loc_list;
+ }
+ if (list == NULL)
+ {
+ list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+ /* It is usually worth caching this result if the decl is from
+ BLOCK_NONLOCALIZED_VARS and if the list has at least two elements. */
+ if (cache_p && list && list->dw_loc_next)
+ {
+ slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
+ DECL_UID (decl), INSERT);
+ cache = ggc_alloc_cleared_cached_dw_loc_list ();
+ cache->decl_id = DECL_UID (decl);
+ cache->loc_list = list;
+ *slot = cache;
+ }
+ }
if (list)
{
add_AT_location_description (die, attr, list);
@@ -18721,7 +18894,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
equate_decl_number_to_die (node, parm_die);
if (! DECL_ABSTRACT (node_or_origin))
add_location_or_const_value_attribute (parm_die, node_or_origin,
- DW_AT_location);
+ node == NULL, DW_AT_location);
break;
@@ -18906,6 +19079,7 @@ dwarf2out_abstract_function (tree decl)
tree context;
int was_abstract;
htab_t old_decl_loc_table;
+ htab_t old_cached_dw_loc_list_table;
/* Make sure we have the actual abstract inline, not a clone. */
decl = DECL_ORIGIN (decl);
@@ -18920,6 +19094,8 @@ dwarf2out_abstract_function (tree decl)
get locations in abstract instantces. */
old_decl_loc_table = decl_loc_table;
decl_loc_table = NULL;
+ old_cached_dw_loc_list_table = cached_dw_loc_list_table;
+ cached_dw_loc_list_table = NULL;
/* Be sure we've emitted the in-class declaration DIE (if any) first, so
we don't get confused by DECL_ABSTRACT. */
@@ -18944,6 +19120,7 @@ dwarf2out_abstract_function (tree decl)
current_function_decl = save_fn;
decl_loc_table = old_decl_loc_table;
+ cached_dw_loc_list_table = old_cached_dw_loc_list_table;
pop_cfun ();
}
@@ -19728,9 +19905,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
&& !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
defer_location (decl_or_origin, var_die);
else
- add_location_or_const_value_attribute (var_die,
- decl_or_origin,
- DW_AT_location);
+ add_location_or_const_value_attribute (var_die, decl_or_origin,
+ decl == NULL, DW_AT_location);
add_pubname (decl_or_origin, var_die);
}
else
@@ -21035,6 +21211,8 @@ gen_namespace_die (tree decl, dw_die_ref context_die)
add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
equate_decl_number_to_die (decl, namespace_die);
}
+ /* Bypass dwarf2_name's check for DECL_NAMELESS. */
+ add_pubname_string (lang_hooks.dwarf_name (decl, 1), namespace_die);
}
/* Generate Dwarf debug information for a decl described by DECL.
@@ -21399,7 +21577,48 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
void
dwarf2out_decl (tree decl)
{
- dw_die_ref context_die = comp_unit_die ();
+ dw_die_ref context_die;
+
+ /* In LIPO mode, we may output some functions whose type is defined
+ in another function that will not be output. This can result in
+ undefined location list symbols in the debug type info.
+ Here we disable the output of the type info for this case.
+ It is safe since this function and its debug info should never
+ be referenced. */
+ if (L_IPO_COMP_MODE)
+ {
+ tree decl_context, orig_decl;
+
+ decl_context = DECL_CONTEXT (decl);
+ while (decl_context &&
+ TREE_CODE (decl_context) != TRANSLATION_UNIT_DECL)
+ {
+ struct cgraph_node *node;
+
+ /* Refer to cgraph_mark_functions_to_output() in cgraphunit.c,
+ if cgraph_is_aux_decl_external() is true,
+ this function will not be output in LIPO mode. */
+ if (TREE_CODE (decl_context) == FUNCTION_DECL &&
+ TREE_PUBLIC (decl_context) &&
+ (node = cgraph_get_node (decl_context)) &&
+ cgraph_is_aux_decl_external (node))
+ return;
+
+ if (TYPE_P (decl_context))
+ {
+ decl_context = TYPE_CONTEXT (decl_context);
+ continue;
+ }
+
+ orig_decl = DECL_ORIGIN (decl_context);
+ while (orig_decl != DECL_ORIGIN (orig_decl))
+ orig_decl = DECL_ORIGIN (orig_decl);
+
+ decl_context = DECL_CONTEXT (orig_decl);
+ }
+ }
+
+ context_die = comp_unit_die ();
switch (TREE_CODE (decl))
{
@@ -21521,6 +21740,7 @@ dwarf2out_function_decl (tree decl)
dwarf2out_decl (decl);
htab_empty (decl_loc_table);
+ htab_empty (cached_dw_loc_list_table);
}
/* Output a marker (i.e. a label) for the beginning of the generated code for
@@ -22046,7 +22266,8 @@ dwarf2out_source_line (unsigned int line, const char *filename,
fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
last_is_stmt = is_stmt;
}
- if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
+ if (SUPPORTS_DISCRIMINATOR && discriminator != 0
+ && (dwarf_version >= 4 || !dwarf_strict))
fprintf (asm_out_file, " discriminator %d", discriminator);
fputc ('\n', asm_out_file);
@@ -22252,6 +22473,11 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
decl_loc_table_eq, NULL);
+ /* Allocate the cached_dw_loc_list_table. */
+ cached_dw_loc_list_table
+ = htab_create_ggc (10, cached_dw_loc_list_table_hash,
+ cached_dw_loc_list_table_eq, NULL);
+
/* Allocate the initial hunk of the decl_scope_table. */
decl_scope_table = VEC_alloc (tree, gc, 256);
@@ -22319,6 +22545,10 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
DEBUG_INFO_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (debug_pubnames_section_label,
+ DEBUG_PUBNAMES_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (debug_pubtypes_section_label,
+ DEBUG_PUBTYPES_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
DEBUG_LINE_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
@@ -22892,30 +23122,53 @@ resolve_addr (dw_die_ref die)
{
dw_die_ref c;
dw_attr_ref a;
- dw_loc_list_ref *curr;
+ dw_loc_list_ref *curr, *start, loc;
unsigned ix;
FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
switch (AT_class (a))
{
case dw_val_class_loc_list:
- curr = AT_loc_list_ptr (a);
- while (*curr)
+ start = curr = AT_loc_list_ptr (a);
+ loc = *curr;
+ gcc_assert (loc);
+ /* The same list can be referenced more than once. See if we have
+ already recorded the result from a previous pass. */
+ if (loc->replaced)
+ *curr = loc->dw_loc_next;
+ else if (!loc->resolved_addr)
{
- if (!resolve_addr_in_expr ((*curr)->expr))
+ /* As things stand, we do not expect or allow one die to
+ reference a suffix of another die's location list chain.
+ References must be identical or completely separate.
+ There is therefore no need to cache the result of this
+ pass on any list other than the first; doing so
+ would lead to unnecessary writes. */
+ while (*curr)
{
- dw_loc_list_ref next = (*curr)->dw_loc_next;
- if (next && (*curr)->ll_symbol)
+ gcc_assert (!(*curr)->replaced && !(*curr)->resolved_addr);
+ if (!resolve_addr_in_expr ((*curr)->expr))
{
- gcc_assert (!next->ll_symbol);
- next->ll_symbol = (*curr)->ll_symbol;
+ dw_loc_list_ref next = (*curr)->dw_loc_next;
+ if (next && (*curr)->ll_symbol)
+ {
+ gcc_assert (!next->ll_symbol);
+ next->ll_symbol = (*curr)->ll_symbol;
+ }
+ *curr = next;
}
- *curr = next;
+ else
+ curr = &(*curr)->dw_loc_next;
}
+ if (loc == *start)
+ loc->resolved_addr = 1;
else
- curr = &(*curr)->dw_loc_next;
+ {
+ loc->replaced = 1;
+ loc->dw_loc_next = *start;
+ }
}
- if (!AT_loc_list (a))
+ if (!*start)
{
remove_AT (die, a->dw_attr);
ix--;
@@ -23312,6 +23565,7 @@ optimize_location_lists (dw_die_ref die)
htab_delete (htab);
}
+
/* Output stuff that dwarf requires at the end of every file,
and generate the DWARF-2 debugging info. */
@@ -23344,6 +23598,7 @@ dwarf2out_finish (const char *filename)
add_location_or_const_value_attribute (
VEC_index (deferred_locations, deferred_locations_list, i)->die,
VEC_index (deferred_locations, deferred_locations_list, i)->variable,
+ false,
DW_AT_location);
}
@@ -23551,6 +23806,17 @@ dwarf2out_finish (const char *filename)
}
htab_delete (comdat_type_table);
+ /* Add the DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes attributes. */
+ if (targetm.want_debug_pub_sections)
+ {
+ /* FIXME: Should use add_AT_pubnamesptr. This works because most targets
+ don't care what the base section is. */
+ add_AT_lineptr (comp_unit_die (), DW_AT_GNU_pubnames,
+ debug_pubnames_section_label);
+ add_AT_lineptr (comp_unit_die (), DW_AT_GNU_pubtypes,
+ debug_pubtypes_section_label);
+ }
+
/* Output the main compilation unit if non-empty or if .debug_macinfo
will be emitted. */
output_comp_unit (comp_unit_die (), debug_info_level >= DINFO_LEVEL_VERBOSE);
@@ -23571,42 +23837,12 @@ dwarf2out_finish (const char *filename)
output_location_lists (comp_unit_die ());
}
- /* Output public names table if necessary. */
- if (!VEC_empty (pubname_entry, pubname_table))
- {
- gcc_assert (info_section_emitted);
- switch_to_section (debug_pubnames_section);
- output_pubnames (pubname_table);
- }
-
- /* Output public types table if necessary. */
+ /* Output public names and types tables if necessary. */
+ output_pubnames (pubname_table);
/* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
It shouldn't hurt to emit it always, since pure DWARF2 consumers
simply won't look for the section. */
- if (!VEC_empty (pubname_entry, pubtype_table))
- {
- bool empty = false;
-
- if (flag_eliminate_unused_debug_types)
- {
- /* The pubtypes table might be emptied by pruning unused items. */
- unsigned i;
- pubname_ref p;
- empty = true;
- FOR_EACH_VEC_ELT (pubname_entry, pubtype_table, i, p)
- if (p->die->die_offset != 0)
- {
- empty = false;
- break;
- }
- }
- if (!empty)
- {
- gcc_assert (info_section_emitted);
- switch_to_section (debug_pubtypes_section);
- output_pubnames (pubtype_table);
- }
- }
+ output_pubnames (pubtype_table);
/* Output direct and virtual call tables if necessary. */
if (!VEC_empty (dcall_entry, dcall_table))