for gcc/ChangeLog
from 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.
===================================================================
@@ -2253,10 +2253,11 @@ assign_parms_augmented_arg_list (struct
tree decl;
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_ARTIFICIAL (decl) = 1;
- DECL_IGNORED_P (decl) = 1;
+ DECL_NAMELESS (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
DECL_CHAIN (decl) = all->orig_fnargs;
all->orig_fnargs = decl;
@@ -3418,13 +3419,22 @@ assign_parms (tree fndecl)
rtx x;
if (DECL_BY_REFERENCE (result))
- x = addr;
+ {
+ SET_DECL_VALUE_EXPR (result, all.function_result_decl);
+ x = addr;
+ }
else
{
+ SET_DECL_VALUE_EXPR (result,
+ build1 (INDIRECT_REF, TREE_TYPE (result),
+ all.function_result_decl));
addr = convert_memory_address (Pmode, addr);
x = gen_rtx_MEM (DECL_MODE (result), addr);
set_mem_attributes (x, result, 1);
}
+
+ DECL_HAS_VALUE_EXPR_P (result) = 1;
+
SET_DECL_RTL (result, x);
}
===================================================================
@@ -2773,7 +2773,8 @@ struct GTY(()) tree_decl_common {
In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */
unsigned decl_flag_1 : 1;
/* 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;
/* Logically, these two would go in a theoretical base shared by var and
parm decl. */
@@ -2818,7 +2819,8 @@ extern void decl_value_expr_insert (tree
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. */
#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) \
(decl_value_expr_lookup (DECL_WRTL_CHECK (NODE)))
#define SET_DECL_VALUE_EXPR(NODE, VAL) \
===================================================================
@@ -15446,12 +15446,12 @@ loc_list_from_tree (tree loc, int want_a
/* FALLTHRU */
case PARM_DECL:
+ case RESULT_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;
===================================================================
@@ -2396,12 +2396,12 @@ dbxout_expand_expr (tree expr)
/* FALLTHRU */
case PARM_DECL:
+ case RESULT_DECL:
if (DECL_HAS_VALUE_EXPR_P (expr))
return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
/* FALLTHRU */
case CONST_DECL:
- case RESULT_DECL:
return DECL_RTL_IF_SET (expr);
case INTEGER_CST:
===================================================================
@@ -7999,121 +7999,136 @@ vt_get_decl_and_offset (rtx rtl, tree *d
return false;
}
-/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
-
static void
-vt_add_function_parameters (void)
+vt_add_function_parameter (tree parm)
{
- 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;
- for (parm = DECL_ARGUMENTS (current_function_decl);
- parm; parm = DECL_CHAIN (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)
- continue;
-
- if (!DECL_NAME (parm))
- continue;
+ if (TREE_CODE (parm) != PARM_DECL)
+ return;
- if (!decl_rtl || !incoming)
- continue;
+ if (!decl_rtl || !incoming)
+ return;
- if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
- continue;
+ if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
+ return;
- if (!vt_get_decl_and_offset (incoming, &decl, &offset))
+ if (!vt_get_decl_and_offset (incoming, &decl, &offset))
+ {
+ if (REG_P (incoming) || MEM_P (incoming))
{
- 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));
- }
+ /* This means argument is passed by invisible reference. */
+ offset = 0;
+ decl = parm;
+ incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
}
-
- if (!decl)
- continue;
-
- if (parm != decl)
+ else
{
- /* 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 (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
+ return;
+ offset += byte_lowpart_offset (GET_MODE (incoming),
+ GET_MODE (decl_rtl));
}
+ }
- if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
- continue;
+ if (!decl)
+ return;
- out = &VTI (ENTRY_BLOCK_PTR)->out;
+ 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;
+ }
- dv = dv_from_decl (parm);
+ if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
+ return;
- 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;
+ out = &VTI (ENTRY_BLOCK_PTR)->out;
- /* ??? 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);
- }
- }
+ dv = dv_from_decl (parm);
- if (REG_P (incoming))
+ 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)
{
- 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,
+ 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. */
+
+static void
+vt_add_function_parameters (void)
+{
+ tree parm;
+
+ for (parm = DECL_ARGUMENTS (current_function_decl);
+ parm; parm = DECL_CHAIN (parm))
+ vt_add_function_parameter (parm);
+
+ if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
+ {
+ tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl));
+
+ if (TREE_CODE (vexpr) == INDIRECT_REF)
+ vexpr = TREE_OPERAND (vexpr, 0);
+
+ if (TREE_CODE (vexpr) == PARM_DECL
+ && DECL_ARTIFICIAL (vexpr)
+ && !DECL_IGNORED_P (vexpr)
+ && DECL_NAMELESS (vexpr))
+ vt_add_function_parameter (vexpr);
+ }
+
if (MAY_HAVE_DEBUG_INSNS)
{
cselib_preserve_only_values ();