calls.c (emit_call_1): Set MEM_EXPR on call's MEM.
* calls.c (emit_call_1): Set MEM_EXPR on call's MEM. * var-tracking.c (prepare_call_arguments): Use MEM_EXPR on call's MEM. Handle functions returning aggregate through a hidden first pointer. For virtual calls add clobbered pc to call arguments chain. * dwarf2out.c (gen_subprogram_die): Emit DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target can't be emitted. From-SVN: r171036
This commit is contained in:
parent
a58a8e4b1f
commit
325f5379f1
|
@ -1,5 +1,14 @@
|
|||
2011-03-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* calls.c (emit_call_1): Set MEM_EXPR on call's MEM.
|
||||
* var-tracking.c (prepare_call_arguments): Use MEM_EXPR on
|
||||
call's MEM. Handle functions returning aggregate through a hidden
|
||||
first pointer. For virtual calls add clobbered pc to call arguments
|
||||
chain.
|
||||
* dwarf2out.c (gen_subprogram_die): Emit
|
||||
DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target
|
||||
can't be emitted.
|
||||
|
||||
PR debug/45882
|
||||
* rtl.def (ENTRY_VALUE): Change format from "e" to "0".
|
||||
* rtl.h (ENTRY_VALUE_EXP): Define.
|
||||
|
|
56
gcc/calls.c
56
gcc/calls.c
|
@ -256,7 +256,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED)
|
||||
{
|
||||
rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
|
||||
rtx call_insn;
|
||||
rtx call_insn, call, funmem;
|
||||
int already_popped = 0;
|
||||
HOST_WIDE_INT n_popped
|
||||
= targetm.calls.return_pops_args (fndecl, funtype, stack_size);
|
||||
|
@ -271,6 +271,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
if (GET_CODE (funexp) != SYMBOL_REF)
|
||||
funexp = memory_address (FUNCTION_MODE, funexp);
|
||||
|
||||
funmem = gen_rtx_MEM (FUNCTION_MODE, funexp);
|
||||
if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
|
||||
set_mem_expr (funmem, fndecl);
|
||||
else if (fntree)
|
||||
set_mem_expr (funmem, build_fold_indirect_ref (CALL_EXPR_FN (fntree)));
|
||||
|
||||
#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
|
||||
if ((ecf_flags & ECF_SIBCALL)
|
||||
&& HAVE_sibcall_pop && HAVE_sibcall_value_pop
|
||||
|
@ -283,13 +289,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
if possible, for the sake of frame pointer elimination. */
|
||||
|
||||
if (valreg)
|
||||
pat = GEN_SIBCALL_VALUE_POP (valreg,
|
||||
gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg,
|
||||
n_pop);
|
||||
pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
|
||||
next_arg_reg, n_pop);
|
||||
else
|
||||
pat = GEN_SIBCALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg, n_pop);
|
||||
pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
|
||||
n_pop);
|
||||
|
||||
emit_call_insn (pat);
|
||||
already_popped = 1;
|
||||
|
@ -316,12 +320,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
if possible, for the sake of frame pointer elimination. */
|
||||
|
||||
if (valreg)
|
||||
pat = GEN_CALL_VALUE_POP (valreg,
|
||||
gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg, n_pop);
|
||||
pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
|
||||
next_arg_reg, n_pop);
|
||||
else
|
||||
pat = GEN_CALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg, n_pop);
|
||||
pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
|
||||
n_pop);
|
||||
|
||||
emit_call_insn (pat);
|
||||
already_popped = 1;
|
||||
|
@ -334,13 +337,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
&& HAVE_sibcall && HAVE_sibcall_value)
|
||||
{
|
||||
if (valreg)
|
||||
emit_call_insn (GEN_SIBCALL_VALUE (valreg,
|
||||
gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem,
|
||||
rounded_stack_size_rtx,
|
||||
next_arg_reg, NULL_RTX));
|
||||
else
|
||||
emit_call_insn (GEN_SIBCALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg,
|
||||
emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx,
|
||||
next_arg_reg,
|
||||
GEN_INT (struct_value_size)));
|
||||
}
|
||||
else
|
||||
|
@ -350,13 +352,10 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
if (HAVE_call && HAVE_call_value)
|
||||
{
|
||||
if (valreg)
|
||||
emit_call_insn (GEN_CALL_VALUE (valreg,
|
||||
gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg,
|
||||
NULL_RTX));
|
||||
emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx,
|
||||
next_arg_reg, NULL_RTX));
|
||||
else
|
||||
emit_call_insn (GEN_CALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
|
||||
rounded_stack_size_rtx, next_arg_reg,
|
||||
emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg,
|
||||
GEN_INT (struct_value_size)));
|
||||
}
|
||||
else
|
||||
|
@ -366,6 +365,19 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
|
|||
/* Find the call we just emitted. */
|
||||
call_insn = last_call_insn ();
|
||||
|
||||
/* Some target create a fresh MEM instead of reusing the one provided
|
||||
above. Set its MEM_EXPR. */
|
||||
call = PATTERN (call_insn);
|
||||
if (GET_CODE (call) == PARALLEL)
|
||||
call = XVECEXP (call, 0, 0);
|
||||
if (GET_CODE (call) == SET)
|
||||
call = SET_SRC (call);
|
||||
if (GET_CODE (call) == CALL
|
||||
&& MEM_P (XEXP (call, 0))
|
||||
&& MEM_EXPR (XEXP (call, 0)) == NULL_TREE
|
||||
&& MEM_EXPR (funmem) != NULL_TREE)
|
||||
set_mem_expr (XEXP (call, 0), MEM_EXPR (funmem));
|
||||
|
||||
/* Put the register usage information there. */
|
||||
add_function_usage_to (call_insn, call_fusage);
|
||||
|
||||
|
|
|
@ -19615,7 +19615,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
|||
for (ca_loc = call_arg_locations; ca_loc; ca_loc = ca_loc->next)
|
||||
{
|
||||
dw_die_ref die = NULL;
|
||||
rtx tloc = NULL_RTX;
|
||||
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
|
||||
rtx arg, next_arg;
|
||||
|
||||
for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
|
||||
|
@ -19644,6 +19644,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
|||
tloc = XEXP (XEXP (arg, 0), 1);
|
||||
continue;
|
||||
}
|
||||
else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
|
||||
&& XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
|
||||
{
|
||||
gcc_assert (ca_loc->symbol_ref == NULL_RTX);
|
||||
tlocc = XEXP (XEXP (arg, 0), 1);
|
||||
continue;
|
||||
}
|
||||
if (REG_P (XEXP (XEXP (arg, 0), 0)))
|
||||
reg = reg_loc_descriptor (XEXP (XEXP (arg, 0), 0),
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
|
@ -19677,13 +19684,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
|||
if (die == NULL
|
||||
&& (ca_loc->symbol_ref || tloc))
|
||||
die = gen_call_site_die (decl, subr_die, ca_loc);
|
||||
if (die != NULL && tloc != NULL_RTX)
|
||||
if (die != NULL && (tloc != NULL_RTX || tlocc != NULL_RTX))
|
||||
{
|
||||
dw_loc_descr_ref tval
|
||||
= mem_loc_descriptor (tloc, VOIDmode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
dw_loc_descr_ref tval = NULL;
|
||||
|
||||
if (tloc != NULL_RTX)
|
||||
tval = mem_loc_descriptor (tloc, VOIDmode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
if (tval)
|
||||
add_AT_loc (die, DW_AT_GNU_call_site_target, tval);
|
||||
else if (tlocc != NULL_RTX)
|
||||
{
|
||||
tval = mem_loc_descriptor (tlocc, VOIDmode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
if (tval)
|
||||
add_AT_loc (die, DW_AT_GNU_call_site_target_clobbered,
|
||||
tval);
|
||||
}
|
||||
}
|
||||
if (die != NULL)
|
||||
{
|
||||
|
|
|
@ -5576,7 +5576,9 @@ prepare_call_arguments (basic_block bb, rtx insn)
|
|||
rtx link, x;
|
||||
rtx prev, cur, next;
|
||||
rtx call = PATTERN (insn);
|
||||
tree type = NULL_TREE, t;
|
||||
rtx this_arg = NULL_RTX;
|
||||
tree type = NULL_TREE, t, fndecl = NULL_TREE;
|
||||
tree obj_type_ref = NULL_TREE;
|
||||
CUMULATIVE_ARGS args_so_far;
|
||||
|
||||
memset (&args_so_far, 0, sizeof (args_so_far));
|
||||
|
@ -5584,27 +5586,91 @@ prepare_call_arguments (basic_block bb, rtx insn)
|
|||
call = XVECEXP (call, 0, 0);
|
||||
if (GET_CODE (call) == SET)
|
||||
call = SET_SRC (call);
|
||||
if (GET_CODE (call) == CALL
|
||||
&& MEM_P (XEXP (call, 0))
|
||||
&& GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
|
||||
if (GET_CODE (call) == CALL && MEM_P (XEXP (call, 0)))
|
||||
{
|
||||
rtx symbol = XEXP (XEXP (call, 0), 0);
|
||||
if (SYMBOL_REF_DECL (symbol)
|
||||
&& TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL
|
||||
&& TYPE_ARG_TYPES (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
|
||||
if (GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
|
||||
{
|
||||
rtx symbol = XEXP (XEXP (call, 0), 0);
|
||||
if (SYMBOL_REF_DECL (symbol))
|
||||
fndecl = SYMBOL_REF_DECL (symbol);
|
||||
}
|
||||
if (fndecl == NULL_TREE)
|
||||
fndecl = MEM_EXPR (XEXP (call, 0));
|
||||
if (fndecl
|
||||
&& TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
|
||||
fndecl = NULL_TREE;
|
||||
if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
|
||||
type = TREE_TYPE (fndecl);
|
||||
if (fndecl && TREE_CODE (fndecl) != FUNCTION_DECL)
|
||||
{
|
||||
if (TREE_CODE (fndecl) == INDIRECT_REF
|
||||
&& TREE_CODE (TREE_OPERAND (fndecl, 0)) == OBJ_TYPE_REF)
|
||||
obj_type_ref = TREE_OPERAND (fndecl, 0);
|
||||
fndecl = NULL_TREE;
|
||||
}
|
||||
if (type)
|
||||
{
|
||||
type = TREE_TYPE (SYMBOL_REF_DECL (symbol));
|
||||
for (t = TYPE_ARG_TYPES (type); t && t != void_list_node;
|
||||
t = TREE_CHAIN (t))
|
||||
if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t))))
|
||||
break;
|
||||
if (t == NULL || t == void_list_node)
|
||||
if ((t == NULL || t == void_list_node) && obj_type_ref == NULL_TREE)
|
||||
type = NULL;
|
||||
else
|
||||
INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX,
|
||||
SYMBOL_REF_DECL (symbol),
|
||||
list_length (TYPE_ARG_TYPES (type)));
|
||||
{
|
||||
int nargs = list_length (TYPE_ARG_TYPES (type));
|
||||
link = CALL_INSN_FUNCTION_USAGE (insn);
|
||||
#ifndef PCC_STATIC_STRUCT_RETURN
|
||||
if (aggregate_value_p (TREE_TYPE (type), type)
|
||||
&& targetm.calls.struct_value_rtx (type, 0) == 0)
|
||||
{
|
||||
tree struct_addr = build_pointer_type (TREE_TYPE (type));
|
||||
enum machine_mode mode = TYPE_MODE (struct_addr);
|
||||
rtx reg;
|
||||
INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl,
|
||||
nargs + 1);
|
||||
reg = targetm.calls.function_arg (&args_so_far, mode,
|
||||
struct_addr, true);
|
||||
targetm.calls.function_arg_advance (&args_so_far, mode,
|
||||
struct_addr, true);
|
||||
if (reg == NULL_RTX)
|
||||
{
|
||||
for (; link; link = XEXP (link, 1))
|
||||
if (GET_CODE (XEXP (link, 0)) == USE
|
||||
&& MEM_P (XEXP (XEXP (link, 0), 0)))
|
||||
{
|
||||
link = XEXP (link, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl,
|
||||
nargs);
|
||||
if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
t = TYPE_ARG_TYPES (type);
|
||||
mode = TYPE_MODE (TREE_VALUE (t));
|
||||
this_arg = targetm.calls.function_arg (&args_so_far, mode,
|
||||
TREE_VALUE (t), true);
|
||||
if (this_arg && !REG_P (this_arg))
|
||||
this_arg = NULL_RTX;
|
||||
else if (this_arg == NULL_RTX)
|
||||
{
|
||||
for (; link; link = XEXP (link, 1))
|
||||
if (GET_CODE (XEXP (link, 0)) == USE
|
||||
&& MEM_P (XEXP (XEXP (link, 0), 0)))
|
||||
{
|
||||
this_arg = XEXP (XEXP (link, 0), 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = type ? TYPE_ARG_TYPES (type) : NULL_TREE;
|
||||
|
@ -5752,6 +5818,20 @@ prepare_call_arguments (basic_block bb, rtx insn)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (this_arg)
|
||||
{
|
||||
enum machine_mode mode
|
||||
= TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
|
||||
rtx clobbered = gen_rtx_MEM (mode, this_arg);
|
||||
HOST_WIDE_INT token
|
||||
= tree_low_cst (OBJ_TYPE_REF_TOKEN (obj_type_ref), 0);
|
||||
if (token)
|
||||
clobbered = plus_constant (clobbered, token * GET_MODE_SIZE (mode));
|
||||
clobbered = gen_rtx_MEM (mode, clobbered);
|
||||
x = gen_rtx_CONCAT (mode, gen_rtx_CLOBBER (VOIDmode, pc_rtx), clobbered);
|
||||
call_arguments
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback for cselib_record_sets_hook, that records as micro
|
||||
|
|
Loading…
Reference in New Issue