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:
parent
0b1d7060b5
commit
c4a80a2df3
2 changed files with 317 additions and 226 deletions
|
@ -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>
|
||||
|
||||
|
|
521
gcc/dwarf2out.c
521
gcc/dwarf2out.c
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue