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:
Jakub Jelinek 2011-03-16 09:36:42 +01:00 committed by Jakub Jelinek
parent a58a8e4b1f
commit 325f5379f1
4 changed files with 158 additions and 40 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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)
{

View File

@ -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