aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2009-09-20 12:04:21 +0000
committerJan Hubicka <jh@suse.cz>2009-09-20 12:04:21 +0000
commita16ee61838b23b2830a74c499177a6d63fc8858e (patch)
tree55ab5f5feb7fa46dc52c03bf3c1614a6ac8f40b4
parent8dbfc621d9b2c23c193066fd38b6964c1a5868bc (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@151901 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/dwarf2out.c521
2 files changed, 317 insertions, 226 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 361484a7b2d..bb7dc70f283 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7202a8e22d0..19eabacfde9 100644
--- a/gcc/dwarf2out.c
+++ b/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