aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2009-12-14 16:55:12 +0000
committerJakub Jelinek <jakub@gcc.gnu.org>2009-12-14 17:55:12 +0100
commit23198957a2176cf80b4b33e17f77ab5e5dea4bfe (patch)
treedcda67d4f613a7e3844e5df9b0bbe883b6d92351 /gcc
parent20cdc2be22a6e32fd6a0fbedae32473e3698961a (diff)
downloadgcc-23198957a2176cf80b4b33e17f77ab5e5dea4bfe.zip
gcc-23198957a2176cf80b4b33e17f77ab5e5dea4bfe.tar.gz
gcc-23198957a2176cf80b4b33e17f77ab5e5dea4bfe.tar.bz2
re PR target/41473 (dsymutil "Assertion failed ...")
PR debug/41473 * dwarf2out.c (add_var_loc_to_decl): Don't drop initial empty locations. (new_loc_list): Drop gensym arg. Move generation of ll_symbol... (gen_llsym): ... here. New function. (add_loc_descr_to_loc_list): Removed. (loc_descriptor): Infer mode from CONST_DOUBLEs and CONST_VECTORs. (single_element_loc_list): Removed. (dw_loc_list): Don't create entries without a location. Don't special-case the first node of the list, only single nodes. (single_element_loc_list_p): Simplify. (loc_list_from_tree): Don't use DECL_RTL if loc_list is nonempty. (add_location_or_const_value_attribute): Test var loc for NULL. (convert_cfa_to_fb_loc_list): Adjust calls to new new_loc_list, call gen_llsym if needed. From-SVN: r155221
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/dwarf2out.c160
2 files changed, 93 insertions, 85 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1badea3..b1094a8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2009-12-14 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/41473
+ * dwarf2out.c (add_var_loc_to_decl): Don't drop initial empty
+ locations.
+ (new_loc_list): Drop gensym arg. Move generation of ll_symbol...
+ (gen_llsym): ... here. New function.
+ (add_loc_descr_to_loc_list): Removed.
+ (loc_descriptor): Infer mode from CONST_DOUBLEs and CONST_VECTORs.
+ (single_element_loc_list): Removed.
+ (dw_loc_list): Don't create entries without a location. Don't
+ special-case the first node of the list, only single nodes.
+ (single_element_loc_list_p): Simplify.
+ (loc_list_from_tree): Don't use DECL_RTL if loc_list is nonempty.
+ (add_location_or_const_value_attribute): Test var loc for NULL.
+ (convert_cfa_to_fb_loc_list): Adjust calls to new new_loc_list,
+ call gen_llsym if needed.
+
2009-12-14 Jakub Jelinek <jakub@redhat.com>
* cgraph.h (cgraph_set_nothrow_flag, cgraph_set_readonly_flag,
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ec5298c..971b191 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -6177,10 +6177,7 @@ static void gen_generic_params_dies (tree);
static void splice_child_die (dw_die_ref, dw_die_ref);
static int file_info_cmp (const void *, const void *);
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
- const char *, const char *, unsigned);
-static void add_loc_descr_to_loc_list (dw_loc_list_ref *, dw_loc_descr_ref,
- const char *, const char *,
- const char *);
+ const char *, const char *);
static void output_loc_list (dw_loc_list_ref);
static char *gen_internal_sym (const char *);
@@ -7793,8 +7790,7 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
temp->last = loc;
}
}
- /* Do not add empty location to the beginning of the list. */
- else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX)
+ else
{
temp->first = loc;
temp->last = loc;
@@ -10302,12 +10298,11 @@ output_die_symbol (dw_die_ref die)
}
/* Return a new location list, given the begin and end range, and the
- expression. gensym tells us whether to generate a new internal symbol for
- this location list node, which is done for the head of the list only. */
+ expression. */
static inline dw_loc_list_ref
new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
- const char *section, unsigned int gensym)
+ const char *section)
{
dw_loc_list_ref retlist = GGC_CNEW (dw_loc_list_node);
@@ -10315,27 +10310,18 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
retlist->end = end;
retlist->expr = expr;
retlist->section = section;
- if (gensym)
- retlist->ll_symbol = gen_internal_sym ("LLST");
return retlist;
}
-/* Add a location description expression to a location list. */
+/* Generate a new internal symbol for this location list node, if it
+ hasn't got one yet. */
static inline void
-add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr,
- const char *begin, const char *end,
- const char *section)
+gen_llsym (dw_loc_list_ref list)
{
- dw_loc_list_ref *d;
-
- /* Find the end of the chain. */
- for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
- ;
-
- /* Add a new location list node to the list. */
- *d = new_loc_list (descr, begin, end, section, 0);
+ gcc_assert (!list->ll_symbol);
+ list->ll_symbol = gen_internal_sym ("LLST");
}
/* Output the location list given to us. */
@@ -13653,15 +13639,17 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
break;
case CONST_DOUBLE:
+ if (mode == VOIDmode)
+ mode = GET_MODE (rtl);
+
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
{
+ gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
+
/* Note that a CONST_DOUBLE rtx could represent either an integer
or a floating-point constant. A CONST_DOUBLE is used whenever
the constant requires more than one word in order to be
adequately represented. We output CONST_DOUBLEs as blocks. */
- if (GET_MODE (rtl) != VOIDmode)
- mode = GET_MODE (rtl);
-
loc_result = new_loc_descr (DW_OP_implicit_value,
GET_MODE_SIZE (mode), 0);
if (SCALAR_FLOAT_MODE_P (mode))
@@ -13687,6 +13675,9 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
break;
case CONST_VECTOR:
+ if (mode == VOIDmode)
+ mode = GET_MODE (rtl);
+
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
{
unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
@@ -13695,7 +13686,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
unsigned int i;
unsigned char *p;
- mode = GET_MODE (rtl);
+ gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
switch (GET_MODE_CLASS (mode))
{
case MODE_VECTOR_INT:
@@ -13842,14 +13833,6 @@ decl_by_reference_p (tree decl)
&& DECL_BY_REFERENCE (decl));
}
-/* Return single element location list containing loc descr REF. */
-
-static dw_loc_list_ref
-single_element_loc_list (dw_loc_descr_ref ref)
-{
- return new_loc_list (ref, NULL, NULL, NULL, 0);
-}
-
/* Helper function for dw_loc_list. Compute proper Dwarf location descriptor
for VARLOC. */
@@ -13931,20 +13914,21 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
return descr;
}
-/* Return dwarf representation of location list representing for
- LOC_LIST of DECL. WANT_ADDRESS has the same meaning as in
- loc_list_from_tree function. */
+/* Return the dwarf representation of the location list LOC_LIST of
+ DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree
+ function. */
static dw_loc_list_ref
-dw_loc_list (var_loc_list * loc_list, tree decl, int want_address)
+dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
{
const char *endname, *secname;
- dw_loc_list_ref list;
rtx varloc;
enum var_init_status initialized;
struct var_loc_node *node;
dw_loc_descr_ref descr;
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
+ dw_loc_list_ref list = NULL;
+ dw_loc_list_ref *listp = &list;
/* Now that we know what section we are using for a base,
actually construct the list of locations.
@@ -13957,26 +13941,9 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address)
This means we have to special case the last node, and generate
a range of [last location start, end of function label]. */
- node = loc_list->first;
secname = secname_for_decl (decl);
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
- initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
- else
- initialized = VAR_INIT_STATUS_INITIALIZED;
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
-
- if (loc_list && loc_list->first != loc_list->last)
- list = new_loc_list (descr, node->label, node->next->label, secname, 1);
- else
- return single_element_loc_list (descr);
- node = node->next;
-
- if (!node)
- return NULL;
-
- for (; node->next; node = node->next)
+ for (node = loc_list->first; node->next; node = node->next)
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
{
/* The variable has a location between NODE->LABEL and
@@ -13984,28 +13951,46 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address)
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
- add_loc_descr_to_loc_list (&list, descr,
- node->label, node->next->label, secname);
+ if (descr)
+ {
+ *listp = new_loc_list (descr, node->label, node->next->label,
+ secname);
+ listp = &(*listp)->dw_loc_next;
+ }
}
/* If the variable has a location at the last label
it keeps its location until the end of function. */
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
{
- if (!current_function_decl)
- endname = text_end_label;
- else
- {
- ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
- current_function_funcdef_no);
- endname = ggc_strdup (label_id);
- }
-
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
- add_loc_descr_to_loc_list (&list, descr, node->label, endname, secname);
+ if (descr)
+ {
+ if (!current_function_decl)
+ endname = text_end_label;
+ else
+ {
+ ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+ current_function_funcdef_no);
+ endname = ggc_strdup (label_id);
+ }
+
+ *listp = new_loc_list (descr, node->label, endname, secname);
+ listp = &(*listp)->dw_loc_next;
+ }
}
+
+ /* Try to avoid the overhead of a location list emitting a location
+ expression instead, but only if we didn't have more than one
+ location entry in the first place. If some entries were not
+ representable, we don't want to pretend a single entry that was
+ applies to the entire scope in which the variable is
+ available. */
+ if (list && loc_list->first->next)
+ gen_llsym (list);
+
return list;
}
@@ -14015,7 +14000,8 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address)
static bool
single_element_loc_list_p (dw_loc_list_ref list)
{
- return (!list->dw_loc_next && !list->begin && !list->end);
+ gcc_assert (!list->dw_loc_next || list->ll_symbol);
+ return !list->ll_symbol;
}
/* To each location in list LIST add loc descr REF. */
@@ -14315,9 +14301,9 @@ loc_list_from_tree (tree loc, int want_address)
rtx rtl;
var_loc_list *loc_list = lookup_decl_loc (loc);
- if (loc_list && loc_list->first
- && (list_ret = dw_loc_list (loc_list, loc, want_address)))
+ if (loc_list && loc_list->first)
{
+ list_ret = dw_loc_list (loc_list, loc, want_address);
have_address = want_address != 0;
break;
}
@@ -14728,7 +14714,7 @@ loc_list_from_tree (tree loc, int want_address)
add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
}
if (ret)
- list_ret = single_element_loc_list (ret);
+ list_ret = new_loc_list (ret, NULL, NULL, NULL);
return list_ret;
}
@@ -15722,15 +15708,18 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
a constant value. That way we are better to use add_const_value_attribute
rather than expanding constant value equivalent. */
loc_list = lookup_decl_loc (decl);
- if (loc_list && loc_list->first && loc_list->first == loc_list->last)
+ if (loc_list
+ && loc_list->first
+ && loc_list->first == loc_list->last
+ && NOTE_VAR_LOCATION (loc_list->first->var_loc_note)
+ && NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note))
{
struct var_loc_node *node;
node = loc_list->first;
- rtl = NOTE_VAR_LOCATION (node->var_loc_note);
- if (GET_CODE (rtl) == VAR_LOCATION
- && GET_CODE (XEXP (rtl, 1)) != PARALLEL)
- rtl = XEXP (XEXP (rtl, 1), 0);
+ rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
+ if (GET_CODE (rtl) != PARALLEL)
+ rtl = XEXP (rtl, 0);
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
&& add_const_value_attribute (die, rtl))
return true;
@@ -16017,8 +16006,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
if (!cfa_equal_p (&last_cfa, &next_cfa))
{
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
- start_label, last_label, section,
- list == NULL);
+ start_label, last_label, section);
list_tail = &(*list_tail)->dw_loc_next;
last_cfa = next_cfa;
@@ -16039,14 +16027,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
if (!cfa_equal_p (&last_cfa, &next_cfa))
{
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
- start_label, last_label, section,
- list == NULL);
+ start_label, last_label, section);
list_tail = &(*list_tail)->dw_loc_next;
start_label = last_label;
}
+
*list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset),
- start_label, fde->dw_fde_end, section,
- list == NULL);
+ start_label, fde->dw_fde_end, section);
+
+ if (list && list->dw_loc_next)
+ gen_llsym (list);
return list;
}