===================================================================
@@ -202,6 +202,9 @@
/* A vector for a table that contains frame description
information for each routine. */
+#define NOT_INDEXED (-1U)
+#define NO_INDEX_ASSIGNED (-2U)
+
static GTY(()) VEC(dw_fde_ref, gc) *fde_vec;
struct GTY(()) indirect_string_node {
@@ -1216,14 +1219,35 @@
DEF_VEC_P(dw_die_ref);
DEF_VEC_ALLOC_P(dw_die_ref,heap);
+/* Describe an entry into the .debug_addr section. */
+
+enum ate_kind {
+ ate_kind_rtx,
+ ate_kind_rtx_dtprel,
+ ate_kind_label
+};
+
+typedef struct GTY(()) addr_table_entry_struct {
+ enum ate_kind kind;
+ unsigned int refcount;
+ unsigned int index;
+ union addr_table_entry_struct_union
+ {
+ rtx GTY ((tag ("0"))) rtl;
+ char * GTY ((tag ("1"))) label;
+ }
+ GTY ((desc ("%1.kind"))) addr;
+}
+addr_table_entry;
+
/* Location lists are ranges + location descriptions for that range,
so you can track variables that are in different places over
their entire life. */
typedef struct GTY(()) dw_loc_list_struct {
dw_loc_list_ref dw_loc_next;
- const char *begin; /* Label and index for begin address of range */
- unsigned int begin_index;
- const char *end; /* Label for end address of range */
+ const char *begin; /* Label and addr_entry for start of range */
+ addr_table_entry *begin_entry;
+ const char *end; /* Label for end of range */
char *ll_symbol; /* Label for beginning of location list.
Only on head of list */
const char *section; /* Section this loclist is relative to */
@@ -1599,10 +1623,10 @@
descr->dw_loc_opc = op;
descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
- descr->dw_loc_oprnd1.val_index = -1U;
+ descr->dw_loc_oprnd1.val_entry = NULL;
descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
- descr->dw_loc_oprnd2.val_index = -1U;
+ descr->dw_loc_oprnd2.val_entry = NULL;
descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
return descr;
@@ -1809,7 +1833,8 @@
break;
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.val_index);
+ gcc_assert (loc->dw_loc_oprnd1.val_entry->index != NO_INDEX_ASSIGNED);
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.val_entry->index);
break;
case DW_OP_const1u:
case DW_OP_const1s:
@@ -2249,7 +2274,8 @@
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
- dw2_asm_output_data_uleb128 (loc->dw_loc_oprnd1.val_index,
+ gcc_assert (loc->dw_loc_oprnd1.val_entry->index != NO_INDEX_ASSIGNED);
+ dw2_asm_output_data_uleb128 (loc->dw_loc_oprnd1.val_entry->index,
"(index into .debug_addr)");
break;
@@ -2613,7 +2639,7 @@
{
head = new_reg_loc_descr (cfa->reg, cfa->base_offset);
head->dw_loc_oprnd1.val_class = dw_val_class_const;
- head->dw_loc_oprnd1.val_index = -1U;
+ head->dw_loc_oprnd1.val_entry = NULL;
tmp = new_loc_descr (DW_OP_deref, 0, 0);
add_loc_descr (&head, tmp);
if (offset != 0)
@@ -3242,7 +3268,6 @@
static void add_dwarf_attr (dw_die_ref, dw_attr_ref);
static inline enum dw_val_class AT_class (dw_attr_ref);
static inline unsigned int AT_index (dw_attr_ref);
-static inline void set_AT_index (dw_attr_ref, unsigned int);
static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
static inline unsigned AT_flag (dw_attr_ref);
static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT);
@@ -3270,18 +3295,17 @@
static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
dw_loc_list_ref);
static inline dw_loc_list_ref AT_loc_list (dw_attr_ref);
-static unsigned int add_addr_table_entry (dw_attr_node *);
-static void remove_addr_table_entry (unsigned int);
+static addr_table_entry *add_addr_table_entry (void *, enum ate_kind);
+static void remove_addr_table_entry (addr_table_entry *);
static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool);
static inline rtx AT_addr (dw_attr_ref);
-static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *,
- bool);
+static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
unsigned HOST_WIDE_INT);
static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
- unsigned long, bool);
+ unsigned long, bool);
static inline const char *AT_lbl (dw_attr_ref);
static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
static const char *get_AT_low_pc (dw_die_ref);
@@ -3392,7 +3416,7 @@
static unsigned int add_ranges_num (int);
static unsigned int add_ranges (const_tree);
static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
- bool *, bool);
+ bool *, bool);
static void output_ranges (void);
static dw_line_info_table *new_line_info_table (void);
static void output_line_info (bool);
@@ -3534,49 +3558,49 @@
static void schedule_generic_params_dies_gen (tree t);
static void gen_scheduled_generic_parms_dies (void);
-/* Return the operator to use for an address of a variable.
- DTPREL is true for thread-local variables whose address
- is really an offset relative to the TLS pointer, which
- will need link-time relocation, but will not need relocation
- by the DWARF consumer. For those, we use DW_OP_const*.
- For regular variables, which need both link-time relocation
- and consumer-level relocation (e.g., to account for
- shared objects loaded at a random address), we use
- DW_OP_addr*. */
+/* enum for tracking thread-local variables whose address is really an offset
+ relative to the TLS pointer, which will need link-time relocation, but will
+ not need relocation by the DWARF consumer. */
-static inline enum dwarf_location_atom dw_addr_op (bool dtprel)
+enum dtprel_bool
{
- if (dtprel)
+ dtprel_false = 0,
+ dtprel_true = 1
+};
+
+/* Return the operator to use for an address of a variable. For dtprel_true, we
+ use DW_OP_const*. For regular variables, which need both link-time
+ relocation and consumer-level relocation (e.g., to account for shared objects
+ loaded at a random address), we use DW_OP_addr*. */
+
+static inline enum dwarf_location_atom
+dw_addr_op (enum dtprel_bool dtprel)
+{
+ if (dtprel == dtprel_true)
return (dwarf_split_debug_info ? DW_OP_GNU_const_index
: (DWARF2_ADDR_SIZE == 4 ? DW_OP_const4u : DW_OP_const8u));
else
- return (dwarf_split_debug_info ? DW_OP_GNU_addr_index : DW_OP_addr);
+ return dwarf_split_debug_info ? DW_OP_GNU_addr_index : DW_OP_addr;
}
/* Return a pointer to a newly allocated address location description. If
dwarf_split_debug_info is true, then record the address with the appropriate
relocation. */
static inline dw_loc_descr_ref
-new_addr_loc_descr (rtx addr, int dtprel)
+new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
{
dw_loc_descr_ref ref = new_loc_descr (dw_addr_op (dtprel), 0, 0);
ref->dw_loc_oprnd1.val_class = dw_val_class_addr;
- ref->dw_loc_oprnd1.val_index = -1U;
ref->dw_loc_oprnd1.v.val_addr = addr;
ref->dtprel = dtprel;
if (dwarf_split_debug_info)
- {
- dw_attr_node attr;
+ ref->dw_loc_oprnd1.val_entry
+ = add_addr_table_entry (addr,
+ dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx);
+ else
+ ref->dw_loc_oprnd1.val_entry = NULL;
- attr.dw_attr = DW_AT_location;
- attr.dw_attr_val.val_class = (dtprel
- ? dw_val_class_loc : dw_val_class_addr);
- attr.dw_attr_val.val_index = -1U;
- attr.dw_attr_val.v.val_addr = addr;
-
- ref->dw_loc_oprnd1.val_index = add_addr_table_entry (&attr);
- }
return ref;
}
@@ -3586,7 +3610,7 @@
#define DEBUG_INFO_SECTION ".debug_info"
#endif
#ifndef DEBUG_DWO_INFO_SECTION
-#define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
+#define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
#endif
#ifndef DEBUG_ABBREV_SECTION
#define DEBUG_ABBREV_SECTION ".debug_abbrev"
@@ -3598,13 +3622,13 @@
#define DEBUG_ARANGES_SECTION ".debug_aranges"
#endif
#ifndef DEBUG_ADDR_SECTION
-#define DEBUG_ADDR_SECTION ".debug_addr"
+#define DEBUG_ADDR_SECTION ".debug_addr"
#endif
#ifndef DEBUG_NORM_MACINFO_SECTION
-#define DEBUG_NORM_MACINFO_SECTION ".debug_macinfo"
+#define DEBUG_NORM_MACINFO_SECTION ".debug_macinfo"
#endif
#ifndef DEBUG_DWO_MACINFO_SECTION
-#define DEBUG_DWO_MACINFO_SECTION ".debug_macinfo.dwo"
+#define DEBUG_DWO_MACINFO_SECTION ".debug_macinfo.dwo"
#endif
#ifndef DEBUG_MACINFO_SECTION
#define DEBUG_MACINFO_SECTION \
@@ -3615,7 +3639,7 @@
#define DEBUG_NORM_MACRO_SECTION ".debug_macro"
#endif
#ifndef DEBUG_DWO_MACRO_SECTION
-#define DEBUG_DWO_MACRO_SECTION ".debug_macro.dwo"
+#define DEBUG_DWO_MACRO_SECTION ".debug_macro.dwo"
#endif
#ifndef DEBUG_MACRO_SECTION
#define DEBUG_MACRO_SECTION \
@@ -3626,13 +3650,13 @@
#define DEBUG_LINE_SECTION ".debug_line"
#endif
#ifndef DEBUG_DWO_LINE_SECTION
-#define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
+#define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
#endif
#ifndef DEBUG_LOC_SECTION
#define DEBUG_LOC_SECTION ".debug_loc"
#endif
#ifndef DEBUG_DWO_LOC_SECTION
-#define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo"
+#define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo"
#endif
#ifndef DEBUG_PUBNAMES_SECTION
#define DEBUG_PUBNAMES_SECTION \
@@ -4419,30 +4443,20 @@
}
/* Return the index for any attribute that will be referenced with a
- DW_FORM_GNU_addr_index. Strings have their indices handled differently to
- account for reference counting pruning. */
+ DW_FORM_GNU_addr_index or DW_FORM_GNU_str_index. String indices
+ are stored in dw_attr_val.v.val_str for reference counting
+ pruning. */
static inline unsigned int
AT_index (dw_attr_ref a)
{
if (AT_class (a) == dw_val_class_str)
return a->dw_attr_val.v.val_str->index;
- else
- return a->dw_attr_val.val_index;
+ else if (a->dw_attr_val.val_entry != NULL)
+ return a->dw_attr_val.val_entry->index;
+ return NOT_INDEXED;
}
-/* Set the index for any attribute that will be referenced with a
- DW_FORM_GNU_addr_index. */
-
-static inline void
-set_AT_index (dw_attr_ref a, unsigned int index)
-{
- if (AT_class (a) == dw_val_class_str)
- a->dw_attr_val.v.val_str->index = index;
- else
- a->dw_attr_val.val_index = index;
-}
-
/* Add a flag value attribute to a DIE. */
static inline void
@@ -4452,7 +4466,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_flag;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_flag = flag;
add_dwarf_attr (die, &attr);
}
@@ -4473,7 +4487,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_const;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_int = int_val;
add_dwarf_attr (die, &attr);
}
@@ -4495,7 +4509,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_unsigned_const;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_unsigned = unsigned_val;
add_dwarf_attr (die, &attr);
}
@@ -4517,7 +4531,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_const_double;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_double.high = high;
attr.dw_attr_val.v.val_double.low = low;
add_dwarf_attr (die, &attr);
@@ -4533,7 +4547,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_vec;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_vec.length = length;
attr.dw_attr_val.v.val_vec.elt_size = elt_size;
attr.dw_attr_val.v.val_vec.array = array;
@@ -4550,38 +4564,48 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_data8;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
memcpy (attr.dw_attr_val.v.val_data8, data8, 8);
add_dwarf_attr (die, &attr);
}
-/* Add DW_AT_low_pc and DW_AT_high_pc to a DIE. */
+/* Add DW_AT_low_pc and DW_AT_high_pc to a DIE. When using
+ dwarf_split_debug_info, address attributes in dies destined for the
+ final executable have force_direct set to avoid using indexed
+ references. */
+
static inline void
add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high,
bool force_direct)
{
dw_attr_node attr;
+ char * lbl_id;
+ lbl_id = xstrdup (lbl_low);
attr.dw_attr = DW_AT_low_pc;
attr.dw_attr_val.val_class = dw_val_class_lbl_id;
- attr.dw_attr_val.val_index = -1U;
- attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_low);
+ attr.dw_attr_val.v.val_lbl_id = lbl_id;
+ if (dwarf_split_debug_info && !force_direct)
+ attr.dw_attr_val.val_entry
+ = add_addr_table_entry (lbl_id, ate_kind_label);
+ else
+ attr.dw_attr_val.val_entry = NULL;
add_dwarf_attr (die, &attr);
- if (dwarf_split_debug_info && !force_direct)
- set_AT_index (get_AT (die, DW_AT_low_pc), add_addr_table_entry (&attr));
attr.dw_attr = DW_AT_high_pc;
if (dwarf_version < 4)
attr.dw_attr_val.val_class = dw_val_class_lbl_id;
else
attr.dw_attr_val.val_class = dw_val_class_high_pc;
- attr.dw_attr_val.val_index = -1U;
- attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_high);
- add_dwarf_attr (die, &attr);
+ lbl_id = xstrdup (lbl_high);
+ attr.dw_attr_val.v.val_lbl_id = lbl_id;
if (attr.dw_attr_val.val_class == dw_val_class_lbl_id
&& dwarf_split_debug_info && !force_direct)
- set_AT_index (get_AT (die, DW_AT_high_pc), add_addr_table_entry (&attr));
-
+ attr.dw_attr_val.val_entry
+ = add_addr_table_entry (lbl_id, ate_kind_label);
+ else
+ attr.dw_attr_val.val_entry = NULL;
+ add_dwarf_attr (die, &attr);
}
/* Hash and equality functions for debug_str_hash. */
@@ -4638,7 +4662,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_str;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_str = node;
add_dwarf_attr (die, &attr);
}
@@ -4650,27 +4674,43 @@
return a->dw_attr_val.v.val_str->str;
}
-/* A vector for a table of strings in the form DW_FORM_GNU_index_str. */
+/* Call this function directly to bypass AT_string_form's logic to put
+ the string inline in the die. */
-typedef struct indirect_string_node indirect_string_node;
-DEF_VEC_O(indirect_string_node);
-DEF_VEC_ALLOC_O(indirect_string_node, gc);
-static GTY (()) VEC (indirect_string_node, gc) *index_string_table;
+static void
+set_indirect_string (struct indirect_string_node *node)
+{
+ char label[32];
+ /* Already indirect is a no op. */
+ if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
+ {
+ gcc_assert (node->label);
+ return;
+ }
+ ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+ ++dw2_string_counter;
+ node->label = xstrdup (label);
+ if (!dwarf_split_debug_info)
+ {
+ node->form = DW_FORM_strp;
+ node->index = NOT_INDEXED;
+ }
+ else
+ {
+ node->form = DW_FORM_GNU_str_index;
+ node->index = NO_INDEX_ASSIGNED;
+ }
+}
+
/* Find out whether a string should be output inline in DIE
or out-of-line in .debug_str section. */
static enum dwarf_form
-AT_string_form (dw_attr_ref a)
+find_string_form (struct indirect_string_node *node)
{
- static unsigned int index_string_count = 0;
- struct indirect_string_node *node;
unsigned int len;
- char label[32];
- gcc_assert (a && AT_class (a) == dw_val_class_str);
-
- node = a->dw_attr_val.v.val_str;
if (node->form)
return node->form;
@@ -4689,23 +4729,21 @@
&& (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
return node->form = DW_FORM_string;
- ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
- ++dw2_string_counter;
- node->label = xstrdup (label);
+ set_indirect_string (node);
- if (!dwarf_split_debug_info)
- node->form = DW_FORM_strp;
- else
- {
- node->form = DW_FORM_GNU_str_index;
- set_AT_index (a, index_string_count);
- index_string_count++;
- VEC_safe_push (indirect_string_node, gc, index_string_table, node);
- }
-
return node->form;
}
+/* Find out whether the string referenced from the attribute should be
+ output inline in DIE or out-of-line in .debug_str section. */
+
+static enum dwarf_form
+AT_string_form (dw_attr_ref a)
+{
+ gcc_assert (a && AT_class (a) == dw_val_class_str);
+ return find_string_form (a->dw_attr_val.v.val_str);
+}
+
/* Add a DIE reference attribute value to a DIE. */
static inline void
@@ -4724,7 +4762,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_die_ref;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_die_ref.die = targ_die;
attr.dw_attr_val.v.val_die_ref.external = 0;
add_dwarf_attr (die, &attr);
@@ -4773,7 +4811,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_fde_ref;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_fde_index = targ_fde;
add_dwarf_attr (die, &attr);
}
@@ -4787,7 +4825,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_loc;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_loc = loc;
add_dwarf_attr (die, &attr);
}
@@ -4806,7 +4844,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_loc_list;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_loc_list = loc_list;
add_dwarf_attr (die, &attr);
have_location_lists = true;
@@ -4826,34 +4864,121 @@
return &a->dw_attr_val.v.val_loc_list;
}
-/* A table of entries into the .debug_addr section. */
+/* Table of entries into the .debug_addr section. */
-static GTY (()) VEC (dw_attr_node,gc) * addr_index_table;
+static GTY ((param_is (addr_table_entry))) htab_t addr_index_table;
-static unsigned int
-add_addr_table_entry (dw_attr_node *attr)
+/* Hash an address_table_entry. */
+
+static hashval_t
+addr_table_entry_do_hash (const void *x)
{
- gcc_assert (dwarf_split_debug_info);
+ const addr_table_entry *a = (const addr_table_entry *) x;
+ switch (a->kind)
+ {
+ case ate_kind_rtx:
+ return iterative_hash_rtx (a->addr.rtl, 0);
+ case ate_kind_rtx_dtprel:
+ return iterative_hash_rtx (a->addr.rtl, 1);
+ case ate_kind_label:
+ return htab_hash_string (a->addr.label);
+ default:
+ gcc_unreachable ();
+ }
+}
- VEC_safe_push (dw_attr_node, gc, addr_index_table, attr);
- return VEC_length (dw_attr_node, addr_index_table) - 1;
+/* Determine equality for two address_table_entries. */
+
+static int
+addr_table_entry_eq (const void *x1, const void *x2)
+{
+ const addr_table_entry *a1 = (const addr_table_entry *) x1;
+ const addr_table_entry *a2 = (const addr_table_entry *) x2;
+
+ if (a1->kind != a2->kind)
+ return 0;
+ switch (a1->kind)
+ {
+ case ate_kind_rtx:
+ case ate_kind_rtx_dtprel:
+ return rtx_equal_p (a1->addr.rtl, a2->addr.rtl);
+ case ate_kind_label:
+ return strcmp (a1->addr.label, a2->addr.label) == 0;
+ default:
+ gcc_unreachable ();
+ }
}
-/* Remove an entry from the addr table. Since we have already numbered
- all the entries, the best we can do here is null it out. */
+/* Initialize an addr_table_entry. */
-static void
-remove_addr_table_entry (unsigned int i)
+void
+init_addr_table_entry (addr_table_entry *e, enum ate_kind kind, void *addr);
+
+void
+init_addr_table_entry (addr_table_entry *e, enum ate_kind kind, void *addr)
{
- dw_attr_node *attr;
+ e->kind = kind;
+ switch (kind)
+ {
+ case ate_kind_rtx:
+ case ate_kind_rtx_dtprel:
+ e->addr.rtl = (rtx) addr;
+ break;
+ case ate_kind_label:
+ e->addr.label = (char *) addr;
+ break;
+ }
+ e->refcount = 0;
+ e->index = NO_INDEX_ASSIGNED;
+}
+/* Add attr to the address table entry to the table. Defer setting an
+ index until output time. */
+
+static addr_table_entry *
+add_addr_table_entry (void *addr, enum ate_kind kind)
+{
+ addr_table_entry *node;
+ addr_table_entry finder;
+ void **slot;
+
gcc_assert (dwarf_split_debug_info);
- gcc_assert (i < VEC_length (dw_attr_node, addr_index_table));
+ if (! addr_index_table)
+ addr_index_table = htab_create_ggc (10, addr_table_entry_do_hash,
+ addr_table_entry_eq, NULL);
+ init_addr_table_entry (&finder, kind, addr);
+ slot = htab_find_slot (addr_index_table, &finder, INSERT);
- attr = VEC_index (dw_attr_node, addr_index_table, i);
- attr->dw_attr = (enum dwarf_attribute) 0;
+ if (*slot == HTAB_EMPTY_ENTRY)
+ {
+ node = ggc_alloc_cleared_addr_table_entry ();
+ init_addr_table_entry (node, kind, addr);
+ *slot = node;
+ }
+ else
+ node = (addr_table_entry *) *slot;
+
+ node->refcount++;
+ return node;
}
+/* Remove an entry from the addr table by decrementing its refcount.
+ Strictly, decrementing the refcount would be enough, but the
+ assertion that the entry is actually in the table has found
+ bugs. */
+
+static void
+remove_addr_table_entry (addr_table_entry *entry)
+{
+ addr_table_entry *node;
+
+ gcc_assert (dwarf_split_debug_info && addr_index_table);
+ node = (addr_table_entry *) htab_find (addr_index_table, entry);
+ /* After an index is assigned, the table is frozen. */
+ gcc_assert (node->refcount > 0 && node->index == NO_INDEX_ASSIGNED);
+ node->refcount--;
+}
+
/* Given a location list, remove all addresses it refers to from the
address_table. */
@@ -4861,25 +4986,55 @@
remove_loc_list_addr_table_entries (dw_loc_descr_ref descr)
{
for (; descr; descr = descr->dw_loc_next)
- if (descr->dw_loc_oprnd1.val_index != -1U)
- remove_addr_table_entry (descr->dw_loc_oprnd1.val_index);
+ if (descr->dw_loc_oprnd1.val_entry != NULL)
+ {
+ gcc_assert (descr->dw_loc_oprnd1.val_entry->index == NO_INDEX_ASSIGNED);
+ remove_addr_table_entry (descr->dw_loc_oprnd1.val_entry);
+ }
}
-/* Add an address constant attribute value to a DIE. */
+/* A helper function for dwarf2out_finish called through
+ htab_traverse. Assign an addr_table_entry its index. All entries
+ must be collected into the table when this function is called,
+ because the indexing code relies on htab_traverse to traverse nodes
+ in the same order for each run. */
+static int
+index_addr_table_entry (void **h, void *v)
+{
+ addr_table_entry *node = (addr_table_entry *) *h;
+ unsigned int *index = (unsigned int *) v;
+
+ /* Don't index unreferenced nodes. */
+ if (node->refcount == 0)
+ return 1;
+
+ gcc_assert(node->index == NO_INDEX_ASSIGNED);
+ node->index = *index;
+ *index += 1;
+
+ return 1;
+}
+
+/* Add an address constant attribute value to a DIE. When using
+ dwarf_split_debug_info, address attributes in dies destined for the
+ final executable should be direct references--setting the parameter
+ force_direct ensures this behavior. */
+
static inline void
add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr,
- bool force_direct)
+ bool force_direct)
{
dw_attr_node attr;
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_addr;
- attr.dw_attr_val.val_index = -1U;
attr.dw_attr_val.v.val_addr = addr;
+ if (dwarf_split_debug_info && !force_direct)
+ attr.dw_attr_val.val_entry = add_addr_table_entry (addr, ate_kind_rtx);
+ else
+ attr.dw_attr_val.val_entry = NULL;
add_dwarf_attr (die, &attr);
- if (dwarf_split_debug_info && !force_direct)
- set_AT_index (get_AT (die, attr_kind), add_addr_table_entry (&attr));
}
/* Get the RTX from to an address DIE attribute. */
@@ -4901,7 +5056,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_file;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_file = fd;
add_dwarf_attr (die, &attr);
}
@@ -4925,7 +5080,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_vms_delta;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_vms_delta.lbl1 = xstrdup (lbl1);
attr.dw_attr_val.v.val_vms_delta.lbl2 = xstrdup (lbl2);
add_dwarf_attr (die, &attr);
@@ -4935,17 +5090,19 @@
static inline void
add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind,
- const char *lbl_id, bool force_direct)
+ const char *lbl_id)
{
dw_attr_node attr;
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_lbl_id;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
+ if (dwarf_split_debug_info)
+ attr.dw_attr_val.val_entry
+ = add_addr_table_entry (attr.dw_attr_val.v.val_lbl_id,
+ ate_kind_label);
add_dwarf_attr (die, &attr);
- if (dwarf_split_debug_info && !force_direct)
- set_AT_index (get_AT (die, attr_kind), add_addr_table_entry (&attr));
}
/* Add a section offset attribute value to a DIE, an offset into the
@@ -4959,7 +5116,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_lineptr;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
add_dwarf_attr (die, &attr);
}
@@ -4975,7 +5132,7 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_macptr;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
add_dwarf_attr (die, &attr);
}
@@ -4990,25 +5147,34 @@
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_offset;
- attr.dw_attr_val.val_index = -1U;
+ attr.dw_attr_val.val_entry = NULL;
attr.dw_attr_val.v.val_offset = offset;
add_dwarf_attr (die, &attr);
}
-/* Add a range_list attribute value to a DIE. */
+/* Add a range_list attribute value to a DIE. When using
+ dwarf_split_debug_info, address attributes in dies destined for the
+ final executable should be direct references--setting the parameter
+ force_direct ensures this behavior. */
+#define UNRELOCATED_OFFSET ((addr_table_entry *) 1)
+#define RELOCATED_OFFSET (NULL)
+
static void
add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
- long unsigned int offset, bool force_direct)
+ long unsigned int offset, bool force_direct)
{
dw_attr_node attr;
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_range_list;
- /* This is a bit of a misnomer--the offset isn't an index, but we need to
- save force_direct for output. */
- attr.dw_attr_val.val_index
- = (dwarf_split_debug_info && !force_direct) ? offset : -1U;
+ /* For the range_list attribute, use val_entry to store whether the
+ offset should follow split-debug-info or normal semantics. This
+ value is read in output_range_list_offset. */
+ if (dwarf_split_debug_info && !force_direct)
+ attr.dw_attr_val.val_entry = UNRELOCATED_OFFSET;
+ else
+ attr.dw_attr_val.val_entry = RELOCATED_OFFSET;
attr.dw_attr_val.v.val_offset = offset;
add_dwarf_attr (die, &attr);
}
@@ -8055,8 +8221,11 @@
switch (AT_class (a))
{
case dw_val_class_addr:
- if (dwarf_split_debug_info && AT_index (a) != -1U)
- size += size_of_uleb128 (AT_index (a));
+ if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+ {
+ gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+ size += size_of_uleb128 (AT_index (a));
+ }
else
size += DWARF2_ADDR_SIZE;
break;
@@ -8076,8 +8245,11 @@
}
break;
case dw_val_class_loc_list:
- if (dwarf_split_debug_info && AT_index (a) != -1U)
- size += size_of_uleb128 (AT_index (a));
+ if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+ {
+ gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+ size += size_of_uleb128 (AT_index (a));
+ }
else
size += DWARF_OFFSET_SIZE;
break;
@@ -8142,8 +8314,11 @@
size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_lbl_id:
- if (dwarf_split_debug_info && AT_index (a) != -1U)
- size += size_of_uleb128 (AT_index (a));
+ if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+ {
+ gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+ size += size_of_uleb128 (AT_index (a));
+ }
else
size += DWARF2_ADDR_SIZE;
break;
@@ -8155,7 +8330,7 @@
form = AT_string_form (a);
if (form == DW_FORM_strp)
size += DWARF_OFFSET_SIZE;
- else if (form == DW_FORM_GNU_str_index)
+ else if (form == DW_FORM_GNU_str_index)
size += size_of_uleb128 (AT_index (a));
else
size += strlen (a->dw_attr_val.v.val_str->str) + 1;
@@ -8361,8 +8536,8 @@
case DW_AT_high_pc:
case DW_AT_entry_pc:
case DW_AT_trampoline:
- return (dwarf_split_debug_info && AT_index (a) != -1U
- ? DW_FORM_GNU_addr_index : DW_FORM_addr);
+ return (AT_index (a) == NOT_INDEXED
+ ? DW_FORM_addr : DW_FORM_GNU_addr_index);
default:
break;
}
@@ -8480,8 +8655,8 @@
case dw_val_class_fde_ref:
return DW_FORM_data;
case dw_val_class_lbl_id:
- return (dwarf_split_debug_info && AT_index (a) != -1U
- ? DW_FORM_GNU_addr_index : DW_FORM_addr);
+ return (AT_index (a) == NOT_INDEXED
+ ? DW_FORM_addr : DW_FORM_GNU_addr_index);
case dw_val_class_lineptr:
case dw_val_class_macptr:
return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data;
@@ -8603,7 +8778,7 @@
dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
retlist->begin = begin;
- retlist->begin_index = -1U;
+ retlist->begin_entry = NULL;
retlist->end = end;
retlist->expr = expr;
retlist->section = section;
@@ -8653,7 +8828,7 @@
dw2_asm_output_data (1, DW_LLE_start_length_entry,
"Location list start/length entry (%s)",
list_head->ll_symbol);
- dw2_asm_output_data_uleb128 (curr->begin_index,
+ dw2_asm_output_data_uleb128 (curr->begin_entry->index,
"Location list range start index (%s)",
curr->begin);
/* The length field is 4 bytes. If we ever need to support
@@ -8704,14 +8879,16 @@
}
}
-/* Output the offset into the debug_range section. */
+/* Output a range_list offset into the debug_range section. Emit a
+ relocated reference if val_entry is NULL, otherwise, emit an
+ indirect reference. */
static void
output_range_list_offset (dw_attr_ref a)
{
const char *name = dwarf_attr_name (a->dw_attr);
- if (!dwarf_split_debug_info || AT_index (a) == -1U)
+ if (a->dw_attr_val.val_entry == RELOCATED_OFFSET)
{
char *p = strchr (ranges_section_label, '\0');
sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX, a->dw_attr_val.v.val_offset);
@@ -8747,7 +8924,7 @@
{
const char *name = dwarf_attr_name (a->dw_attr);
- if (dwarf_split_debug_info && AT_index (a) != -1U)
+ if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
{
dw2_asm_output_data_uleb128 (AT_index (a), "%s", name);
return;
@@ -8757,6 +8934,7 @@
case dw_val_class_addr:
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
break;
+ case dw_val_class_high_pc:
case dw_val_class_lbl_id:
dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
break;
@@ -8989,12 +9167,12 @@
break;
case dw_val_class_str:
- if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE,
- a->dw_attr_val.v.val_str->label,
- debug_str_section,
- "%s: \"%s\"", name, AT_string (a));
- else if (a->dw_attr_val.v.val_str->form == DW_FORM_GNU_str_index)
+ if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ a->dw_attr_val.v.val_str->label,
+ debug_str_section,
+ "%s: \"%s\"", name, AT_string (a));
+ else if (a->dw_attr_val.v.val_str->form == DW_FORM_GNU_str_index)
dw2_asm_output_data_uleb128 (AT_index (a),
"%s: \"%s\"", name, AT_string (a));
else
@@ -9170,9 +9348,9 @@
static dw_die_ref
get_skeleton_type_unit (void)
{
- /* For split_debug_sections with use_type info, all type units int the
- skeleton sections have identical dies (but different headers). This single
- die will be output many times. */
+ /* For dwarf_split_debug_sections with use_type info, all type units in the
+ skeleton sections have identical dies (but different headers). This
+ single die will be output many times. */
static dw_die_ref skeleton_type_unit = NULL;
@@ -9218,7 +9396,7 @@
"Offset Into Abbrev. Section");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
- comp_unit->die_abbrev = 1;
+ comp_unit->die_abbrev = SKELETON_COMP_DIE_ABBREV;
output_die (comp_unit);
/* Build the skeleton debug_abbrev section. */
@@ -9286,6 +9464,7 @@
unmark_dies (node->root_die);
+#if defined (OBJECT_FORMAT_ELF)
if (dwarf_split_debug_info)
{
/* Produce the skeleton type-unit header. */
@@ -9298,7 +9477,6 @@
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- /* One for the terminating NULL byte. */
dw2_asm_output_data (DWARF_OFFSET_SIZE,
DWARF_COMPILE_UNIT_HEADER_SIZE
- DWARF_INITIAL_LENGTH_SIZE
@@ -9316,6 +9494,7 @@
output_die (get_skeleton_type_unit ());
}
+#endif
}
/* Return the DWARF2/3 pubname associated with a decl. */
@@ -9699,8 +9878,10 @@
return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
}
-/* Add a new entry to .debug_ranges corresponding to a pair of
- labels. */
+/* Add a new entry to .debug_ranges corresponding to a pair of labels.
+ When using dwarf_split_debug_info, address attributes in dies destined
+ for the final executable should be direct references--setting the
+ parameter force_direct ensures this behavior. */
static void
add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
@@ -12649,7 +12830,7 @@
if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
break;
- temp = new_addr_loc_descr (rtl, true);
+ temp = new_addr_loc_descr (rtl, dtprel_true);
mem_loc_result = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
add_loc_descr (&mem_loc_result, temp);
@@ -12661,7 +12842,7 @@
break;
symref:
- mem_loc_result = new_addr_loc_descr (rtl, 0);
+ mem_loc_result = new_addr_loc_descr (rtl, dtprel_false);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
break;
@@ -13563,7 +13744,7 @@
if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE
&& (dwarf_version >= 4 || !dwarf_strict))
{
- loc_result = new_addr_loc_descr (rtl, 0);
+ loc_result = new_addr_loc_descr (rtl, dtprel_false);
add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
}
@@ -14264,8 +14445,8 @@
if (DECL_THREAD_LOCAL_P (loc))
{
rtx rtl;
- enum dwarf_location_atom tls_op;
- bool dtprel = false;
+ enum dwarf_location_atom tls_op;
+ enum dtprel_bool dtprel = dtprel_false;
if (targetm.have_tls)
{
@@ -14282,8 +14463,8 @@
operand shouldn't be. */
if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
return 0;
- dtprel = true;
- tls_op = DW_OP_GNU_push_tls_address;
+ dtprel = dtprel_true;
+ tls_op = DW_OP_GNU_push_tls_address;
}
else
{
@@ -14309,7 +14490,7 @@
return 0;
ret = new_addr_loc_descr (rtl, dtprel);
- ret1 = new_loc_descr (tls_op, 0, 0);
+ ret1 = new_loc_descr (tls_op, 0, 0);
add_loc_descr (&ret, ret1);
have_address = 1;
@@ -14354,7 +14535,7 @@
return 0;
}
else if (CONSTANT_P (rtl) && const_ok_for_output (rtl))
- ret = new_addr_loc_descr (rtl, 0);
+ ret = new_addr_loc_descr (rtl, dtprel_false);
else
{
enum machine_mode mode, mem_mode;
@@ -15292,7 +15473,7 @@
dw_loc_descr_ref loc_result;
resolve_one_addr (&rtl, NULL);
rtl_addr:
- loc_result = new_addr_loc_descr (rtl, 0);
+ loc_result = new_addr_loc_descr (rtl, dtprel_false);
add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
add_AT_loc (die, DW_AT_location, loc_result);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
@@ -16822,7 +17003,7 @@
add_name_attribute (die, VMS_DEBUG_MAIN_POINTER);
ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
FUNC_LABEL_ID (cfun));
- add_AT_lbl_id (die, DW_AT_entry_pc, label, false);
+ add_AT_lbl_id (die, DW_AT_entry_pc, label);
/* Make it the first child of comp_unit_die (). */
die->die_parent = comp_unit_die ();
@@ -17436,7 +17617,7 @@
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die (decl, decl_die);
else
- add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl), false);
+ add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl));
}
#endif
@@ -17957,7 +18138,7 @@
if (stmt_die == NULL)
stmt_die = subr_die;
die = new_die (DW_TAG_GNU_call_site, stmt_die, NULL_TREE);
- add_AT_lbl_id (die, DW_AT_low_pc, ca_loc->label, false);
+ add_AT_lbl_id (die, DW_AT_low_pc, ca_loc->label);
if (ca_loc->tail_call_p)
add_AT_flag (die, DW_AT_GNU_tail_call, 1);
if (ca_loc->symbol_ref)
@@ -17966,7 +18147,7 @@
if (tdie)
add_AT_die_ref (die, DW_AT_abstract_origin, tdie);
else
- add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref, false);
+ add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref, false);
}
return die;
}
@@ -18896,7 +19077,7 @@
gcc_assert (!INSN_DELETED_P (insn));
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
- add_AT_lbl_id (lbl_die, DW_AT_low_pc, label, false);
+ add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
}
else if (insn
&& NOTE_P (insn)
@@ -18904,7 +19085,7 @@
&& CODE_LABEL_NUMBER (insn) != -1)
{
ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn));
- add_AT_lbl_id (lbl_die, DW_AT_low_pc, label, false);
+ add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
}
}
}
@@ -18943,7 +19124,7 @@
{
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
BLOCK_NUMBER (stmt));
- add_AT_lbl_id (die, DW_AT_entry_pc, label, false);
+ add_AT_lbl_id (die, DW_AT_entry_pc, label);
}
add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt), false);
@@ -21612,24 +21793,22 @@
case DW_MACRO_GNU_define_indirect:
case DW_MACRO_GNU_undef_indirect:
node = find_AT_string (ref->info);
- /* FIXME: needs to change for dwarf_split_debug_info. */
- if (node->form != DW_FORM_strp)
- {
- char label[32];
- ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
- ++dw2_string_counter;
- node->label = xstrdup (label);
- node->form = DW_FORM_strp;
- }
+ gcc_assert (node
+ && ((node->form == DW_FORM_strp)
+ || (node->form == DW_FORM_GNU_str_index)));
dw2_asm_output_data (1, ref->code,
ref->code == DW_MACRO_GNU_define_indirect
? "Define macro indirect"
: "Undefine macro indirect");
dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
(unsigned long) ref->lineno);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
- debug_str_section, "The macro: \"%s\"",
- ref->info);
+ if (node->form == DW_FORM_strp)
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ debug_str_section, "The macro: \"%s\"",
+ ref->info);
+ else
+ dw2_asm_output_data_uleb128 (node->index, "The macro: \"%s\"",
+ ref->info);
break;
case DW_MACRO_GNU_transparent_include:
dw2_asm_output_data (1, ref->code, "Transparent include");
@@ -21772,6 +21951,42 @@
return count;
}
+/* Save any strings needed by the macinfo table in the debug str
+ table. All strings must be collected into the table by the time
+ index_string is called. */
+
+static void
+save_macinfo_strings (void)
+{
+ unsigned len;
+ unsigned i;
+ macinfo_entry *ref;
+
+ for (i = 0; VEC_iterate (macinfo_entry, macinfo_table, i, ref); i++)
+ {
+ switch (ref->code)
+ {
+ /* Match the logic in output_macinfo_op to decide on
+ indirect strings. */
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ len = strlen (ref->info) + 1;
+ if (!dwarf_strict
+ && len > DWARF_OFFSET_SIZE
+ && !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
+ && (debug_str_section->common.flags & SECTION_MERGE) != 0)
+ set_indirect_string (find_AT_string (ref->info));
+ break;
+ case DW_MACRO_GNU_define_indirect:
+ case DW_MACRO_GNU_undef_indirect:
+ set_indirect_string (find_AT_string (ref->info));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/* Output macinfo section(s). */
static void
@@ -21965,7 +22180,7 @@
debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
SECTION_DEBUG, NULL);
ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
- DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
+ DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
/* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
the main .o, but the skeleton_line goes into the split off dwo. */
@@ -21987,7 +22202,7 @@
debug_macinfo_section = get_section (dwarf_strict
? DEBUG_MACINFO_SECTION
: DEBUG_MACRO_SECTION,
- DEBUG_MACRO_SECTION_FLAGS, NULL);
+ DEBUG_MACRO_SECTION_FLAGS, NULL);
debug_line_section = get_section (DEBUG_LINE_SECTION,
SECTION_DEBUG, NULL);
debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
@@ -21995,7 +22210,7 @@
debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
SECTION_DEBUG, NULL);
debug_str_section = get_section (DEBUG_STR_SECTION,
- DEBUG_STR_SECTION_FLAGS, NULL);
+ DEBUG_STR_SECTION_FLAGS, NULL);
debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
SECTION_DEBUG, NULL);
debug_frame_section = get_section (DEBUG_FRAME_SECTION,
@@ -22020,7 +22235,7 @@
ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
DEBUG_RANGES_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
- DEBUG_ADDR_SECTION_LABEL, 0);
+ DEBUG_ADDR_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
dwarf_strict
? DEBUG_MACINFO_SECTION_LABEL
@@ -22052,6 +22267,71 @@
}
/* A helper function for dwarf2out_finish called through
+ htab_traverse. Assign a string its index. All strings must be
+ collected into the table by the time index_string is called,
+ because the indexing code relies on htab_traverse to traverse nodes
+ in the same order for each run. */
+
+static int
+index_string (void **h, void *v)
+{
+ struct indirect_string_node *node = (struct indirect_string_node *) *h;
+ unsigned int *index = (unsigned int *) v;
+
+ find_string_form (node);
+ if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+ {
+ gcc_assert(node->index == NO_INDEX_ASSIGNED);
+ node->index = *index;
+ *index += 1;
+ }
+ return 1;
+}
+
+/* A helper function for output_indirect_strings called through
+ htab_traverse. Output the offset to a string and update the
+ current offset. */
+
+static int
+output_index_string_offset (void **h, void *v)
+{
+ struct indirect_string_node *node = (struct indirect_string_node *) *h;
+ unsigned int *offset = (unsigned int *) v;
+
+ if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+ {
+ /* Assert that this node has been assigned an index. */
+ gcc_assert (node->index != NO_INDEX_ASSIGNED
+ && node->index != NOT_INDEXED);
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, *offset,
+ "indexed string 0x%x: %s", node->index, node->str);
+ *offset += strlen (node->str) + 1;
+ }
+ return 1;
+}
+
+/* A helper function for dwarf2out_finish called through
+ htab_traverse. Output the indexed string. */
+
+static int
+output_index_string (void **h, void *v)
+{
+ struct indirect_string_node *node = (struct indirect_string_node *) *h;
+ unsigned int *cur_idx = (unsigned int *) v;
+
+ if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+ {
+ /* Assert that the strings are output in the same order as their
+ indexes were assigned. */
+ gcc_assert (*cur_idx == node->index);
+ ASM_OUTPUT_LABEL (asm_out_file, node->label);
+ assemble_string (node->str, strlen (node->str) + 1);
+ *cur_idx += 1;
+ }
+ return 1;
+}
+
+/* A helper function for dwarf2out_finish called through
htab_traverse. Emit one queued .debug_str string. */
static int
@@ -22059,9 +22339,8 @@
{
struct indirect_string_node *node = (struct indirect_string_node *) *h;
- if (node->form == DW_FORM_strp)
+ if (node->form == DW_FORM_strp && node->refcount > 0)
{
- switch_to_section (debug_str_section);
ASM_OUTPUT_LABEL (asm_out_file, node->label);
assemble_string (node->str, strlen (node->str) + 1);
}
@@ -22069,77 +22348,85 @@
return 1;
}
+/* Output the indexed string table. */
+
static void
-output_index_strings (void)
+output_indirect_strings (void)
{
- unsigned int i;
- unsigned int len = 0;
- struct indirect_string_node *node;
+ if (!dwarf_split_debug_info)
+ {
+ switch_to_section (debug_str_section);
+ htab_traverse (debug_str_hash, output_indirect_string, NULL);
+ }
+ else
+ {
+ unsigned int offset = 0;
+ unsigned int cur_idx = 0;
- if (VEC_empty (indirect_string_node, index_string_table))
- return;
+ switch_to_section (debug_str_offsets_section);
+ htab_traverse_noresize (debug_str_hash,
+ output_index_string_offset,
+ &offset);
+ switch_to_section (debug_str_section);
+ htab_traverse_noresize (debug_str_hash,
+ output_index_string,
+ &cur_idx);
+ }
+}
- switch_to_section (debug_str_offsets_section);
- for (i = 0; VEC_iterate (indirect_string_node, index_string_table, i, node);
- i++)
+/* Callback for htab_traverse to assign an index to an entry in the
+ table, and to write that entry to the .debug_addr section. */
+
+static int
+output_addr_table_entry (void **slot, void *data)
+{
+ addr_table_entry *entry = (addr_table_entry *) *slot;
+ unsigned int *cur_index = (unsigned int *)data;
+
+ if (entry->refcount == 0)
{
- gcc_assert (node->form == DW_FORM_GNU_str_index);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, len,
- "indexed string 0x%x: %s", i, node->str);
- len += strlen (node->str) + 1;
+ gcc_assert (entry->index == NO_INDEX_ASSIGNED
+ || entry->index == NOT_INDEXED);
+ return 1;
}
- switch_to_section (debug_str_section);
- for (i = 0; VEC_iterate (indirect_string_node, index_string_table, i, node);
- i++)
+
+ gcc_assert (entry->index == *cur_index);
+ (*cur_index)++;
+
+ switch (entry->kind)
{
- ASM_OUTPUT_LABEL (asm_out_file, node->label);
- assemble_string (node->str, strlen (node->str) + 1);
+ case ate_kind_rtx:
+ dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, entry->addr.rtl,
+ "0x%x", entry->index);
+ break;
+ case ate_kind_rtx_dtprel:
+ gcc_assert (targetm.asm_out.output_dwarf_dtprel);
+ targetm.asm_out.output_dwarf_dtprel (asm_out_file,
+ DWARF2_ADDR_SIZE,
+ entry->addr.rtl);
+ fputc ('\n', asm_out_file);
+ break;
+ case ate_kind_label:
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, entry->addr.label,
+ "0x%x", entry->index);
+ break;
+ default:
+ gcc_unreachable ();
}
+ return 1;
}
-/* Write the index table. */
+/* Produce the .debug_addr section. */
static void
output_addr_table (void)
{
- unsigned int i;
- dw_attr_node *node;
-
- if (VEC_empty (dw_attr_node, addr_index_table))
+ unsigned int index = 0;
+ if (addr_index_table == NULL || htab_size (addr_index_table) == 0)
return;
switch_to_section (debug_addr_section);
- for (i = 0; VEC_iterate (dw_attr_node, addr_index_table, i, node); i++)
- {
- const char *name;
-
- if (node->dw_attr == 0)
- {
- dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, "<Removed entry>");
- continue;
- }
-
- name = dwarf_attr_name (node->dw_attr);
- switch (AT_class (node))
- {
- case dw_val_class_addr:
- dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (node),
- "%s", name);
- break;
- case dw_val_class_loc:
- gcc_assert (targetm.asm_out.output_dwarf_dtprel);
- targetm.asm_out.output_dwarf_dtprel (asm_out_file,
- DWARF2_ADDR_SIZE,
- node->dw_attr_val.v.val_addr);
- fputc ('\n', asm_out_file);
- break;
- case dw_val_class_lbl_id:
- dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (node), "%s", name);
- break;
- default:
- gcc_unreachable ();
- }
- }
+ htab_traverse_noresize (addr_index_table, output_addr_table_entry, &index);
}
#if ENABLE_ASSERT_CHECKING
@@ -22749,11 +23036,10 @@
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
{
- unsigned int idx = loc->dw_loc_oprnd1.val_index;
- dw_attr_node *node = VEC_index (dw_attr_node, addr_index_table, idx);
if ((loc->dw_loc_opc == DW_OP_GNU_addr_index
|| (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel))
- && resolve_one_addr (&node->dw_attr_val.v.val_addr, NULL))
+ && resolve_one_addr (&loc->dw_loc_oprnd1.val_entry->addr.rtl,
+ NULL))
return false;
}
break;
@@ -22898,8 +23184,8 @@
gcc_assert (!next->ll_symbol);
next->ll_symbol = (*curr)->ll_symbol;
}
- if (dwarf_split_debug_info)
- remove_loc_list_addr_table_entries (l);
+ if (dwarf_split_debug_info)
+ remove_loc_list_addr_table_entries (l);
*curr = next;
}
else
@@ -22939,8 +23225,8 @@
|| l->dw_loc_next != NULL)
&& !resolve_addr_in_expr (l))
{
- if (dwarf_split_debug_info)
- remove_loc_list_addr_table_entries (l);
+ if (dwarf_split_debug_info)
+ remove_loc_list_addr_table_entries (l);
remove_AT (die, a->dw_attr);
ix--;
}
@@ -22952,8 +23238,8 @@
if (a->dw_attr == DW_AT_const_value
&& resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL))
{
- if (AT_index (a) != -1U)
- remove_addr_table_entry (AT_index (a));
+ if (AT_index (a) != NOT_INDEXED)
+ remove_addr_table_entry (a->dw_attr_val.val_entry);
remove_AT (die, a->dw_attr);
ix--;
}
@@ -22977,8 +23263,8 @@
}
else
{
- if (AT_index (a) != -1U)
- remove_addr_table_entry (AT_index (a));
+ if (AT_index (a) != NOT_INDEXED)
+ remove_addr_table_entry (a->dw_attr_val.val_entry);
remove_AT (die, a->dw_attr);
ix--;
}
@@ -23115,14 +23401,12 @@
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
{
- dw_attr_ref attr = VEC_index (dw_attr_node, addr_index_table,
- val1->val_index);
if (loc->dtprel)
- {
+ {
unsigned char dtprel = 0xd1;
hash = iterative_hash_object (dtprel, hash);
}
- hash = iterative_hash_rtx (attr->dw_attr_val.v.val_addr, hash);
+ hash = iterative_hash_rtx (val1->val_entry->addr.rtl, hash);
}
break;
case DW_OP_GNU_implicit_pointer:
@@ -23310,8 +23594,8 @@
can cause irrelevant differences in dw_loc_addr. */
gcc_assert (valx1->val_class == dw_val_class_loc
&& valy1->val_class == dw_val_class_loc
- && (dwarf_split_debug_info
- || x->dw_loc_addr == y->dw_loc_addr));
+ && (dwarf_split_debug_info
+ || x->dw_loc_addr == y->dw_loc_addr));
return valx1->v.val_loc->dw_loc_addr == valy1->v.val_loc->dw_loc_addr;
case DW_OP_implicit_value:
if (valx1->v.val_unsigned != valy1->v.val_unsigned
@@ -23345,14 +23629,9 @@
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
{
- dw_attr_node *attrx1 = VEC_index (dw_attr_node,
- addr_index_table,
- valx1->val_index);
- dw_attr_node *attry1 = VEC_index (dw_attr_node,
- addr_index_table,
- valy1->val_index);
- return rtx_equal_p (attrx1->dw_attr_val.v.val_addr,
- attry1->dw_attr_val.v.val_addr);
+ rtx ax1 = valx1->val_entry->addr.rtl;
+ rtx ay1 = valy1->val_entry->addr.rtl;
+ return rtx_equal_p (ax1, ay1);
}
case DW_OP_GNU_implicit_pointer:
return valx1->val_class == dw_val_class_die_ref
@@ -23502,19 +23781,15 @@
dw_loc_list_ref curr;
for (curr = list; curr != NULL; curr = curr->dw_loc_next)
{
- dw_attr_node attr;
-
/* Don't index an entry that has already been indexed
- or won't be output. */
- if (curr->begin_index != -1U
- || (strcmp (curr->begin, curr->end) == 0 && !curr->force))
- continue;
+ or won't be output. */
+ if (curr->begin_entry != NULL
+ || (strcmp (curr->begin, curr->end) == 0 && !curr->force))
+ continue;
- attr.dw_attr = DW_AT_location;
- attr.dw_attr_val.val_class = dw_val_class_lbl_id;
- attr.dw_attr_val.val_index = -1U;
- attr.dw_attr_val.v.val_lbl_id = xstrdup (curr->begin);
- curr->begin_index = add_addr_table_entry (&attr);
+ curr->begin_entry
+ = add_addr_table_entry (xstrdup (curr->begin),
+ ate_kind_label);
}
}
@@ -23760,11 +24035,26 @@
dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
macinfo_section_label);
+ if (dwarf_split_debug_info && addr_index_table != NULL)
+ {
+ /* optimize_location_lists calculates the size of the lists,
+ so index them first, and assign indices to the entries.
+ Although optimize_location_lists will remove entries from
+ the table, it only does so for duplicates, and therefore
+ only reduces ref_counts to 1. */
+ unsigned int index = 0;
+ index_location_lists (comp_unit_die ());
+ htab_traverse_noresize (addr_index_table,
+ index_addr_table_entry, &index);
+ }
if (have_location_lists)
+ optimize_location_lists (comp_unit_die ());
+
+ save_macinfo_strings ();
+ if (dwarf_split_debug_info)
{
- optimize_location_lists (comp_unit_die ());
- if (dwarf_split_debug_info)
- index_location_lists (comp_unit_die ());
+ unsigned int index = 0;
+ htab_traverse_noresize (debug_str_hash, index_string, &index);
}
/* Output all of the compilation units. We put the main one last so that
@@ -23795,6 +24085,10 @@
}
htab_delete (comdat_type_table);
+ /* The AT_pubnames attribute needs to go in all skeleton dies, including
+ both the main_cu and all skeleton TUs. Making this call unconditional
+ would end up either adding a second copy of the AT_pubnames attribute, or
+ requiring a special case in add_top_level_skeleton_die_attrs. */
if (!dwarf_split_debug_info)
add_AT_pubnames (comp_unit_die ());
@@ -23819,8 +24113,12 @@
/* Add the base offset of the ranges table to the skeleton
comp-unit DIE. */
if (ranges_table_in_use)
- add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
- ranges_section_label);
+ add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
+ ranges_section_label);
+
+ switch_to_section (debug_addr_section);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
+ output_addr_table ();
}
/* Output the main compilation unit if non-empty or if .debug_macinfo
@@ -23895,17 +24193,11 @@
switch_to_section (debug_skeleton_line_section);
ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
output_line_info (true);
-
- output_index_strings ();
-
- switch_to_section (debug_addr_section);
- ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
- output_addr_table ();
}
/* If we emitted any indirect strings, output the string table too. */
if (debug_str_hash)
- htab_traverse (debug_str_hash, output_indirect_string, NULL);
+ output_indirect_strings ();
}
#include "gt-dwarf2out.h"
===================================================================
@@ -167,12 +167,14 @@
}
dw_vec_const;
+struct addr_table_entry_struct;
+
/* The dw_val_node describes an attribute's value, as it is
represented internally. */
typedef struct GTY(()) dw_val_struct {
enum dw_val_class val_class;
- unsigned int val_index;
+ struct addr_table_entry_struct * GTY(()) val_entry;
union dw_val_struct_union
{
rtx GTY ((tag ("dw_val_class_addr"))) val_addr;