re PR debug/46724 (Wrong debug info: Invalid variable location)
PR debug/46724 * function.c (assign_parms_augmented_arg_list): Name and mark DECL of result address as NAMELESS rather than IGNORED. (assign_parms): Set DECL_VALUE_EXPR for indirect result. * tree.h (tree_decl_common::decl_flag_2): Document RESULT_DECL. (DECL_HAS_VALUE_EXPR_P): Accept RESULT_DECL. * dwarf2out.c (loc_list_from_tree) <RESULT_DECL>: Use DECL_VALUE_EXPR. * dbxout.c (dbxout_expand_expr) <RESULT_DECL>: Likewise. * var-tracking.c (vt_add_function_parameter): New, split out of... (vt_add_function_parameters): ... this. Handle incoming pointer to hold result. From-SVN: r168160
This commit is contained in:
parent
16a9afdc66
commit
8dcfef8f2b
@ -1,3 +1,18 @@
|
|||||||
|
2010-12-22 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
|
PR debug/46724
|
||||||
|
* function.c (assign_parms_augmented_arg_list): Name and mark
|
||||||
|
DECL of result address as NAMELESS rather than IGNORED.
|
||||||
|
(assign_parms): Set DECL_VALUE_EXPR for indirect result.
|
||||||
|
* tree.h (tree_decl_common::decl_flag_2): Document RESULT_DECL.
|
||||||
|
(DECL_HAS_VALUE_EXPR_P): Accept RESULT_DECL.
|
||||||
|
* dwarf2out.c (loc_list_from_tree) <RESULT_DECL>: Use
|
||||||
|
DECL_VALUE_EXPR.
|
||||||
|
* dbxout.c (dbxout_expand_expr) <RESULT_DECL>: Likewise.
|
||||||
|
* var-tracking.c (vt_add_function_parameter): New, split out of...
|
||||||
|
(vt_add_function_parameters): ... this. Handle incoming
|
||||||
|
pointer to hold result.
|
||||||
|
|
||||||
2010-12-22 Jie Zhang <jie@codesourcery.com>
|
2010-12-22 Jie Zhang <jie@codesourcery.com>
|
||||||
|
|
||||||
* config/arm/arm.c (output_move_double): Update the comment
|
* config/arm/arm.c (output_move_double): Update the comment
|
||||||
|
@ -2396,12 +2396,12 @@ dbxout_expand_expr (tree expr)
|
|||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
|
case RESULT_DECL:
|
||||||
if (DECL_HAS_VALUE_EXPR_P (expr))
|
if (DECL_HAS_VALUE_EXPR_P (expr))
|
||||||
return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
|
return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
case CONST_DECL:
|
case CONST_DECL:
|
||||||
case RESULT_DECL:
|
|
||||||
return DECL_RTL_IF_SET (expr);
|
return DECL_RTL_IF_SET (expr);
|
||||||
|
|
||||||
case INTEGER_CST:
|
case INTEGER_CST:
|
||||||
|
@ -15446,12 +15446,12 @@ loc_list_from_tree (tree loc, int want_address)
|
|||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
|
case RESULT_DECL:
|
||||||
if (DECL_HAS_VALUE_EXPR_P (loc))
|
if (DECL_HAS_VALUE_EXPR_P (loc))
|
||||||
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
|
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
|
||||||
want_address);
|
want_address);
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
case RESULT_DECL:
|
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
{
|
{
|
||||||
rtx rtl;
|
rtx rtl;
|
||||||
|
@ -2253,10 +2253,11 @@ assign_parms_augmented_arg_list (struct assign_parm_data_all *all)
|
|||||||
tree decl;
|
tree decl;
|
||||||
|
|
||||||
decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
|
decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
|
||||||
PARM_DECL, NULL_TREE, type);
|
PARM_DECL, get_identifier (".result_ptr"), type);
|
||||||
DECL_ARG_TYPE (decl) = type;
|
DECL_ARG_TYPE (decl) = type;
|
||||||
DECL_ARTIFICIAL (decl) = 1;
|
DECL_ARTIFICIAL (decl) = 1;
|
||||||
DECL_IGNORED_P (decl) = 1;
|
DECL_NAMELESS (decl) = 1;
|
||||||
|
TREE_CONSTANT (decl) = 1;
|
||||||
|
|
||||||
DECL_CHAIN (decl) = all->orig_fnargs;
|
DECL_CHAIN (decl) = all->orig_fnargs;
|
||||||
all->orig_fnargs = decl;
|
all->orig_fnargs = decl;
|
||||||
@ -3418,13 +3419,22 @@ assign_parms (tree fndecl)
|
|||||||
rtx x;
|
rtx x;
|
||||||
|
|
||||||
if (DECL_BY_REFERENCE (result))
|
if (DECL_BY_REFERENCE (result))
|
||||||
x = addr;
|
{
|
||||||
|
SET_DECL_VALUE_EXPR (result, all.function_result_decl);
|
||||||
|
x = addr;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SET_DECL_VALUE_EXPR (result,
|
||||||
|
build1 (INDIRECT_REF, TREE_TYPE (result),
|
||||||
|
all.function_result_decl));
|
||||||
addr = convert_memory_address (Pmode, addr);
|
addr = convert_memory_address (Pmode, addr);
|
||||||
x = gen_rtx_MEM (DECL_MODE (result), addr);
|
x = gen_rtx_MEM (DECL_MODE (result), addr);
|
||||||
set_mem_attributes (x, result, 1);
|
set_mem_attributes (x, result, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECL_HAS_VALUE_EXPR_P (result) = 1;
|
||||||
|
|
||||||
SET_DECL_RTL (result, x);
|
SET_DECL_RTL (result, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2773,7 +2773,8 @@ struct GTY(()) tree_decl_common {
|
|||||||
In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */
|
In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */
|
||||||
unsigned decl_flag_1 : 1;
|
unsigned decl_flag_1 : 1;
|
||||||
/* In FIELD_DECL, this is DECL_NONADDRESSABLE_P
|
/* In FIELD_DECL, this is DECL_NONADDRESSABLE_P
|
||||||
In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR_P. */
|
In VAR_DECL, PARM_DECL and RESULT_DECL, this is
|
||||||
|
DECL_HAS_VALUE_EXPR_P. */
|
||||||
unsigned decl_flag_2 : 1;
|
unsigned decl_flag_2 : 1;
|
||||||
/* Logically, these two would go in a theoretical base shared by var and
|
/* Logically, these two would go in a theoretical base shared by var and
|
||||||
parm decl. */
|
parm decl. */
|
||||||
@ -2818,7 +2819,8 @@ extern void decl_value_expr_insert (tree, tree);
|
|||||||
decl itself. This should only be used for debugging; once this field has
|
decl itself. This should only be used for debugging; once this field has
|
||||||
been set, the decl itself may not legitimately appear in the function. */
|
been set, the decl itself may not legitimately appear in the function. */
|
||||||
#define DECL_HAS_VALUE_EXPR_P(NODE) \
|
#define DECL_HAS_VALUE_EXPR_P(NODE) \
|
||||||
(TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_flag_2)
|
(TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, RESULT_DECL) \
|
||||||
|
->decl_common.decl_flag_2)
|
||||||
#define DECL_VALUE_EXPR(NODE) \
|
#define DECL_VALUE_EXPR(NODE) \
|
||||||
(decl_value_expr_lookup (DECL_WRTL_CHECK (NODE)))
|
(decl_value_expr_lookup (DECL_WRTL_CHECK (NODE)))
|
||||||
#define SET_DECL_VALUE_EXPR(NODE, VAL) \
|
#define SET_DECL_VALUE_EXPR(NODE, VAL) \
|
||||||
|
@ -7999,6 +7999,113 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Insert function parameter PARM in IN and OUT sets of ENTRY_BLOCK. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
vt_add_function_parameter (tree parm)
|
||||||
|
{
|
||||||
|
rtx decl_rtl = DECL_RTL_IF_SET (parm);
|
||||||
|
rtx incoming = DECL_INCOMING_RTL (parm);
|
||||||
|
tree decl;
|
||||||
|
enum machine_mode mode;
|
||||||
|
HOST_WIDE_INT offset;
|
||||||
|
dataflow_set *out;
|
||||||
|
decl_or_value dv;
|
||||||
|
|
||||||
|
if (TREE_CODE (parm) != PARM_DECL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!decl_rtl || !incoming)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!vt_get_decl_and_offset (incoming, &decl, &offset))
|
||||||
|
{
|
||||||
|
if (REG_P (incoming) || MEM_P (incoming))
|
||||||
|
{
|
||||||
|
/* This means argument is passed by invisible reference. */
|
||||||
|
offset = 0;
|
||||||
|
decl = parm;
|
||||||
|
incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
|
||||||
|
return;
|
||||||
|
offset += byte_lowpart_offset (GET_MODE (incoming),
|
||||||
|
GET_MODE (decl_rtl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parm != decl)
|
||||||
|
{
|
||||||
|
/* Assume that DECL_RTL was a pseudo that got spilled to
|
||||||
|
memory. The spill slot sharing code will force the
|
||||||
|
memory to reference spill_slot_decl (%sfp), so we don't
|
||||||
|
match above. That's ok, the pseudo must have referenced
|
||||||
|
the entire parameter, so just reset OFFSET. */
|
||||||
|
gcc_assert (decl == get_spill_slot_decl (false));
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
|
||||||
|
return;
|
||||||
|
|
||||||
|
out = &VTI (ENTRY_BLOCK_PTR)->out;
|
||||||
|
|
||||||
|
dv = dv_from_decl (parm);
|
||||||
|
|
||||||
|
if (target_for_debug_bind (parm)
|
||||||
|
/* We can't deal with these right now, because this kind of
|
||||||
|
variable is single-part. ??? We could handle parallels
|
||||||
|
that describe multiple locations for the same single
|
||||||
|
value, but ATM we don't. */
|
||||||
|
&& GET_CODE (incoming) != PARALLEL)
|
||||||
|
{
|
||||||
|
cselib_val *val;
|
||||||
|
|
||||||
|
/* ??? We shouldn't ever hit this, but it may happen because
|
||||||
|
arguments passed by invisible reference aren't dealt with
|
||||||
|
above: incoming-rtl will have Pmode rather than the
|
||||||
|
expected mode for the type. */
|
||||||
|
if (offset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
|
||||||
|
|
||||||
|
/* ??? Float-typed values in memory are not handled by
|
||||||
|
cselib. */
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
preserve_value (val);
|
||||||
|
set_variable_part (out, val->val_rtx, dv, offset,
|
||||||
|
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
||||||
|
dv = dv_from_value (val->val_rtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (REG_P (incoming))
|
||||||
|
{
|
||||||
|
incoming = var_lowpart (mode, incoming);
|
||||||
|
gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
|
||||||
|
attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
|
||||||
|
incoming);
|
||||||
|
set_variable_part (out, incoming, dv, offset,
|
||||||
|
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
||||||
|
}
|
||||||
|
else if (MEM_P (incoming))
|
||||||
|
{
|
||||||
|
incoming = var_lowpart (mode, incoming);
|
||||||
|
set_variable_part (out, incoming, dv, offset,
|
||||||
|
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
|
/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -8008,110 +8115,20 @@ vt_add_function_parameters (void)
|
|||||||
|
|
||||||
for (parm = DECL_ARGUMENTS (current_function_decl);
|
for (parm = DECL_ARGUMENTS (current_function_decl);
|
||||||
parm; parm = DECL_CHAIN (parm))
|
parm; parm = DECL_CHAIN (parm))
|
||||||
|
vt_add_function_parameter (parm);
|
||||||
|
|
||||||
|
if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
|
||||||
{
|
{
|
||||||
rtx decl_rtl = DECL_RTL_IF_SET (parm);
|
tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl));
|
||||||
rtx incoming = DECL_INCOMING_RTL (parm);
|
|
||||||
tree decl;
|
|
||||||
enum machine_mode mode;
|
|
||||||
HOST_WIDE_INT offset;
|
|
||||||
dataflow_set *out;
|
|
||||||
decl_or_value dv;
|
|
||||||
|
|
||||||
if (TREE_CODE (parm) != PARM_DECL)
|
if (TREE_CODE (vexpr) == INDIRECT_REF)
|
||||||
continue;
|
vexpr = TREE_OPERAND (vexpr, 0);
|
||||||
|
|
||||||
if (!DECL_NAME (parm))
|
if (TREE_CODE (vexpr) == PARM_DECL
|
||||||
continue;
|
&& DECL_ARTIFICIAL (vexpr)
|
||||||
|
&& !DECL_IGNORED_P (vexpr)
|
||||||
if (!decl_rtl || !incoming)
|
&& DECL_NAMELESS (vexpr))
|
||||||
continue;
|
vt_add_function_parameter (vexpr);
|
||||||
|
|
||||||
if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!vt_get_decl_and_offset (incoming, &decl, &offset))
|
|
||||||
{
|
|
||||||
if (REG_P (incoming) || MEM_P (incoming))
|
|
||||||
{
|
|
||||||
/* This means argument is passed by invisible reference. */
|
|
||||||
offset = 0;
|
|
||||||
decl = parm;
|
|
||||||
incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
|
|
||||||
continue;
|
|
||||||
offset += byte_lowpart_offset (GET_MODE (incoming),
|
|
||||||
GET_MODE (decl_rtl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!decl)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (parm != decl)
|
|
||||||
{
|
|
||||||
/* Assume that DECL_RTL was a pseudo that got spilled to
|
|
||||||
memory. The spill slot sharing code will force the
|
|
||||||
memory to reference spill_slot_decl (%sfp), so we don't
|
|
||||||
match above. That's ok, the pseudo must have referenced
|
|
||||||
the entire parameter, so just reset OFFSET. */
|
|
||||||
gcc_assert (decl == get_spill_slot_decl (false));
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
out = &VTI (ENTRY_BLOCK_PTR)->out;
|
|
||||||
|
|
||||||
dv = dv_from_decl (parm);
|
|
||||||
|
|
||||||
if (target_for_debug_bind (parm)
|
|
||||||
/* We can't deal with these right now, because this kind of
|
|
||||||
variable is single-part. ??? We could handle parallels
|
|
||||||
that describe multiple locations for the same single
|
|
||||||
value, but ATM we don't. */
|
|
||||||
&& GET_CODE (incoming) != PARALLEL)
|
|
||||||
{
|
|
||||||
cselib_val *val;
|
|
||||||
|
|
||||||
/* ??? We shouldn't ever hit this, but it may happen because
|
|
||||||
arguments passed by invisible reference aren't dealt with
|
|
||||||
above: incoming-rtl will have Pmode rather than the
|
|
||||||
expected mode for the type. */
|
|
||||||
if (offset)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
|
|
||||||
|
|
||||||
/* ??? Float-typed values in memory are not handled by
|
|
||||||
cselib. */
|
|
||||||
if (val)
|
|
||||||
{
|
|
||||||
preserve_value (val);
|
|
||||||
set_variable_part (out, val->val_rtx, dv, offset,
|
|
||||||
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
|
||||||
dv = dv_from_value (val->val_rtx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REG_P (incoming))
|
|
||||||
{
|
|
||||||
incoming = var_lowpart (mode, incoming);
|
|
||||||
gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
|
|
||||||
attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
|
|
||||||
incoming);
|
|
||||||
set_variable_part (out, incoming, dv, offset,
|
|
||||||
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
|
||||||
}
|
|
||||||
else if (MEM_P (incoming))
|
|
||||||
{
|
|
||||||
incoming = var_lowpart (mode, incoming);
|
|
||||||
set_variable_part (out, incoming, dv, offset,
|
|
||||||
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MAY_HAVE_DEBUG_INSNS)
|
if (MAY_HAVE_DEBUG_INSNS)
|
||||||
|
Loading…
Reference in New Issue
Block a user