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
This commit is contained in:
Alexandre Oliva 2009-12-14 16:55:12 +00:00 committed by Jakub Jelinek
parent 20cdc2be22
commit 23198957a2
2 changed files with 93 additions and 85 deletions

View File

@ -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,

View File

@ -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;
}