dwarf2out.c (add_const_value_attribute): Return true if successful.

* dwarf2out.c (add_const_value_attribute): Return true if successful.
	(add_location_or_const_value_attribute): Rewrite using loc_list_from_tree.
	(tree_add_const_value_attribute): Return true if successful.
	(tree_add_const_value_attribute_for_decl): Likewise.

	* dwarf2out.c (address_of_int_loc_descriptor): Break out from ...
	(loc_descriptor): ... here;
	(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
	(cst_pool_loc_descr): Break out from ...; do not reffer constant
	pool items that was not marked for output.
	(loc_list_from_tree): ... here; handle special cases of ADDR_EXPR;
	(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
	(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
	handle ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF, REALPART_EXPR,
	IMAGPART_EXPR; handle address of INTEGER_CST; improve handling of
	CONSTRUCTOR; handle REAL_CST, STRING_CST, COMPLEX_CST; use
	DW_OP_stack_value to get address of items that are not available
	as addresses.
	(dw_loc_list): Handle single element lists correctly.

From-SVN: r151901
This commit is contained in:
Jan Hubicka 2009-09-20 14:04:21 +02:00 committed by Jan Hubicka
parent 0b1d7060b5
commit c4a80a2df3
2 changed files with 317 additions and 226 deletions

View file

@ -1,3 +1,25 @@
2009-09-20 Jan Hubicka <jh@suse.cz>
* dwarf2out.c (add_const_value_attribute): Return true if successful.
(add_location_or_const_value_attribute): Rewrite using loc_list_from_tree.
(tree_add_const_value_attribute): Return true if successful.
(tree_add_const_value_attribute_for_decl): Likewise.
* dwarf2out.c (address_of_int_loc_descriptor): Break out from ...
(loc_descriptor): ... here;
(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
(cst_pool_loc_descr): Break out from ...; do not reffer constant
pool items that was not marked for output.
(loc_list_from_tree): ... here; handle special cases of ADDR_EXPR;
(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
(loc_list_for_address_of_addr_expr_of_indirect_ref): New function.
handle ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF, REALPART_EXPR,
IMAGPART_EXPR; handle address of INTEGER_CST; improve handling of
CONSTRUCTOR; handle REAL_CST, STRING_CST, COMPLEX_CST; use
DW_OP_stack_value to get address of items that are not available
as addresses.
(dw_loc_list): Handle single element lists correctly.
2009-09-20 Kai Tietz <kai.tietz@onevision.com>
Pascal Obry <obry@adacore.com>

View file

@ -5961,14 +5961,14 @@ static HOST_WIDE_INT field_byte_offset (const_tree);
static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
dw_loc_list_ref);
static void add_data_member_location_attribute (dw_die_ref, tree);
static void add_const_value_attribute (dw_die_ref, rtx);
static bool add_const_value_attribute (dw_die_ref, rtx);
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
static void add_location_or_const_value_attribute (dw_die_ref, tree,
static bool add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute);
static void tree_add_const_value_attribute (dw_die_ref, tree);
static void tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static bool tree_add_const_value_attribute (dw_die_ref, tree);
static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
@ -10882,6 +10882,64 @@ int_loc_descriptor (HOST_WIDE_INT i)
return new_loc_descr (op, i, 0);
}
/* Return loc description representing "address" of integer value.
This can appear only as toplevel expression. */
static dw_loc_descr_ref
address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
{
int litsize;
dw_loc_descr_ref loc_result = NULL;
if (i >= 0)
{
if (i <= 31)
litsize = 1;
else if (i <= 0xff)
litsize = 2;
else if (i <= 0xffff)
litsize = 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i <= 0xffffffff)
litsize = 5;
else
litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
}
else
{
if (i >= -0x80)
litsize = 2;
else if (i >= -0x8000)
litsize = 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i >= -0x80000000)
litsize = 5;
else
litsize = 1 + size_of_sleb128 (i);
}
/* Determine if DW_OP_stack_value or DW_OP_implicit_value
is more compact. For DW_OP_stack_value we need:
litsize + 1 (DW_OP_stack_value) + 1 (DW_OP_bit_size)
+ 1 (mode size)
and for DW_OP_implicit_value:
1 (DW_OP_implicit_value) + 1 (length) + mode_size. */
if (DWARF2_ADDR_SIZE >= size
&& litsize + 1 + 1 + 1 < 1 + 1 + size)
{
loc_result = int_loc_descriptor (i);
add_loc_descr (&loc_result,
new_loc_descr (DW_OP_stack_value, 0, 0));
add_loc_descr_op_piece (&loc_result, size);
return loc_result;
}
loc_result = new_loc_descr (DW_OP_implicit_value,
size, 0);
loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
loc_result->dw_loc_oprnd2.v.val_int = i;
return loc_result;
}
#endif
#ifdef DWARF2_DEBUGGING_INFO
@ -11778,56 +11836,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
case CONST_INT:
if (mode != VOIDmode && mode != BLKmode)
{
HOST_WIDE_INT i = INTVAL (rtl);
int litsize;
if (i >= 0)
{
if (i <= 31)
litsize = 1;
else if (i <= 0xff)
litsize = 2;
else if (i <= 0xffff)
litsize = 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i <= 0xffffffff)
litsize = 5;
else
litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
}
else
{
if (i >= -0x80)
litsize = 2;
else if (i >= -0x8000)
litsize = 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i >= -0x80000000)
litsize = 5;
else
litsize = 1 + size_of_sleb128 (i);
}
/* Determine if DW_OP_stack_value or DW_OP_implicit_value
is more compact. For DW_OP_stack_value we need:
litsize + 1 (DW_OP_stack_value) + 1 (DW_OP_bit_size)
+ 1 (mode size)
and for DW_OP_implicit_value:
1 (DW_OP_implicit_value) + 1 (length) + mode_size. */
if (DWARF2_ADDR_SIZE >= GET_MODE_SIZE (mode)
&& litsize + 1 + 1 + 1 < 1 + 1 + GET_MODE_SIZE (mode))
{
loc_result = int_loc_descriptor (i);
add_loc_descr (&loc_result,
new_loc_descr (DW_OP_stack_value, 0, 0));
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
return loc_result;
}
loc_result = new_loc_descr (DW_OP_implicit_value,
GET_MODE_SIZE (mode), 0);
loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
loc_result->dw_loc_oprnd2.v.val_int = i;
}
loc_result = address_of_int_loc_descriptor (GET_MODE_SIZE (mode),
INTVAL (rtl));
break;
case CONST_DOUBLE:
@ -12071,6 +12081,14 @@ loc_by_reference (dw_loc_descr_ref loc, tree decl)
return loc;
}
/* 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);
}
/* Return dwarf representation of location list representing for
LOC_LIST of DECL. */
@ -12122,15 +12140,10 @@ dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
else
descr = loc_descriptor (varloc, DECL_MODE (decl), initialized);
if (!current_function_decl)
endname = text_end_label;
if (loc_list && loc_list->first != loc_list->last)
list = new_loc_list (descr, node->label, node->next->label, secname, 1);
else
{
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
current_function_funcdef_no);
endname = ggc_strdup (label_id);
}
list = new_loc_list (descr, node->label, node->next ? node->next->label : endname, secname, 1);
return single_element_loc_list (descr);
node = node->next;
if (!node)
@ -12168,6 +12181,15 @@ dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
enum var_init_status initialized =
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
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);
}
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
if (!toplevel || by_reference)
{
@ -12187,14 +12209,6 @@ dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
return list;
}
/* 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);
}
/* Return if the loc_list has only single element and thus can be represented
as location description. */
@ -12267,6 +12281,105 @@ add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list)
return;
}
/* LOC is constant expression. Try a luck, look it up in constant
pool and return its loc_descr of its address. */
static dw_loc_descr_ref
cst_pool_loc_descr (tree loc)
{
/* Get an RTL for this, if something has been emitted. */
rtx rtl = lookup_constant_def (loc);
enum machine_mode mode;
if (!rtl || !MEM_P (rtl))
{
gcc_assert (!rtl);
return 0;
}
gcc_assert (GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF);
/* TODO: We might get more coverage if we was actually delaying expansion
of all expressions till end of compilation when constant pools are fully
populated. */
if (!TREE_ASM_WRITTEN (SYMBOL_REF_DECL (XEXP (rtl, 0))))
{
expansion_failed (loc, NULL_RTX,
"CST value in contant pool but not marked.");
return 0;
}
mode = GET_MODE (rtl);
rtl = XEXP (rtl, 0);
return mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
}
/* Return dw_loc_list representing address of addr_expr LOC
by looking for innder INDIRECT_REF expression and turing it
into simple arithmetics. */
static dw_loc_list_ref
loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
enum machine_mode mode;
int volatilep;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
obj = get_inner_reference (TREE_OPERAND (loc, 0),
&bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
STRIP_NOPS (obj);
if (bitpos % BITS_PER_UNIT)
{
expansion_failed (loc, NULL_RTX, "bitfield access");
return 0;
}
if (!INDIRECT_REF_P (obj))
{
expansion_failed (obj,
NULL_RTX, "no indirect ref in inner refrence");
return 0;
}
if (!offset && !bitpos)
list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
else if (toplev
&& int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE)
{
list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
if (!list_ret)
return 0;
if (offset)
{
/* Variable offset. */
list_ret1 = loc_list_from_tree (offset, 0);
if (list_ret1 == 0)
return 0;
add_loc_list (&list_ret, list_ret1);
if (!list_ret)
return 0;
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_plus, 0, 0));
}
bytepos = bitpos / BITS_PER_UNIT;
if (bytepos > 0)
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_plus_uconst,
bytepos, 0));
else if (bytepos < 0)
loc_list_plus_const (list_ret, bytepos);
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_stack_value, 0, 0));
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_piece,
int_size_in_bytes (TREE_TYPE
(loc)),
0));
}
return list_ret;
}
/* Generate Dwarf location list representing LOC.
If WANT_ADDRESS is false, expression computing LOC will be computed
If WANT_ADDRESS is 1, expression computing address of LOC will be returned
@ -12318,15 +12431,28 @@ loc_list_from_tree (tree loc, int want_address)
return 0;
case ADDR_EXPR:
/* If we already want an address, there's nothing we can do. */
/* If we already want an address, see if there is INDIRECT_REF inside
e.g. for &this->field. */
if (want_address)
{
expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
return 0;
list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
(loc, want_address == 2);
if (list_ret)
have_address = 1;
else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
&& (ret = cst_pool_loc_descr (loc)))
have_address = 1;
}
/* Otherwise, process the argument and look for the address. */
return loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
/* Otherwise, process the argument and look for the address. */
if (!list_ret && !ret)
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
else
{
if (want_address)
expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
return NULL;
}
break;
case VAR_DECL:
if (DECL_THREAD_LOCAL_P (loc))
@ -12387,7 +12513,7 @@ loc_list_from_tree (tree loc, int want_address)
case PARM_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
want_address);
want_address);
/* FALLTHRU */
case RESULT_DECL:
@ -12451,6 +12577,8 @@ loc_list_from_tree (tree loc, int want_address)
break;
case INDIRECT_REF:
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
have_address = 1;
break;
@ -12468,6 +12596,8 @@ loc_list_from_tree (tree loc, int want_address)
case BIT_FIELD_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
@ -12480,7 +12610,11 @@ loc_list_from_tree (tree loc, int want_address)
gcc_assert (obj != loc);
list_ret = loc_list_from_tree (obj, 1);
list_ret = loc_list_from_tree (obj,
want_address == 2
&& !bitpos && !offset ? 2 : 1);
/* TODO: We can extract value of the small expression via shifting even
for nonzero bitpos. */
if (list_ret == 0)
return 0;
if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
@ -12513,7 +12647,16 @@ loc_list_from_tree (tree loc, int want_address)
}
case INTEGER_CST:
if (host_integerp (loc, 0))
if ((want_address || !host_integerp (loc, 0))
&& (ret = cst_pool_loc_descr (loc)))
have_address = 1;
else if (want_address == 2
&& host_integerp (loc, 0)
&& (ret = address_of_int_loc_descriptor
(int_size_in_bytes (TREE_TYPE (loc)),
tree_low_cst (loc, 0))))
have_address = 1;
else if (host_integerp (loc, 0))
ret = int_loc_descriptor (tree_low_cst (loc, 0));
else
{
@ -12524,19 +12667,16 @@ loc_list_from_tree (tree loc, int want_address)
break;
case CONSTRUCTOR:
{
/* Get an RTL for this, if something has been emitted. */
rtx rtl = lookup_constant_def (loc);
enum machine_mode mode;
if (!rtl || !MEM_P (rtl))
return 0;
mode = GET_MODE (rtl);
rtl = XEXP (rtl, 0);
ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
if ((ret = cst_pool_loc_descr (loc)))
have_address = 1;
break;
}
else
/* We can construct small constants here using int_loc_descriptor. */
expansion_failed (loc, NULL_RTX,
"constructor or constant not in constant pool");
break;
case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
@ -12743,6 +12883,23 @@ loc_list_from_tree (tree loc, int want_address)
if (!ret && !list_ret)
return 0;
if (want_address == 2 && !have_address)
{
if (int_size_in_bytes (TREE_TYPE (loc)) > DWARF2_ADDR_SIZE)
{
expansion_failed (loc, NULL_RTX,
"DWARF address size mismatch");
return 0;
}
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_stack_value, 0, 0));
add_loc_descr_to_each (list_ret,
new_loc_descr (DW_OP_piece,
int_size_in_bytes (TREE_TYPE
(loc)),
0));
have_address = 1;
}
/* Show if we can't fill the request for an address. */
if (want_address && !have_address)
{
@ -13170,7 +13327,7 @@ insert_float (const_rtx rtl, unsigned char *array)
to an inlined function. They can also arise in C++ where declared
constants do not necessarily get memory "homes". */
static void
static bool
add_const_value_attribute (dw_die_ref die, rtx rtl)
{
switch (GET_CODE (rtl))
@ -13184,7 +13341,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
else
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
}
break;
return true;
case CONST_DOUBLE:
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
@ -13205,7 +13362,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
else
add_AT_long_long (die, DW_AT_const_value, rtl);
}
break;
return true;
case CONST_VECTOR:
{
@ -13273,27 +13430,27 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
}
break;
return true;
case CONST_STRING:
add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0));
break;
return true;
case CONST:
if (CONSTANT_P (XEXP (rtl, 0)))
{
add_const_value_attribute (die, XEXP (rtl, 0));
return;
return true;
}
/* FALLTHROUGH */
case SYMBOL_REF:
if (GET_CODE (rtl) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
break;
return false;
case LABEL_REF:
add_AT_addr (die, DW_AT_const_value, rtl);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
break;
return true;
case PLUS:
/* In cases where an inlined instance of an inline function is passed
@ -13307,13 +13464,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
*value* which the artificial local variable always has during its
lifetime. We currently have no way to represent such quasi-constant
values in Dwarf, so for now we just punt and generate nothing. */
break;
return false;
default:
/* No other kinds of rtx should be possible here. */
gcc_unreachable ();
}
return false;
}
/* Determine whether the evaluation of EXPR references any variables
@ -13706,151 +13863,56 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
pointer. This can happen for example if an actual argument in an inlined
function call evaluates to a compile-time constant address. */
static void
static bool
add_location_or_const_value_attribute (dw_die_ref die, tree decl,
enum dwarf_attribute attr)
{
rtx rtl;
dw_loc_descr_ref descr;
dw_loc_list_ref descr_list;
dw_loc_list_ref list;
var_loc_list *loc_list;
struct var_loc_node *node;
if (TREE_CODE (decl) == ERROR_MARK)
return;
return false;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
/* See if we possibly have multiple locations for this variable. */
loc_list = lookup_decl_loc (decl);
/* If it truly has multiple locations, the first and last node will
differ. */
if (loc_list && loc_list->first != loc_list->last)
{
const char *endname, *secname;
dw_loc_list_ref list;
rtx varloc;
enum var_init_status initialized;
/* Now that we know what section we are using for a base,
actually construct the list of locations.
The first location information is what is passed to the
function that creates the location list, and the remaining
locations just get added on to that list.
Note that we only know the start address for a location
(IE location changes), so to build the range, we use
the range [current location start, next location start].
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;
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
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;
descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
initialized), decl);
list = new_loc_list (descr, node->label, node->next->label, secname, 1);
node = node->next;
for (; 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
NODE->NEXT->LABEL. */
enum var_init_status initialized =
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
initialized), decl);
add_loc_descr_to_loc_list (&list, descr,
node->label, node->next->label, secname);
}
/* 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)
{
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
enum var_init_status initialized =
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
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);
}
descr = loc_by_reference (loc_descriptor (varloc,
DECL_MODE (decl),
initialized),
decl);
add_loc_descr_to_loc_list (&list, descr,
node->label, endname, secname);
}
/* Finally, add the location list to the DIE, and we are done. */
add_AT_loc_list (die, attr, list);
return;
}
/* Try to get some constant RTL for this decl, and use that as the value of
the location. */
rtl = rtl_for_decl_location (decl);
if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
{
add_const_value_attribute (die, rtl);
return;
}
if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
&& add_const_value_attribute (die, rtl))
return true;
/* If we have tried to generate the location otherwise, and it
didn't work out (we wouldn't be here if we did), and we have a one entry
location list, try generating a location from that. */
if (loc_list && loc_list->first)
/* See if we have single element location list that is equivalent to
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)
{
enum var_init_status status;
struct var_loc_node *node;
node = loc_list->first;
status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
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);
if (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
{
add_const_value_attribute (die, rtl);
return;
}
descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note),
DECL_MODE (decl), status);
if (descr)
{
descr = loc_by_reference (descr, decl);
add_AT_location_description (die, attr, single_element_loc_list (descr));
return;
}
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
&& add_const_value_attribute (die, rtl))
return true;
}
/* We couldn't get any rtl, so try directly generating the location
description from the tree. */
descr_list = loc_list_from_tree (decl, 2);
if (descr_list)
list = loc_list_from_tree (decl, 2);
if (list)
{
descr = loc_by_reference (descr, decl);
add_AT_location_description (die, attr, descr_list);
return;
add_AT_location_description (die, attr, list);
return true;
}
/* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */
tree_add_const_value_attribute_for_decl (die, decl);
return tree_add_const_value_attribute_for_decl (die, decl);
}
/* Add VARIABLE and DIE into deferred locations list. */
@ -14014,7 +14076,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
/* Attach a DW_AT_const_value attribute to DIE. The value of the
attribute is the const value T. */
static void
static bool
tree_add_const_value_attribute (dw_die_ref die, tree t)
{
tree init;
@ -14022,14 +14084,17 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
rtx rtl;
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
return;
return false;
init = t;
gcc_assert (!DECL_P (init));
rtl = rtl_for_decl_init (init, type);
if (rtl)
add_const_value_attribute (die, rtl);
{
add_const_value_attribute (die, rtl);
return true;
}
/* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type))
@ -14040,9 +14105,13 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, size))
add_AT_vec (die, DW_AT_const_value, size, 1, array);
{
add_AT_vec (die, DW_AT_const_value, size, 1, array);
return true;
}
}
}
return false;
}
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
@ -14050,23 +14119,23 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
variable with static storage duration
(so it can't be a PARM_DECL or a RESULT_DECL). */
static void
static bool
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
{
if (!decl
|| (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != CONST_DECL))
return;
return false;
if (TREE_READONLY (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl))
/* OK */;
else
return;
return false;
tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
return tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
}
/* Convert the CFI instructions for the current function into a