Commit 23198957 by Alexandre Oliva Committed by Jakub Jelinek

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
parent 20cdc2be
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> 2009-12-14 Jakub Jelinek <jakub@redhat.com>
* cgraph.h (cgraph_set_nothrow_flag, cgraph_set_readonly_flag, * cgraph.h (cgraph_set_nothrow_flag, cgraph_set_readonly_flag,
...@@ -6177,10 +6177,7 @@ static void gen_generic_params_dies (tree); ...@@ -6177,10 +6177,7 @@ static void gen_generic_params_dies (tree);
static void splice_child_die (dw_die_ref, dw_die_ref); static void splice_child_die (dw_die_ref, dw_die_ref);
static int file_info_cmp (const void *, const void *); static int file_info_cmp (const void *, const void *);
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
const char *, const char *, unsigned); const char *, const char *);
static void add_loc_descr_to_loc_list (dw_loc_list_ref *, dw_loc_descr_ref,
const char *, const char *,
const char *);
static void output_loc_list (dw_loc_list_ref); static void output_loc_list (dw_loc_list_ref);
static char *gen_internal_sym (const char *); static char *gen_internal_sym (const char *);
...@@ -7793,8 +7790,7 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc) ...@@ -7793,8 +7790,7 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
temp->last = loc; temp->last = loc;
} }
} }
/* Do not add empty location to the beginning of the list. */ else
else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX)
{ {
temp->first = loc; temp->first = loc;
temp->last = loc; temp->last = loc;
...@@ -10302,12 +10298,11 @@ output_die_symbol (dw_die_ref die) ...@@ -10302,12 +10298,11 @@ output_die_symbol (dw_die_ref die)
} }
/* Return a new location list, given the begin and end range, and the /* 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 expression. */
this location list node, which is done for the head of the list only. */
static inline dw_loc_list_ref static inline dw_loc_list_ref
new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, 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); 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, ...@@ -10315,27 +10310,18 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
retlist->end = end; retlist->end = end;
retlist->expr = expr; retlist->expr = expr;
retlist->section = section; retlist->section = section;
if (gensym)
retlist->ll_symbol = gen_internal_sym ("LLST");
return retlist; 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 static inline void
add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr, gen_llsym (dw_loc_list_ref list)
const char *begin, const char *end,
const char *section)
{ {
dw_loc_list_ref *d; gcc_assert (!list->ll_symbol);
list->ll_symbol = gen_internal_sym ("LLST");
/* 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);
} }
/* Output the location list given to us. */ /* Output the location list given to us. */
...@@ -13653,15 +13639,17 @@ loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -13653,15 +13639,17 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
break; break;
case CONST_DOUBLE: case CONST_DOUBLE:
if (mode == VOIDmode)
mode = GET_MODE (rtl);
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict)) 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 /* Note that a CONST_DOUBLE rtx could represent either an integer
or a floating-point constant. A CONST_DOUBLE is used whenever or a floating-point constant. A CONST_DOUBLE is used whenever
the constant requires more than one word in order to be the constant requires more than one word in order to be
adequately represented. We output CONST_DOUBLEs as blocks. */ 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, loc_result = new_loc_descr (DW_OP_implicit_value,
GET_MODE_SIZE (mode), 0); GET_MODE_SIZE (mode), 0);
if (SCALAR_FLOAT_MODE_P (mode)) if (SCALAR_FLOAT_MODE_P (mode))
...@@ -13687,6 +13675,9 @@ loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -13687,6 +13675,9 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
break; break;
case CONST_VECTOR: case CONST_VECTOR:
if (mode == VOIDmode)
mode = GET_MODE (rtl);
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict)) if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
{ {
unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl)); unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
...@@ -13695,7 +13686,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode, ...@@ -13695,7 +13686,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
unsigned int i; unsigned int i;
unsigned char *p; unsigned char *p;
mode = GET_MODE (rtl); gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
switch (GET_MODE_CLASS (mode)) switch (GET_MODE_CLASS (mode))
{ {
case MODE_VECTOR_INT: case MODE_VECTOR_INT:
...@@ -13842,14 +13833,6 @@ decl_by_reference_p (tree decl) ...@@ -13842,14 +13833,6 @@ decl_by_reference_p (tree decl)
&& DECL_BY_REFERENCE (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 /* Helper function for dw_loc_list. Compute proper Dwarf location descriptor
for VARLOC. */ for VARLOC. */
...@@ -13931,20 +13914,21 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address, ...@@ -13931,20 +13914,21 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
return descr; return descr;
} }
/* Return dwarf representation of location list representing for /* Return the dwarf representation of the location list LOC_LIST of
LOC_LIST of DECL. WANT_ADDRESS has the same meaning as in DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree
loc_list_from_tree function. */ function. */
static dw_loc_list_ref 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; const char *endname, *secname;
dw_loc_list_ref list;
rtx varloc; rtx varloc;
enum var_init_status initialized; enum var_init_status initialized;
struct var_loc_node *node; struct var_loc_node *node;
dw_loc_descr_ref descr; dw_loc_descr_ref descr;
char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 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, /* Now that we know what section we are using for a base,
actually construct the list of locations. actually construct the list of locations.
...@@ -13957,26 +13941,9 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) ...@@ -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 This means we have to special case the last node, and generate
a range of [last location start, end of function label]. */ a range of [last location start, end of function label]. */
node = loc_list->first;
secname = secname_for_decl (decl); secname = secname_for_decl (decl);
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note)) for (node = loc_list->first; node->next; node = node->next)
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)
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX) if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
{ {
/* The variable has a location between NODE->LABEL and /* 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) ...@@ -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); initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note); varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized); descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
add_loc_descr_to_loc_list (&list, descr, if (descr)
node->label, node->next->label, secname); {
*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 /* If the variable has a location at the last label
it keeps its location until the end of function. */ it keeps its location until the end of function. */
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX) 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); initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note); varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized); 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; return list;
} }
...@@ -14015,7 +14000,8 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) ...@@ -14015,7 +14000,8 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address)
static bool static bool
single_element_loc_list_p (dw_loc_list_ref list) 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. */ /* To each location in list LIST add loc descr REF. */
...@@ -14315,9 +14301,9 @@ loc_list_from_tree (tree loc, int want_address) ...@@ -14315,9 +14301,9 @@ loc_list_from_tree (tree loc, int want_address)
rtx rtl; rtx rtl;
var_loc_list *loc_list = lookup_decl_loc (loc); var_loc_list *loc_list = lookup_decl_loc (loc);
if (loc_list && loc_list->first if (loc_list && loc_list->first)
&& (list_ret = dw_loc_list (loc_list, loc, want_address)))
{ {
list_ret = dw_loc_list (loc_list, loc, want_address);
have_address = want_address != 0; have_address = want_address != 0;
break; break;
} }
...@@ -14728,7 +14714,7 @@ loc_list_from_tree (tree loc, int want_address) ...@@ -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)); add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
} }
if (ret) if (ret)
list_ret = single_element_loc_list (ret); list_ret = new_loc_list (ret, NULL, NULL, NULL);
return list_ret; return list_ret;
} }
...@@ -15722,15 +15708,18 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -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 a constant value. That way we are better to use add_const_value_attribute
rather than expanding constant value equivalent. */ rather than expanding constant value equivalent. */
loc_list = lookup_decl_loc (decl); 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; struct var_loc_node *node;
node = loc_list->first; node = loc_list->first;
rtl = NOTE_VAR_LOCATION (node->var_loc_note); rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
if (GET_CODE (rtl) == VAR_LOCATION if (GET_CODE (rtl) != PARALLEL)
&& GET_CODE (XEXP (rtl, 1)) != PARALLEL) rtl = XEXP (rtl, 0);
rtl = XEXP (XEXP (rtl, 1), 0);
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING) if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
&& add_const_value_attribute (die, rtl)) && add_const_value_attribute (die, rtl))
return true; return true;
...@@ -16017,8 +16006,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) ...@@ -16017,8 +16006,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
if (!cfa_equal_p (&last_cfa, &next_cfa)) if (!cfa_equal_p (&last_cfa, &next_cfa))
{ {
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
start_label, last_label, section, start_label, last_label, section);
list == NULL);
list_tail = &(*list_tail)->dw_loc_next; list_tail = &(*list_tail)->dw_loc_next;
last_cfa = next_cfa; last_cfa = next_cfa;
...@@ -16039,14 +16027,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) ...@@ -16039,14 +16027,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
if (!cfa_equal_p (&last_cfa, &next_cfa)) if (!cfa_equal_p (&last_cfa, &next_cfa))
{ {
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
start_label, last_label, section, start_label, last_label, section);
list == NULL);
list_tail = &(*list_tail)->dw_loc_next; list_tail = &(*list_tail)->dw_loc_next;
start_label = last_label; start_label = last_label;
} }
*list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset), *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset),
start_label, fde->dw_fde_end, section, start_label, fde->dw_fde_end, section);
list == NULL);
if (list && list->dw_loc_next)
gen_llsym (list);
return list; return list;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment