Commit 823e9473 by Jakub Jelinek Committed by Jakub Jelinek

re PR debug/43983 (var-tracking needlessly throws away location info for SRAed vars)

	PR debug/43983
	* var-tracking.c (track_expr_p): Allow tracking of variables optimized
	by SRA.
	* Makefile.in (dwarf2out.o): Depend on $(TREE_FLOW_H).
	* tree-sra.c (create_access_replacement): Call unshare_expr before
	passing expr to SET_DECL_DEBUG_EXPR, and remove any SSA_NAMEs from
	it.
	* dwarf2out.c: Include tree-flow.h.
	(struct var_loc_node): Rename var_loc_note field to loc, add comment.
	(size_of_loc_descr, output_loc_operands, output_loc_operands_raw):
	Handle DW_OP_bit_piece.
	(decl_piece_bitsize, decl_piece_varloc_ptr, decl_piece_node,
	construct_piece_list, adjust_piece_list): New functions.
	(add_var_loc_to_decl): Handle SRA optimized variables.
	Adjust for var_loc_note to loc field renaming.
	(dw_loc_list_1): For WANT_ADDRESS == 2 prefer DECL_MODE of decl
	in VAR_LOCATION note.
	(new_loc_descr_op_bit_piece): New function.
	(dw_sra_loc_expr): New function.
	(dw_loc_list): Use it.  Don't handle the last range after the
	loop, handle it inside of the loop.  Adjust for var_loc_note
	to loc field renaming.
	(add_location_or_const_value_attribute): Only special case
	single entry loc lists if loc is NOTE_P.  Adjust for
	var_loc_note to loc field renaming.
	(dwarf2out_var_location): Don't set newloc->var_loc_note
	and newloc->next here.

	* gcc.dg/guality/sra-1.c: New test.

