This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: dwarf2out tree expression expansion improvements
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Jan Hubicka <hubicka at ucw dot cz>
- Cc: gcc-patches at gcc dot gnu dot org, jakub at redhat dot com, aoliva at redhat dot com, rguenther at suse dot de, martinj at suse dot de
- Date: Mon, 7 Sep 2009 17:39:06 +0200
- Subject: Re: dwarf2out tree expression expansion improvements
- References: <20090830172002.GA29914@kam.mff.cuni.cz>
Hi,
this is updated patch that applies post VTA merge.
Alexandre, most of merging was trivial, only non-trivial change was
needed to dw_loc_list that is essentially code broken out of
add_location_or_const_value_attribute. I hope I backported everything
correctly, but it would be nice if you could check.
Honza
* dwarf2out.c (loc_list_plus_const): New function.
(loc_descriptor_from_tree_1): Rename to ...
(loc_descriptor_from_tree): ... remove original.
(loc_list_from_tree): New function.
(add_AT_location_description): Accept location list.
(tls_mem_loc_descriptor): Update call of loc_descriptor_from_tree.
(mem_loc_descriptor): Handle CONCAT and VAR_LOCATION.
(secname_for_decl): Move up.
(hidden_reference_p): New function; break out from ...
(loc_by_refernece): ... here; move up.
(dw_loc_list): New function.
(single_element_loc_list): New function.
(single_element_loc_list_p): New function.
(add_loc_descr_to_each): New function.
(add_loc_list): New function.
(loc_descr_from_tree): Make wraper of loc_list_from_tree.
(loc_list_from_tree): Reroganized from loc_descr_from_tree;
add diagnostics why expansion failed.
(add_location_or_const_value_attribute): Support location lists.
(add_bound_info): Likewise.
(descr_info_loc): Update call of loc_descriptor_from_tree.
(gen_variable_die): Work on location lists.
Index: dwarf2out.c
===================================================================
*** dwarf2out.c (revision 151325)
--- dwarf2out.c (working copy)
*************** along with GCC; see the file COPYING3.
*** 89,94 ****
--- 89,95 ----
#include "hashtab.h"
#include "cgraph.h"
#include "input.h"
+ #include "gimple.h"
#ifdef DWARF2_DEBUGGING_INFO
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
*************** loc_descr_plus_const (dw_loc_descr_ref *
*** 4633,4638 ****
--- 4634,4649 ----
}
}
+ /* Add a constant OFFSET to a location list. */
+
+ static void
+ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
+ {
+ dw_loc_list_ref d;
+ for (d = list_head; d != NULL; d = d->dw_loc_next)
+ loc_descr_plus_const (&d->expr, offset);
+ }
+
/* Return the size of a location descriptor. */
static unsigned long
*************** static dw_loc_descr_ref concat_loc_descr
*** 5916,5923 ****
enum var_init_status);
static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
enum var_init_status);
! static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
! static dw_loc_descr_ref loc_descriptor_from_tree (tree);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
static tree field_type (const_tree);
static unsigned int simple_type_align_in_bits (const_tree);
--- 5927,5934 ----
enum var_init_status);
static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
enum var_init_status);
! static dw_loc_list_ref loc_list_from_tree (tree, int);
! static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
static tree field_type (const_tree);
static unsigned int simple_type_align_in_bits (const_tree);
*************** static unsigned int simple_decl_align_in
*** 5925,5931 ****
static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
static HOST_WIDE_INT field_byte_offset (const_tree);
static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
! dw_loc_descr_ref);
static void add_data_member_location_attribute (dw_die_ref, tree);
static void add_const_value_attribute (dw_die_ref, rtx);
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
--- 5936,5942 ----
static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
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 void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
*************** tls_mem_loc_descriptor (rtx mem)
*** 10984,10990 ****
|| !DECL_THREAD_LOCAL_P (base))
return NULL;
! loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
if (loc_result == NULL)
return NULL;
--- 10995,11001 ----
|| !DECL_THREAD_LOCAL_P (base))
return NULL;
! loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 2);
if (loc_result == NULL)
return NULL;
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 11171,11176 ****
--- 11182,11203 ----
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
break;
+ case CONCAT:
+ {
+ rtx x0 = XEXP (rtl, 0);
+ rtx x1 = XEXP (rtl, 1);
+ dw_loc_descr_ref x0_ref = mem_loc_descriptor (x0, GET_MODE (x0), VAR_INIT_STATUS_INITIALIZED);
+ dw_loc_descr_ref x1_ref = mem_loc_descriptor (x1, GET_MODE (x1), VAR_INIT_STATUS_INITIALIZED);
+ if (x0_ref == 0 || x1_ref == 0)
+ return 0;
+ mem_loc_result = x0_ref;
+ add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
+
+ add_loc_descr (&mem_loc_result, x1_ref);
+ add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
+ }
+ break;
+
case PRE_MODIFY:
/* Extract the PLUS expression nested inside and fall into
PLUS code below. */
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 11305,11310 ****
--- 11332,11352 ----
VAR_INIT_STATUS_INITIALIZED);
break;
+ case VAR_LOCATION:
+ if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
+ {
+ mem_loc_result = mem_loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode, initialized);
+ break;
+ }
+ /* TODO: We can handle this case via OP_piece of dwarf stack machine operatoins.
+ It should not be common case however. */
+ if (dump_file)
+ {
+ fprintf (stderr, "Multipart value can not be used in value expression.\n");
+ }
+ return 0;
+ break;
+
case EQ:
op = DW_OP_eq;
goto do_scompare;
*************** loc_descriptor (rtx rtl, enum machine_mo
*** 11948,11963 ****
return loc_result;
}
! /* Similar, but generate the descriptor from trees instead of rtl. This comes
! up particularly with variable length arrays. WANT_ADDRESS is 2 if this is
! a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a
! top-level invocation, and we require the address of LOC; is 0 if we require
! the value of LOC. */
static dw_loc_descr_ref
! loc_descriptor_from_tree_1 (tree loc, int want_address)
{
! dw_loc_descr_ref ret, ret1;
int have_address = 0;
enum dwarf_location_atom op;
--- 11990,12270 ----
return loc_result;
}
! /* We need to figure out what section we should use as the base for the
! address ranges where a given location is valid.
! 1. If this particular DECL has a section associated with it, use that.
! 2. If this function has a section associated with it, use that.
! 3. Otherwise, use the text section.
! XXX: If you split a variable across multiple sections, we won't notice. */
!
! static const char *
! secname_for_decl (const_tree decl)
! {
! const char *secname;
!
! if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
! {
! tree sectree = DECL_SECTION_NAME (decl);
! secname = TREE_STRING_POINTER (sectree);
! }
! else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
! {
! tree sectree = DECL_SECTION_NAME (current_function_decl);
! secname = TREE_STRING_POINTER (sectree);
! }
! else if (cfun && in_cold_section_p)
! secname = crtl->subsections.cold_section_label;
! else
! secname = text_section_label;
!
! return secname;
! }
!
! static bool
! hidden_reference_p (tree decl)
! {
! return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL
! || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)))
! && DECL_BY_REFERENCE (decl));
! }
!
! /* Dereference a location expression LOC if DECL is passed by invisible
! reference. */
static dw_loc_descr_ref
! loc_by_reference (dw_loc_descr_ref loc, tree decl)
! {
! HOST_WIDE_INT size;
! enum dwarf_location_atom op;
!
! if (loc == NULL)
! return NULL;
!
! if (!hidden_reference_p (decl))
! return loc;
!
! /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
! change it into corresponding DW_OP_breg{0...31,x} 0. Then the
! location expression is considered to be address of a memory location,
! rather than the register itself. */
! if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
! || loc->dw_loc_opc == DW_OP_regx)
! && (loc->dw_loc_next == NULL
! || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
! && loc->dw_loc_next->dw_loc_next == NULL)))
! {
! if (loc->dw_loc_opc == DW_OP_regx)
! {
! loc->dw_loc_opc = DW_OP_bregx;
! loc->dw_loc_oprnd2.v.val_int = 0;
! }
! else
! {
! loc->dw_loc_opc
! = (enum dwarf_location_atom)
! (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
! loc->dw_loc_oprnd1.v.val_int = 0;
! }
! return loc;
! }
!
! size = int_size_in_bytes (TREE_TYPE (decl));
! if (size > DWARF2_ADDR_SIZE || size == -1)
! return 0;
! else if (size == DWARF2_ADDR_SIZE)
! op = DW_OP_deref;
! else
! op = DW_OP_deref_size;
! add_loc_descr (&loc, new_loc_descr (op, size, 0));
! return loc;
! }
!
! /* Return dwarf representation of location list representing for
! LOC_LIST of DECL. */
!
! static dw_loc_list_ref
! dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
! {
! 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];
!
! bool by_reference = hidden_reference_p (decl);
!
! /* 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;
!
! if (!toplevel || by_reference)
! descr = loc_by_reference (mem_loc_descriptor (varloc,
! TYPE_MODE (TREE_TYPE (decl)),
! initialized),
! decl);
! else
! descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
! initialized), decl);
!
! 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);
! }
! list = new_loc_list (descr, node->label, node->next ? node->next->label : endname, secname, 1);
! node = node->next;
!
! if (!node)
! return NULL;
!
! 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);
! if (!toplevel || by_reference)
! descr = mem_loc_descriptor (varloc, TYPE_MODE (TREE_TYPE (decl)), initialized);
! else
! descr = loc_descriptor (varloc, DECL_MODE (decl), initialized);
! descr = loc_by_reference (descr, 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)
! {
! 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, endname, secname);
! }
! 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. */
!
! static bool
! single_element_loc_list_p (dw_loc_list_ref list)
! {
! return (!list->dw_loc_next && !list->begin && !list->end);
! }
!
! /* To each location in list LIST add loc descr REF. */
!
! static void
! add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
! {
! dw_loc_descr_ref copy;
! add_loc_descr (&list->expr, ref);
! list = list->dw_loc_next;
! while (list)
! {
! copy = GGC_CNEW (dw_loc_descr_node);
! memcpy (copy, ref, sizeof (dw_loc_descr_node));
! add_loc_descr (&list->expr, copy);
! while (copy->dw_loc_next)
! {
! dw_loc_descr_ref new_copy = GGC_CNEW (dw_loc_descr_node);
! memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
! copy->dw_loc_next = new_copy;
! copy = new_copy;
! }
! list = list->dw_loc_next;
! }
! }
!
! /* Given two lists RET and LIST
! produce location list that is result of adding expression in LIST
! to expression in RET on each possition in program.
! Might be destructive on both RET and LIST.
!
! TODO: We handle only simple cases of RET or LIST having at most one
! element. General case would inolve sorting the lists in program order
! and merging them that will need some additional work.
! Adding that will improve quality of debug info especially for SRA-ed
! structures. */
!
! static void
! add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list)
! {
! if (!list)
! return;
! if (!*ret)
! {
! *ret = list;
! return;
! }
! if (!list->dw_loc_next)
! {
! add_loc_descr_to_each (*ret, list->expr);
! return;
! }
! if (!(*ret)->dw_loc_next)
! {
! add_loc_descr_to_each (list, (*ret)->expr);
! *ret = list;
! return;
! }
! if (dump_file)
! fprintf (dump_file, "Don't know how to merge two location lists with multiple locations.\n");
! *ret = NULL;
! return;
! }
!
! /* Generate Dwarf location list representing LOC.
! If WANT_ADDRESS is 0, expression computing LOC will be computed
! If WANT_ADDRESS is 1, expression computing address of LOC will be returned
! if WANT_ADDRESS is 2, expression computing address useable in location
! will be returned (i.e. DW_OP_reg can be used
! to refer to register values)
! TODO: Dwarf4 adds types to the stack machine that ought to be used here
! DW_OP_value will help in cases where we fail to find address of the
! expression.
! */
!
! static dw_loc_list_ref
! loc_list_from_tree (tree loc, int want_address)
{
! dw_loc_descr_ref ret = NULL, ret1 = NULL;
! dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
int have_address = 0;
enum dwarf_location_atom op;
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 11968,11973 ****
--- 12275,12282 ----
switch (TREE_CODE (loc))
{
case ERROR_MARK:
+ if (dump_file)
+ fprintf (dump_file, "ERROR_MARK in the expression\n");
return 0;
case PLACEHOLDER_EXPR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 11975,11989 ****
--- 12284,12305 ----
position of other fields. We don't try to encode this here. The
only user of this is Ada, which encodes the needed information using
the names of types. */
+ if (dump_file)
+ fprintf (dump_file, "PLACEHOLDER_EXPR in the expression\n");
return 0;
case CALL_EXPR:
+ if (dump_file)
+ fprintf (dump_file, "CALL_EXPR in the expression\n");
+ /* There are no opcodes for these operations. */
return 0;
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ if (dump_file)
+ fprintf (dump_file, "PRE/POST INDCREMENT/DECREMENT in the expression\n");
/* There are no opcodes for these operations. */
return 0;
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 11993,11999 ****
return 0;
/* Otherwise, process the argument and look for the address. */
! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
case VAR_DECL:
if (DECL_THREAD_LOCAL_P (loc))
--- 12309,12315 ----
return 0;
/* Otherwise, process the argument and look for the address. */
! return loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
case VAR_DECL:
if (DECL_THREAD_LOCAL_P (loc))
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12053,12069 ****
case PARM_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
! return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc),
! want_address);
/* FALLTHRU */
case RESULT_DECL:
case FUNCTION_DECL:
{
rtx rtl = rtl_for_decl_location (loc);
! if (rtl == NULL_RTX)
! return 0;
else if (CONST_INT_P (rtl))
{
HOST_WIDE_INT val = INTVAL (rtl);
--- 12369,12397 ----
case PARM_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
! return loc_list_from_tree (DECL_VALUE_EXPR (loc),
! want_address);
/* FALLTHRU */
case RESULT_DECL:
case FUNCTION_DECL:
{
rtx rtl = rtl_for_decl_location (loc);
+ 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 == 2)))
! have_address = 1;
! else if (rtl == NULL_RTX)
! {
! if (dump_file)
! {
! fprintf (dump_file, "Expansion for decl failed. No RTL ");
! print_generic_decl (dump_file, loc, 0);
! fprintf (dump_file, "\n");
! }
! return 0;
! }
else if (CONST_INT_P (rtl))
{
HOST_WIDE_INT val = INTVAL (rtl);
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12072,12078 ****
ret = int_loc_descriptor (val);
}
else if (GET_CODE (rtl) == CONST_STRING)
! return 0;
else if (CONSTANT_P (rtl))
{
ret = new_loc_descr (DW_OP_addr, 0, 0);
--- 12400,12410 ----
ret = int_loc_descriptor (val);
}
else if (GET_CODE (rtl) == CONST_STRING)
! {
! if (dump_file)
! fprintf (stderr, "Failed to expand CONST_STRING\n");
! return 0;
! }
else if (CONSTANT_P (rtl))
{
ret = new_loc_descr (DW_OP_addr, 0, 0);
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12085,12117 ****
/* Certain constructs can only be represented at top-level. */
if (want_address == 2)
- return loc_descriptor (rtl, VOIDmode,
- VAR_INIT_STATUS_INITIALIZED);
-
- mode = GET_MODE (rtl);
- if (MEM_P (rtl))
{
! rtl = XEXP (rtl, 0);
have_address = 1;
}
! ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
}
}
break;
case INDIRECT_REF:
! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
have_address = 1;
break;
case COMPOUND_EXPR:
! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address);
CASE_CONVERT:
case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
case MODIFY_EXPR:
! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
case COMPONENT_REF:
case BIT_FIELD_REF:
--- 12417,12459 ----
/* Certain constructs can only be represented at top-level. */
if (want_address == 2)
{
! ret = loc_descriptor (rtl, VOIDmode,
! VAR_INIT_STATUS_INITIALIZED);
have_address = 1;
}
! if (!ret)
! {
! mode = GET_MODE (rtl);
! if (MEM_P (rtl))
! {
! rtl = XEXP (rtl, 0);
! have_address = 1;
! }
! ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
! }
! if (!ret && dump_file)
! {
! fprintf (dump_file, "Failed to produce loc descriptor for rtl\n");
! print_rtl (dump_file, rtl);
! }
}
}
break;
case INDIRECT_REF:
! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
have_address = 1;
break;
case COMPOUND_EXPR:
! return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
CASE_CONVERT:
case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
case MODIFY_EXPR:
! return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
case COMPONENT_REF:
case BIT_FIELD_REF:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12127,12152 ****
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
! if (obj == loc)
! return 0;
! ret = loc_descriptor_from_tree_1 (obj, 1);
! if (ret == 0
! || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
return 0;
if (offset != NULL_TREE)
{
/* Variable offset. */
! ret1 = loc_descriptor_from_tree_1 (offset, 0);
! if (ret1 == 0)
return 0;
! add_loc_descr (&ret, ret1);
! add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
}
bytepos = bitpos / BITS_PER_UNIT;
! loc_descr_plus_const (&ret, bytepos);
have_address = 1;
break;
--- 12469,12503 ----
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
! gcc_assert (obj != loc);
! list_ret = loc_list_from_tree (obj, 1);
! if (list_ret == 0)
return 0;
+ if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
+ {
+ if (dump_file)
+ fprintf (stderr, "Can not encode bitfield accesses.\n");
+ return 0;
+ }
if (offset != NULL_TREE)
{
/* 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);
have_address = 1;
break;
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12156,12162 ****
if (host_integerp (loc, 0))
ret = int_loc_descriptor (tree_low_cst (loc, 0));
else
! return 0;
break;
case CONSTRUCTOR:
--- 12507,12517 ----
if (host_integerp (loc, 0))
ret = int_loc_descriptor (tree_low_cst (loc, 0));
else
! {
! if (dump_file)
! fprintf (stderr, "Integer operand is not host integer.\n");
! return 0;
! }
break;
case CONSTRUCTOR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12226,12236 ****
if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
&& host_integerp (TREE_OPERAND (loc, 1), 0))
{
! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
! if (ret == 0)
return 0;
! loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
break;
}
--- 12581,12591 ----
if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
&& host_integerp (TREE_OPERAND (loc, 1), 0))
{
! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
! if (list_ret == 0)
return 0;
! loc_list_plus_const (list_ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
break;
}
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12274,12286 ****
goto do_binop;
do_binop:
! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
! ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
! if (ret == 0 || ret1 == 0)
return 0;
! add_loc_descr (&ret, ret1);
! add_loc_descr (&ret, new_loc_descr (op, 0, 0));
break;
case TRUTH_NOT_EXPR:
--- 12629,12643 ----
goto do_binop;
do_binop:
! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
! list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
! if (list_ret == 0 || list_ret1 == 0)
return 0;
! add_loc_list (&list_ret, list_ret1);
! if (list_ret == 0)
! return 0;
! add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
break;
case TRUTH_NOT_EXPR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12297,12307 ****
goto do_unop;
do_unop:
! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
! if (ret == 0)
return 0;
! add_loc_descr (&ret, new_loc_descr (op, 0, 0));
break;
case MIN_EXPR:
--- 12654,12664 ----
goto do_unop;
do_unop:
! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
! if (list_ret == 0)
return 0;
! add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
break;
case MIN_EXPR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12321,12349 ****
case COND_EXPR:
{
dw_loc_descr_ref lhs
! = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
! dw_loc_descr_ref rhs
! = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0);
dw_loc_descr_ref bra_node, jump_node, tmp;
! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
! if (ret == 0 || lhs == 0 || rhs == 0)
return 0;
bra_node = new_loc_descr (DW_OP_bra, 0, 0);
! add_loc_descr (&ret, bra_node);
! add_loc_descr (&ret, rhs);
jump_node = new_loc_descr (DW_OP_skip, 0, 0);
! add_loc_descr (&ret, jump_node);
! add_loc_descr (&ret, lhs);
bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
bra_node->dw_loc_oprnd1.v.val_loc = lhs;
/* ??? Need a node to point the skip at. Use a nop. */
tmp = new_loc_descr (DW_OP_nop, 0, 0);
! add_loc_descr (&ret, tmp);
jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
jump_node->dw_loc_oprnd1.v.val_loc = tmp;
}
--- 12678,12706 ----
case COND_EXPR:
{
dw_loc_descr_ref lhs
! = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
! dw_loc_list_ref rhs
! = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
dw_loc_descr_ref bra_node, jump_node, tmp;
! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
! if (list_ret == 0 || lhs == 0 || rhs == 0)
return 0;
bra_node = new_loc_descr (DW_OP_bra, 0, 0);
! add_loc_descr_to_each (list_ret, bra_node);
! add_loc_list (&list_ret, rhs);
jump_node = new_loc_descr (DW_OP_skip, 0, 0);
! add_loc_descr_to_each (list_ret, jump_node);
! add_loc_descr_to_each (list_ret, lhs);
bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
bra_node->dw_loc_oprnd1.v.val_loc = lhs;
/* ??? Need a node to point the skip at. Use a nop. */
tmp = new_loc_descr (DW_OP_nop, 0, 0);
! add_loc_descr_to_each (list_ret, tmp);
jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
jump_node->dw_loc_oprnd1.v.val_loc = tmp;
}
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12357,12363 ****
up, for instance, with the C STMT_EXPR. */
if ((unsigned int) TREE_CODE (loc)
>= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
! return 0;
#ifdef ENABLE_CHECKING
/* Otherwise this is a generic code; we should just lists all of
--- 12714,12724 ----
up, for instance, with the C STMT_EXPR. */
if ((unsigned int) TREE_CODE (loc)
>= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
! {
! if (dump_file)
! fprintf (dump_file, "language specific tree in the expression\n");
! return 0;
! }
#ifdef ENABLE_CHECKING
/* Otherwise this is a generic code; we should just lists all of
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12370,12401 ****
#endif
}
/* Show if we can't fill the request for an address. */
if (want_address && !have_address)
! return 0;
/* If we've got an address and don't want one, dereference. */
! if (!want_address && have_address && ret)
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
if (size > DWARF2_ADDR_SIZE || size == -1)
! return 0;
else if (size == DWARF2_ADDR_SIZE)
op = DW_OP_deref;
else
op = DW_OP_deref_size;
! add_loc_descr (&ret, new_loc_descr (op, size, 0));
}
! return ret;
}
! static inline dw_loc_descr_ref
! loc_descriptor_from_tree (tree loc)
{
! return loc_descriptor_from_tree_1 (loc, 2);
}
/* Given a value, round it up to the lowest multiple of `boundary'
--- 12731,12794 ----
#endif
}
+ if (!ret && !list_ret)
+ return 0;
+
/* Show if we can't fill the request for an address. */
if (want_address && !have_address)
! {
! if (dump_file)
! fprintf (stderr, "Want address but have only value.\n");
! return 0;
! }
!
! gcc_assert (!ret || !list_ret);
/* If we've got an address and don't want one, dereference. */
! if (!want_address && have_address)
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
if (size > DWARF2_ADDR_SIZE || size == -1)
! {
! if (dump_file)
! {
! fprintf (dump_file, "DWARF address size mismatch. %i %i\n",
! (int)size, DWARF2_ADDR_SIZE);
! print_generic_expr (dump_file, loc, 0);
! }
! return 0;
! }
else if (size == DWARF2_ADDR_SIZE)
op = DW_OP_deref;
else
op = DW_OP_deref_size;
! if (ret)
! add_loc_descr (&ret, new_loc_descr (op, size, 0));
! else
! add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
}
+ if (ret)
+ list_ret = single_element_loc_list (ret);
! return list_ret;
}
! /* Same as above but return only single location expression. */
! static dw_loc_descr_ref
! loc_descriptor_from_tree (tree loc, int want_address)
{
! dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
! if (!ret)
! return NULL;
! if (ret->dw_loc_next)
! {
! if (dump_file)
! fprintf (dump_file, "Multiple locations needed where only one is assumed\n");
! return NULL;
! }
! return ret->expr;
}
/* Given a value, round it up to the lowest multiple of `boundary'
*************** field_byte_offset (const_tree decl)
*** 12602,12611 ****
static inline void
add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
! dw_loc_descr_ref descr)
{
! if (descr != 0)
! add_AT_loc (die, attr_kind, descr);
}
/* Attach the specialized form of location attribute used for data members of
--- 12995,13008 ----
static inline void
add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
! dw_loc_list_ref descr)
{
! if (descr == 0)
! return;
! if (single_element_loc_list_p (descr))
! add_AT_loc (die, attr_kind, descr->expr);
! else
! add_AT_loc_list (die, attr_kind, descr);
}
/* Attach the specialized form of location attribute used for data members of
*************** rtl_for_decl_location (tree decl)
*** 13243,13278 ****
return rtl;
}
- /* We need to figure out what section we should use as the base for the
- address ranges where a given location is valid.
- 1. If this particular DECL has a section associated with it, use that.
- 2. If this function has a section associated with it, use that.
- 3. Otherwise, use the text section.
- XXX: If you split a variable across multiple sections, we won't notice. */
-
- static const char *
- secname_for_decl (const_tree decl)
- {
- const char *secname;
-
- if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
- {
- tree sectree = DECL_SECTION_NAME (decl);
- secname = TREE_STRING_POINTER (sectree);
- }
- else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
- {
- tree sectree = DECL_SECTION_NAME (current_function_decl);
- secname = TREE_STRING_POINTER (sectree);
- }
- else if (cfun && in_cold_section_p)
- secname = crtl->subsections.cold_section_label;
- else
- secname = text_section_label;
-
- return secname;
- }
-
/* Check whether decl is a Fortran COMMON symbol. If not, NULL_TREE is
returned. If so, the decl for the COMMON block is returned, and the
value is the offset into the common block for the symbol. */
--- 13640,13645 ----
*************** fortran_common (tree decl, HOST_WIDE_INT
*** 13323,13382 ****
return cvar;
}
- /* Dereference a location expression LOC if DECL is passed by invisible
- reference. */
-
- static dw_loc_descr_ref
- loc_by_reference (dw_loc_descr_ref loc, tree decl)
- {
- HOST_WIDE_INT size;
- enum dwarf_location_atom op;
-
- if (loc == NULL)
- return NULL;
-
- if ((TREE_CODE (decl) != PARM_DECL
- && TREE_CODE (decl) != RESULT_DECL
- && TREE_CODE (decl) != VAR_DECL)
- || !DECL_BY_REFERENCE (decl))
- return loc;
-
- /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
- change it into corresponding DW_OP_breg{0...31,x} 0. Then the
- location expression is considered to be address of a memory location,
- rather than the register itself. */
- if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
- || loc->dw_loc_opc == DW_OP_regx)
- && (loc->dw_loc_next == NULL
- || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
- && loc->dw_loc_next->dw_loc_next == NULL)))
- {
- if (loc->dw_loc_opc == DW_OP_regx)
- {
- loc->dw_loc_opc = DW_OP_bregx;
- loc->dw_loc_oprnd2.v.val_int = 0;
- }
- else
- {
- loc->dw_loc_opc
- = (enum dwarf_location_atom)
- (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
- loc->dw_loc_oprnd1.v.val_int = 0;
- }
- return loc;
- }
-
- size = int_size_in_bytes (TREE_TYPE (decl));
- if (size > DWARF2_ADDR_SIZE || size == -1)
- return 0;
- else if (size == DWARF2_ADDR_SIZE)
- op = DW_OP_deref;
- else
- op = DW_OP_deref_size;
- add_loc_descr (&loc, new_loc_descr (op, size, 0));
- return loc;
- }
-
/* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
data attribute for a variable or a parameter. We generate the
DW_AT_const_value attribute only in those cases where the given variable
--- 13690,13695 ----
*************** add_location_or_const_value_attribute (d
*** 13394,13399 ****
--- 13707,13713 ----
{
rtx rtl;
dw_loc_descr_ref descr;
+ dw_loc_list_ref descr_list;
var_loc_list *loc_list;
struct var_loc_node *node;
if (TREE_CODE (decl) == ERROR_MARK)
*************** add_location_or_const_value_attribute (d
*** 13515,13532 ****
if (descr)
{
descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, descr);
return;
}
}
/* We couldn't get any rtl, so try directly generating the location
description from the tree. */
! descr = loc_descriptor_from_tree (decl);
! if (descr)
{
descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, descr);
return;
}
/* None of that worked, so it must not really have a location;
--- 13829,13846 ----
if (descr)
{
descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, single_element_loc_list (descr));
return;
}
}
/* We couldn't get any rtl, so try directly generating the location
description from the tree. */
! descr_list = loc_list_from_tree (decl, hidden_reference_p (decl) ? 0 : 2);
! if (descr_list)
{
descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, descr_list);
return;
}
/* None of that worked, so it must not really have a location;
*************** add_bound_info (dw_die_ref subrange_die,
*** 13943,13949 ****
case RESULT_DECL:
{
dw_die_ref decl_die = lookup_decl_die (bound);
! dw_loc_descr_ref loc;
/* ??? Can this happen, or should the variable have been bound
first? Probably it can, since I imagine that we try to create
--- 14257,14263 ----
case RESULT_DECL:
{
dw_die_ref decl_die = lookup_decl_die (bound);
! dw_loc_list_ref loc;
/* ??? Can this happen, or should the variable have been bound
first? Probably it can, since I imagine that we try to create
*************** add_bound_info (dw_die_ref subrange_die,
*** 13954,13960 ****
add_AT_die_ref (subrange_die, bound_attr, decl_die);
else
{
! loc = loc_descriptor_from_tree_1 (bound, 0);
add_AT_location_description (subrange_die, bound_attr, loc);
}
break;
--- 14268,14274 ----
add_AT_die_ref (subrange_die, bound_attr, decl_die);
else
{
! loc = loc_list_from_tree (bound, 0);
add_AT_location_description (subrange_die, bound_attr, loc);
}
break;
*************** add_bound_info (dw_die_ref subrange_die,
*** 13966,13975 ****
evaluate the value of the array bound. */
dw_die_ref ctx, decl_die;
! dw_loc_descr_ref loc;
! loc = loc_descriptor_from_tree (bound);
! if (loc == NULL)
break;
if (current_function_decl == 0)
--- 14280,14289 ----
evaluate the value of the array bound. */
dw_die_ref ctx, decl_die;
! dw_loc_list_ref list;
! list = loc_list_from_tree (bound, 2);
! if (list == NULL)
break;
if (current_function_decl == 0)
*************** add_bound_info (dw_die_ref subrange_die,
*** 13980,13986 ****
decl_die = new_die (DW_TAG_variable, ctx, bound);
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
! add_AT_loc (decl_die, DW_AT_location, loc);
add_AT_die_ref (subrange_die, bound_attr, decl_die);
break;
--- 14294,14303 ----
decl_die = new_die (DW_TAG_variable, ctx, bound);
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
! if (list->dw_loc_next)
! add_AT_loc_list (decl_die, DW_AT_location, list);
! else
! add_AT_loc (decl_die, DW_AT_location, list->expr);
add_AT_die_ref (subrange_die, bound_attr, decl_die);
break;
*************** gen_array_type_die (tree type, dw_die_re
*** 14586,14597 ****
&& DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{
tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
! dw_loc_descr_ref loc = loc_descriptor_from_tree (szdecl);
size = int_size_in_bytes (TREE_TYPE (szdecl));
if (loc && size > 0)
{
! add_AT_loc (array_die, DW_AT_string_length, loc);
if (size != DWARF2_ADDR_SIZE)
add_AT_unsigned (array_die, DW_AT_byte_size, size);
}
--- 14903,14914 ----
&& DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{
tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
! dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
size = int_size_in_bytes (TREE_TYPE (szdecl));
if (loc && size > 0)
{
! add_AT_location_description (array_die, DW_AT_string_length, loc);
if (size != DWARF2_ADDR_SIZE)
add_AT_unsigned (array_die, DW_AT_byte_size, size);
}
*************** descr_info_loc (tree val, tree base_decl
*** 14685,14691 ****
CASE_CONVERT:
return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
case VAR_DECL:
! return loc_descriptor_from_tree_1 (val, 0);
case INTEGER_CST:
if (host_integerp (val, 0))
return int_loc_descriptor (tree_low_cst (val, 0));
--- 15002,15008 ----
CASE_CONVERT:
return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
case VAR_DECL:
! return loc_descriptor_from_tree (val, 0);
case INTEGER_CST:
if (host_integerp (val, 0))
return int_loc_descriptor (tree_low_cst (val, 0));
*************** gen_subprogram_die (tree decl, dw_die_re
*** 15443,15449 ****
if (cfun->static_chain_decl)
add_AT_location_description (subr_die, DW_AT_static_link,
! loc_descriptor_from_tree (cfun->static_chain_decl));
}
/* Generate child dies for template paramaters. */
--- 15760,15766 ----
if (cfun->static_chain_decl)
add_AT_location_description (subr_die, DW_AT_static_link,
! loc_list_from_tree (cfun->static_chain_decl, 2));
}
/* Generate child dies for template paramaters. */
*************** gen_variable_die (tree decl, tree origin
*** 15613,15619 ****
{
tree field;
dw_die_ref com_die;
! dw_loc_descr_ref loc;
die_node com_die_arg;
var_die = lookup_decl_die (decl_or_origin);
--- 15930,15936 ----
{
tree field;
dw_die_ref com_die;
! dw_loc_list_ref loc;
die_node com_die_arg;
var_die = lookup_decl_die (decl_or_origin);
*************** gen_variable_die (tree decl, tree origin
*** 15621,15642 ****
{
if (get_AT (var_die, DW_AT_location) == NULL)
{
! loc = loc_descriptor_from_tree (com_decl);
if (loc)
{
if (off)
{
/* Optimize the common case. */
! if (loc->dw_loc_opc == DW_OP_addr
! && loc->dw_loc_next == NULL
! && GET_CODE (loc->dw_loc_oprnd1.v.val_addr)
== SYMBOL_REF)
! loc->dw_loc_oprnd1.v.val_addr
! = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
else
! loc_descr_plus_const (&loc, off);
}
! add_AT_loc (var_die, DW_AT_location, loc);
remove_AT (var_die, DW_AT_declaration);
}
}
--- 15938,15960 ----
{
if (get_AT (var_die, DW_AT_location) == NULL)
{
! loc = loc_list_from_tree (com_decl, off ? 1 : 2);
if (loc)
{
if (off)
{
/* Optimize the common case. */
! if (single_element_loc_list_p (loc)
! && loc->expr->dw_loc_opc == DW_OP_addr
! && loc->expr->dw_loc_next == NULL
! && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
== SYMBOL_REF)
! loc->expr->dw_loc_oprnd1.v.val_addr
! = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
else
! loc_list_plus_const (loc, off);
}
! add_AT_location_description (var_die, DW_AT_location, loc);
remove_AT (var_die, DW_AT_declaration);
}
}
*************** gen_variable_die (tree decl, tree origin
*** 15652,15658 ****
com_die_arg.decl_id = DECL_UID (com_decl);
com_die_arg.die_parent = context_die;
com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
! loc = loc_descriptor_from_tree (com_decl);
if (com_die == NULL)
{
const char *cnam
--- 15970,15976 ----
com_die_arg.decl_id = DECL_UID (com_decl);
com_die_arg.die_parent = context_die;
com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
! loc = loc_list_from_tree (com_decl, 2);
if (com_die == NULL)
{
const char *cnam
*************** gen_variable_die (tree decl, tree origin
*** 15663,15672 ****
add_name_and_src_coords_attributes (com_die, com_decl);
if (loc)
{
! add_AT_loc (com_die, DW_AT_location, loc);
/* Avoid sharing the same loc descriptor between
DW_TAG_common_block and DW_TAG_variable. */
! loc = loc_descriptor_from_tree (com_decl);
}
else if (DECL_EXTERNAL (decl))
add_AT_flag (com_die, DW_AT_declaration, 1);
--- 15981,15990 ----
add_name_and_src_coords_attributes (com_die, com_decl);
if (loc)
{
! add_AT_location_description (com_die, DW_AT_location, loc);
/* Avoid sharing the same loc descriptor between
DW_TAG_common_block and DW_TAG_variable. */
! loc = loc_list_from_tree (com_decl, 2);
}
else if (DECL_EXTERNAL (decl))
add_AT_flag (com_die, DW_AT_declaration, 1);
*************** gen_variable_die (tree decl, tree origin
*** 15677,15684 ****
}
else if (get_AT (com_die, DW_AT_location) == NULL && loc)
{
! add_AT_loc (com_die, DW_AT_location, loc);
! loc = loc_descriptor_from_tree (com_decl);
remove_AT (com_die, DW_AT_declaration);
}
var_die = new_die (DW_TAG_variable, com_die, decl);
--- 15995,16002 ----
}
else if (get_AT (com_die, DW_AT_location) == NULL && loc)
{
! add_AT_location_description (com_die, DW_AT_location, loc);
! loc = loc_list_from_tree (com_decl, 2);
remove_AT (com_die, DW_AT_declaration);
}
var_die = new_die (DW_TAG_variable, com_die, decl);
*************** gen_variable_die (tree decl, tree origin
*** 15691,15705 ****
if (off)
{
/* Optimize the common case. */
! if (loc->dw_loc_opc == DW_OP_addr
! && loc->dw_loc_next == NULL
! && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
! loc->dw_loc_oprnd1.v.val_addr
! = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
else
! loc_descr_plus_const (&loc, off);
}
! add_AT_loc (var_die, DW_AT_location, loc);
}
else if (DECL_EXTERNAL (decl))
add_AT_flag (var_die, DW_AT_declaration, 1);
--- 16009,16024 ----
if (off)
{
/* Optimize the common case. */
! if (single_element_loc_list_p (loc)
! && loc->expr->dw_loc_opc == DW_OP_addr
! && loc->expr->dw_loc_next == NULL
! && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
! loc->expr->dw_loc_oprnd1.v.val_addr
! = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
else
! loc_list_plus_const (loc, off);
}
! add_AT_location_description (var_die, DW_AT_location, loc);
}
else if (DECL_EXTERNAL (decl))
add_AT_flag (var_die, DW_AT_declaration, 1);
*************** gen_variable_die (tree decl, tree origin
*** 15762,15771 ****
tree type = TREE_TYPE (decl);
add_name_and_src_coords_attributes (var_die, decl);
! if ((TREE_CODE (decl) == PARM_DECL
! || TREE_CODE (decl) == RESULT_DECL
! || TREE_CODE (decl) == VAR_DECL)
! && DECL_BY_REFERENCE (decl))
add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
else
add_type_attribute (var_die, type, TREE_READONLY (decl),
--- 16081,16087 ----
tree type = TREE_TYPE (decl);
add_name_and_src_coords_attributes (var_die, decl);
! if (hidden_reference_p (decl))
add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
else
add_type_attribute (var_die, type, TREE_READONLY (decl),