From-SVN: r159357
parent d20cfbc2
2010-05-13 Jakub Jelinek <jakub@redhat.com>
PR debug/43983
* var-tracking.c (track_expr_p): Allow tracking of variables optimized
by SRA.
* Makefile.in (dwarf2out.o): Depend on $(TREE_FLOW_H).
* tree-sra.c (create_access_replacement): Call unshare_expr before
passing expr to SET_DECL_DEBUG_EXPR, and remove any SSA_NAMEs from
it.
* dwarf2out.c: Include tree-flow.h.
(struct var_loc_node): Rename var_loc_note field to loc, add comment.
(size_of_loc_descr, output_loc_operands, output_loc_operands_raw):
Handle DW_OP_bit_piece.
(decl_piece_bitsize, decl_piece_varloc_ptr, decl_piece_node,
construct_piece_list, adjust_piece_list): New functions.
(add_var_loc_to_decl): Handle SRA optimized variables.
Adjust for var_loc_note to loc field renaming.
(dw_loc_list_1): For WANT_ADDRESS == 2 prefer DECL_MODE of decl
in VAR_LOCATION note.
(new_loc_descr_op_bit_piece): New function.
(dw_sra_loc_expr): New function.
(dw_loc_list): Use it. Don't handle the last range after the
loop, handle it inside of the loop. Adjust for var_loc_note
to loc field renaming.
(add_location_or_const_value_attribute): Only special case
single entry loc lists if loc is NOTE_P. Adjust for
var_loc_note to loc field renaming.
(dwarf2out_var_location): Don't set newloc->var_loc_note
and newloc->next here.
2010-05-12 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_mark_address_taken_node): No longer imply needed flag.
......
......@@ -2846,7 +2846,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
libfuncs.h $(TOPLEV_H) dwarf2out.h reload.h $(GGC_H) $(EXCEPT_H) dwarf2asm.h \
$(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
$(MD5_H) $(INPUT_H) $(FUNCTION_H) $(GIMPLE_H) $(TREE_PASS_H)
$(MD5_H) $(INPUT_H) $(FUNCTION_H) $(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H)
dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
......
......@@ -91,6 +91,7 @@ along with GCC; see the file COPYING3. If not see
#include "input.h"
#include "gimple.h"
#include "tree-pass.h"
#include "tree-flow.h"
#ifdef DWARF2_DEBUGGING_INFO
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
......@@ -4784,6 +4785,10 @@ size_of_loc_descr (dw_loc_descr_ref loc)
case DW_OP_piece:
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
break;
case DW_OP_bit_piece:
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
size += size_of_uleb128 (loc->dw_loc_oprnd2.v.val_unsigned);
break;
case DW_OP_deref_size:
case DW_OP_xderef_size:
size += 1;
......@@ -5008,6 +5013,10 @@ output_loc_operands (dw_loc_descr_ref loc)
case DW_OP_piece:
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
break;
case DW_OP_bit_piece:
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
dw2_asm_output_data_uleb128 (val2->v.val_unsigned, NULL);
break;
case DW_OP_deref_size:
case DW_OP_xderef_size:
dw2_asm_output_data (1, val1->v.val_int, NULL);
......@@ -5123,6 +5132,12 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
break;
case DW_OP_bit_piece:
fputc (',', asm_out_file);
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
dw2_asm_output_data_uleb128_raw (val2->v.val_unsigned);
break;
case DW_OP_consts:
case DW_OP_breg0:
case DW_OP_breg1:
......@@ -5739,7 +5754,15 @@ DEF_VEC_ALLOC_O(die_arg_entry,gc);
/* Node of the variable location list. */
struct GTY ((chain_next ("%h.next"))) var_loc_node {
rtx GTY (()) var_loc_note;
/* Either NOTE_INSN_VAR_LOCATION, or, for SRA optimized variables,
EXPR_LIST chain. For small bitsizes, bitsize is encoded
in mode of the EXPR_LIST node and first EXPR_LIST operand
is either NOTE_INSN_VAR_LOCATION for a piece with a known
location or NULL for padding. For larger bitsizes,
mode is 0 and first operand is a CONCAT with bitsize
as first CONCAT operand and NOTE_INSN_VAR_LOCATION resp.
NULL as second operand. */
rtx GTY (()) loc;
const char * GTY (()) label;
struct var_loc_node * GTY (()) next;
};
......@@ -7757,16 +7780,175 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
decl_die->decl_id = decl_id;
}
/* Return how many bits covers PIECE EXPR_LIST. */
static int
decl_piece_bitsize (rtx piece)
{
int ret = (int) GET_MODE (piece);
if (ret)
return ret;
gcc_assert (GET_CODE (XEXP (piece, 0)) == CONCAT
&& CONST_INT_P (XEXP (XEXP (piece, 0), 0)));
return INTVAL (XEXP (XEXP (piece, 0), 0));
}
/* Return pointer to the location of location note in PIECE EXPR_LIST. */
static rtx *
decl_piece_varloc_ptr (rtx piece)
{
if ((int) GET_MODE (piece))
return &XEXP (piece, 0);
else
return &XEXP (XEXP (piece, 0), 1);
}
/* Create an EXPR_LIST for location note LOC_NOTE covering BITSIZE bits.
Next is the chain of following piece nodes. */
static rtx
decl_piece_node (rtx loc_note, HOST_WIDE_INT bitsize, rtx next)
{
if (bitsize <= (int) MAX_MACHINE_MODE)
return alloc_EXPR_LIST (bitsize, loc_note, next);
else
return alloc_EXPR_LIST (0, gen_rtx_CONCAT (VOIDmode,
GEN_INT (bitsize),
loc_note), next);
}
/* Return rtx that should be stored into loc field for
LOC_NOTE and BITPOS/BITSIZE. */
static rtx
construct_piece_list (rtx loc_note, HOST_WIDE_INT bitpos,
HOST_WIDE_INT bitsize)
{
if (bitsize != -1)
{
loc_note = decl_piece_node (loc_note, bitsize, NULL_RTX);
if (bitpos != 0)
loc_note = decl_piece_node (NULL_RTX, bitpos, loc_note);
}
return loc_note;
}
/* This function either modifies location piece list *DEST in
place (if SRC and INNER is NULL), or copies location piece list
*SRC to *DEST while modifying it. Location BITPOS is modified
to contain LOC_NOTE, any pieces overlapping it are removed resp.
not copied and if needed some padding around it is added.
When modifying in place, DEST should point to EXPR_LIST where
earlier pieces cover PIECE_BITPOS bits, when copying SRC points
to the start of the whole list and INNER points to the EXPR_LIST
where earlier pieces cover PIECE_BITPOS bits. */
static void
adjust_piece_list (rtx *dest, rtx *src, rtx *inner,
HOST_WIDE_INT bitpos, HOST_WIDE_INT piece_bitpos,
HOST_WIDE_INT bitsize, rtx loc_note)
{
int diff;
bool copy = inner != NULL;
if (copy)
{
/* First copy all nodes preceeding the current bitpos. */
while (src != inner)
{
*dest = decl_piece_node (*decl_piece_varloc_ptr (*src),
decl_piece_bitsize (*src), NULL_RTX);
dest = &XEXP (*dest, 1);
src = &XEXP (*src, 1);
}
}
/* Add padding if needed. */
if (bitpos != piece_bitpos)
{
*dest = decl_piece_node (NULL_RTX, bitpos - piece_bitpos,
copy ? NULL_RTX : *dest);
dest = &XEXP (*dest, 1);
}
else if (*dest && decl_piece_bitsize (*dest) == bitsize)
{
gcc_assert (!copy);
/* A piece with correct bitpos and bitsize already exist,
just update the location for it and return. */
*decl_piece_varloc_ptr (*dest) = loc_note;
return;
}
/* Add the piece that changed. */
*dest = decl_piece_node (loc_note, bitsize, copy ? NULL_RTX : *dest);
dest = &XEXP (*dest, 1);
/* Skip over pieces that overlap it. */
diff = bitpos - piece_bitpos + bitsize;
if (!copy)
src = dest;
while (diff > 0 && *src)
{
rtx piece = *src;
diff -= decl_piece_bitsize (piece);
if (copy)
src = &XEXP (piece, 1);
else
{
*src = XEXP (piece, 1);
free_EXPR_LIST_node (piece);
}
}
/* Add padding if needed. */
if (diff < 0 && *src)
{
if (!copy)
dest = src;
*dest = decl_piece_node (NULL_RTX, -diff, copy ? NULL_RTX : *dest);
dest = &XEXP (*dest, 1);
}
if (!copy)
return;
/* Finally copy all nodes following it. */
while (*src)
{
*dest = decl_piece_node (*decl_piece_varloc_ptr (*src),
decl_piece_bitsize (*src), NULL_RTX);
dest = &XEXP (*dest, 1);
src = &XEXP (*src, 1);
}
}
/* Add a variable location node to the linked list for DECL. */
static struct var_loc_node *
add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
{
unsigned int decl_id = DECL_UID (decl);
unsigned int decl_id;
var_loc_list *temp;
void **slot;
struct var_loc_node *loc = NULL;
HOST_WIDE_INT bitsize = -1, bitpos = -1;
if (DECL_DEBUG_EXPR_IS_FROM (decl))
{
tree realdecl = DECL_DEBUG_EXPR (decl);
if (realdecl && handled_component_p (realdecl))
{
HOST_WIDE_INT maxsize;
tree innerdecl;
innerdecl
= get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
|| TREE_STATIC (innerdecl)
|| bitsize <= 0
|| bitpos + bitsize > 256
|| bitsize != maxsize)
return NULL;
decl = innerdecl;
}
}
decl_id = DECL_UID (decl);
slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
if (*slot == NULL)
{
......@@ -7780,17 +7962,40 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
if (temp->last)
{
struct var_loc_node *last = temp->last, *unused = NULL;
rtx *piece_loc = NULL, last_loc_note;
int piece_bitpos = 0;
if (last->next)
{
last = last->next;
gcc_assert (last->next == NULL);
}
if (bitsize != -1 && GET_CODE (last->loc) == EXPR_LIST)
{
piece_loc = &last->loc;
do
{
int cur_bitsize = decl_piece_bitsize (*piece_loc);
if (piece_bitpos + cur_bitsize > bitpos)
break;
piece_bitpos += cur_bitsize;
piece_loc = &XEXP (*piece_loc, 1);
}
while (*piece_loc);
}
/* TEMP->LAST here is either pointer to the last but one or
last element in the chained list, LAST is pointer to the
last element. */
/* If the last note doesn't cover any instructions, remove it. */
if (label && strcmp (last->label, label) == 0)
{
/* For SRA optimized variables if there weren't any real
insns since last note, just modify the last node. */
if (piece_loc != NULL)
{
adjust_piece_list (piece_loc, NULL, NULL,
bitpos, piece_bitpos, bitsize, loc_note);
return NULL;
}
/* If the last note doesn't cover any instructions, remove it. */
if (temp->last != last)
{
temp->last->next = NULL;
......@@ -7802,17 +8007,28 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
{
gcc_assert (temp->first == temp->last);
memset (temp->last, '\0', sizeof (*temp->last));
temp->last->loc = construct_piece_list (loc_note, bitpos, bitsize);
return temp->last;
}
}
if (bitsize == -1 && NOTE_P (last->loc))
last_loc_note = last->loc;
else if (piece_loc != NULL
&& *piece_loc != NULL_RTX
&& piece_bitpos == bitpos
&& decl_piece_bitsize (*piece_loc) == bitsize)
last_loc_note = *decl_piece_varloc_ptr (*piece_loc);
else
last_loc_note = NULL_RTX;
/* If the current location is the same as the end of the list,
and either both or neither of the locations is uninitialized,
we have nothing to do. */
if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (last->var_loc_note),
if (last_loc_note == NULL_RTX
|| (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (last_loc_note),
NOTE_VAR_LOCATION_LOC (loc_note)))
|| ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note)
|| ((NOTE_VAR_LOCATION_STATUS (last_loc_note)
!= NOTE_VAR_LOCATION_STATUS (loc_note))
&& ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note)
&& ((NOTE_VAR_LOCATION_STATUS (last_loc_note)
== VAR_INIT_STATUS_UNINITIALIZED)
|| (NOTE_VAR_LOCATION_STATUS (loc_note)
== VAR_INIT_STATUS_UNINITIALIZED))))
......@@ -7827,6 +8043,11 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
}
else
loc = GGC_CNEW (struct var_loc_node);
if (bitsize == -1 || piece_loc == NULL)
loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
else
adjust_piece_list (&loc->loc, &last->loc, piece_loc,
bitpos, piece_bitpos, bitsize, loc_note);
last->next = loc;
/* Ensure TEMP->LAST will point either to the new last but one
element of the chain, or to the last element in it. */
......@@ -7841,6 +8062,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
loc = GGC_CNEW (struct var_loc_node);
temp->first = loc;
temp->last = loc;
loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
}
return loc;
}
......@@ -14084,7 +14306,11 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
}
else
{
descr = loc_descriptor (varloc, DECL_MODE (loc), initialized);
if (GET_CODE (varloc) == VAR_LOCATION)
mode = DECL_MODE (PAT_VAR_LOCATION_DECL (varloc));
else
mode = DECL_MODE (loc);
descr = loc_descriptor (varloc, mode, initialized);
have_address = 1;
}
......@@ -14134,6 +14360,125 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
return descr;
}
/* Create a DW_OP_piece or DW_OP_bit_piece for bitsize, or return NULL
if it is not possible. */
static dw_loc_descr_ref
new_loc_descr_op_bit_piece (HOST_WIDE_INT bitsize)
{
if ((bitsize % BITS_PER_UNIT) == 0)
return new_loc_descr (DW_OP_piece, bitsize / BITS_PER_UNIT, 0);
else if (dwarf_version >= 3 || !dwarf_strict)
return new_loc_descr (DW_OP_bit_piece, bitsize, 0);
else
return NULL;
}
/* Helper function for dw_loc_list. Compute proper Dwarf location descriptor
for VAR_LOC_NOTE for variable DECL that has been optimized by SRA. */
static dw_loc_descr_ref
dw_sra_loc_expr (tree decl, rtx loc)
{
rtx p;
unsigned int padsize = 0;
dw_loc_descr_ref descr, *descr_tail;
unsigned HOST_WIDE_INT decl_size;
rtx varloc;
enum var_init_status initialized;
if (DECL_SIZE (decl) == NULL
|| !host_integerp (DECL_SIZE (decl), 1))
return NULL;
decl_size = tree_low_cst (DECL_SIZE (decl), 1);
descr = NULL;
descr_tail = &descr;
for (p = loc; p; p = XEXP (p, 1))
{
unsigned int bitsize = decl_piece_bitsize (p);
rtx loc_note = *decl_piece_varloc_ptr (p);
dw_loc_descr_ref cur_descr;
dw_loc_descr_ref *tail, last = NULL;
unsigned int opsize = 0;
if (loc_note == NULL_RTX
|| NOTE_VAR_LOCATION_LOC (loc_note) == NULL_RTX)
{
padsize += bitsize;
continue;
}
initialized = NOTE_VAR_LOCATION_STATUS (loc_note);
varloc = NOTE_VAR_LOCATION (loc_note);
cur_descr = dw_loc_list_1 (decl, varloc, 2, initialized);
if (cur_descr == NULL)
{
padsize += bitsize;
continue;
}
/* Check that cur_descr either doesn't use
DW_OP_*piece operations, or their sum is equal
to bitsize. Otherwise we can't embed it. */
for (tail = &cur_descr; *tail != NULL;
tail = &(*tail)->dw_loc_next)
if ((*tail)->dw_loc_opc == DW_OP_piece)
{
opsize += (*tail)->dw_loc_oprnd1.v.val_unsigned
* BITS_PER_UNIT;
last = *tail;
}
else if ((*tail)->dw_loc_opc == DW_OP_bit_piece)
{
opsize += (*tail)->dw_loc_oprnd1.v.val_unsigned;
last = *tail;
}
if (last != NULL && opsize != bitsize)
{
padsize += bitsize;
continue;
}
/* If there is a hole, add DW_OP_*piece after empty DWARF
expression, which means that those bits are optimized out. */
if (padsize)
{
if (padsize > decl_size)
return NULL;
decl_size -= padsize;
*descr_tail = new_loc_descr_op_bit_piece (padsize);
if (*descr_tail == NULL)
return NULL;
descr_tail = &(*descr_tail)->dw_loc_next;
padsize = 0;
}
*descr_tail = cur_descr;
descr_tail = tail;
if (bitsize > decl_size)
return NULL;
decl_size -= bitsize;
if (last == NULL)
{
*descr_tail = new_loc_descr_op_bit_piece (bitsize);
if (*descr_tail == NULL)
return NULL;
descr_tail = &(*descr_tail)->dw_loc_next;
}
}
/* If there were any non-empty expressions, add padding till the end of
the decl. */
if (descr != NULL && decl_size != 0)
{
*descr_tail = new_loc_descr_op_bit_piece (decl_size);
if (*descr_tail == NULL)
return NULL;
}
return descr;
}
/* Return the dwarf representation of the location list LOC_LIST of
DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree
function. */
......@@ -14163,32 +14508,35 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
secname = secname_for_decl (decl);
for (node = loc_list->first; node->next; node = node->next)
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
for (node = loc_list->first; node; node = node->next)
if (GET_CODE (node->loc) == EXPR_LIST
|| NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
{
/* The variable has a location between NODE->LABEL and
NODE->NEXT->LABEL. */
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
if (descr)
if (GET_CODE (node->loc) == EXPR_LIST)
{
*listp = new_loc_list (descr, node->label, node->next->label,
secname);
listp = &(*listp)->dw_loc_next;
}
/* This requires DW_OP_{,bit_}piece, which is not usable
inside DWARF expressions. */
if (want_address != 2)
continue;
descr = dw_sra_loc_expr (decl, node->loc);
if (descr == NULL)
continue;
}
/* 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)
else
{
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
varloc = NOTE_VAR_LOCATION (node->loc);
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
}
if (descr)
{
if (!current_function_decl)
/* The variable has a location between NODE->LABEL and
NODE->NEXT->LABEL. */
if (node->next)
endname = node->next->label;
/* If the variable has a location at the last label
it keeps its location until the end of function. */
else if (!current_function_decl)
endname = text_end_label;
else
{
......@@ -15950,13 +16298,14 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
if (loc_list
&& loc_list->first
&& loc_list->first->next == NULL
&& NOTE_VAR_LOCATION (loc_list->first->var_loc_note)
&& NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note))
&& NOTE_P (loc_list->first->loc)
&& NOTE_VAR_LOCATION (loc_list->first->loc)
&& NOTE_VAR_LOCATION_LOC (loc_list->first->loc))
{
struct var_loc_node *node;
node = loc_list->first;
rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
rtl = NOTE_VAR_LOCATION_LOC (node->loc);
if (GET_CODE (rtl) == EXPR_LIST)
rtl = XEXP (rtl, 0);
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
......@@ -20458,8 +20807,6 @@ dwarf2out_var_location (rtx loc_note)
loclabel_num++;
last_label = ggc_strdup (loclabel);
}
newloc->var_loc_note = loc_note;
newloc->next = NULL;
if (!NOTE_DURING_CALL_P (loc_note))
newloc->label = last_label;
......
2010-05-13 Jakub Jelinek <jakub@redhat.com>
PR debug/43983
* gcc.dg/guality/sra-1.c: New test.
2010-05-12 Jan Hubicka <jh@suse.cz>
* tree-ssa/unreachable.c: New test.
......
/* PR debug/43983 */
/* { dg-do run } */
/* { dg-options "-g" } */
struct A { int i; int j; };
struct B { int : 4; int i : 12; int j : 12; int : 4; };
__attribute__((noinline)) void
bar (int x)
{
asm volatile ("" : : "r" (x) : "memory");
}
__attribute__((noinline)) int
f1 (int k)
{
struct A a = { 4, k + 6 };
asm ("" : "+r" (a.i));
a.j++;
bar (a.i); /* { dg-final { gdb-test 20 "a.i" "4" } } */
bar (a.j); /* { dg-final { gdb-test 20 "a.j" "14" } } */
return a.i + a.j;
}
__attribute__((noinline)) int
f2 (int k)
{
int a[2] = { 4, k + 6 };
asm ("" : "+r" (a[0]));
a[1]++;
bar (a[0]); /* { dg-final { gdb-test 31 "a\[0\]" "4" } } */
bar (a[1]); /* { dg-final { gdb-test 31 "a\[1\]" "14" } } */
return a[0] + a[1];
}
__attribute__((noinline)) int
f3 (int k)
{
struct B a = { 4, k + 6 };
asm ("" : "+r" (a.i));
a.j++;
bar (a.i); /* { dg-final { gdb-test 42 "a.i" "4" } } */
bar (a.j); /* { dg-final { gdb-test 42 "a.j" "14" } } */
return a.i + a.j;
}
int
main (void)
{
int k;
asm ("" : "=r" (k) : "0" (7));
f1 (k);
f2 (k);
f3 (k);
return 0;
}
......@@ -1609,11 +1609,38 @@ create_access_replacement (struct access *access)
&& !DECL_ARTIFICIAL (access->base))
{
char *pretty_name = make_fancy_name (access->expr);
tree debug_expr = unshare_expr (access->expr), d;
DECL_NAME (repl) = get_identifier (pretty_name);
obstack_free (&name_obstack, pretty_name);
SET_DECL_DEBUG_EXPR (repl, access->expr);
/* Get rid of any SSA_NAMEs embedded in debug_expr,
as DECL_DEBUG_EXPR isn't considered when looking for still
used SSA_NAMEs and thus they could be freed. All debug info
generation cares is whether something is constant or variable
and that get_ref_base_and_extent works properly on the
expression. */
for (d = debug_expr; handled_component_p (d); d = TREE_OPERAND (d, 0))
switch (TREE_CODE (d))
{
case ARRAY_REF:
case ARRAY_RANGE_REF:
if (TREE_OPERAND (d, 1)
&& TREE_CODE (TREE_OPERAND (d, 1)) == SSA_NAME)
TREE_OPERAND (d, 1) = SSA_NAME_VAR (TREE_OPERAND (d, 1));
if (TREE_OPERAND (d, 3)
&& TREE_CODE (TREE_OPERAND (d, 3)) == SSA_NAME)
TREE_OPERAND (d, 3) = SSA_NAME_VAR (TREE_OPERAND (d, 3));
/* FALLTHRU */
case COMPONENT_REF:
if (TREE_OPERAND (d, 2)
&& TREE_CODE (TREE_OPERAND (d, 2)) == SSA_NAME)
TREE_OPERAND (d, 2) = SSA_NAME_VAR (TREE_OPERAND (d, 2));
break;
default:
break;
}
SET_DECL_DEBUG_EXPR (repl, debug_expr);
DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
}
......
......@@ -4505,10 +4505,27 @@ track_expr_p (tree expr, bool need_rtl)
realdecl = DECL_DEBUG_EXPR (realdecl);
if (realdecl == NULL_TREE)
realdecl = expr;
/* ??? We don't yet know how to emit DW_OP_piece for variable
that has been SRA'ed. */
else if (!DECL_P (realdecl))
{
if (handled_component_p (realdecl))
{
HOST_WIDE_INT bitsize, bitpos, maxsize;
tree innerdecl
= get_ref_base_and_extent (realdecl, &bitpos, &bitsize,
&maxsize);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
|| TREE_STATIC (innerdecl)
|| bitsize <= 0
|| bitpos + bitsize > 256
|| bitsize != maxsize)
return 0;
else
realdecl = expr;
}
else
return 0;
}
}
/* Do not track EXPR if REALDECL it should be ignored for debugging
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment