mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 11:31:05 +08:00
Add a hook to inform a port about call arguments.
* target.def (call_args, end_call_args): New hooks. * hooks.c (hook_void_rtx_tree): New empty function. * hooks.h (hook_void_rtx_tree): Declare. * doc/tm.texi.in (TARGET_CALL_ARGS, TARGET_END_CALL_ARGS): Add. * doc/tm.texi: Regenerate. * calls.c (expand_call): Slightly rearrange the code. Use the two new hooks. (expand_library_call_value_1): Use the two new hooks. From-SVN: r217199
This commit is contained in:
parent
11717c64bf
commit
2f21e1ba46
@ -1,5 +1,14 @@
|
||||
2014-11-06 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
* target.def (call_args, end_call_args): New hooks.
|
||||
* hooks.c (hook_void_rtx_tree): New empty function.
|
||||
* hooks.h (hook_void_rtx_tree): Declare.
|
||||
* doc/tm.texi.in (TARGET_CALL_ARGS, TARGET_END_CALL_ARGS): Add.
|
||||
* doc/tm.texi: Regenerate.
|
||||
* calls.c (expand_call): Slightly rearrange the code. Use the two new
|
||||
hooks.
|
||||
(expand_library_call_value_1): Use the two new hooks.
|
||||
|
||||
* expr.c (use_reg_mode): Just return for pseudo registers.
|
||||
|
||||
* combine.c (try_combine): Don't allow a call as one of the source
|
||||
|
104
gcc/calls.c
104
gcc/calls.c
@ -3103,45 +3103,6 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
|
||||
funexp = rtx_for_function_call (fndecl, addr);
|
||||
|
||||
/* Figure out the register where the value, if any, will come back. */
|
||||
valreg = 0;
|
||||
valbnd = 0;
|
||||
if (TYPE_MODE (rettype) != VOIDmode
|
||||
&& ! structure_value_addr)
|
||||
{
|
||||
if (pcc_struct_value)
|
||||
{
|
||||
valreg = hard_function_value (build_pointer_type (rettype),
|
||||
fndecl, NULL, (pass == 0));
|
||||
if (CALL_WITH_BOUNDS_P (exp))
|
||||
valbnd = targetm.calls.
|
||||
chkp_function_value_bounds (build_pointer_type (rettype),
|
||||
fndecl, (pass == 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
valreg = hard_function_value (rettype, fndecl, fntype,
|
||||
(pass == 0));
|
||||
if (CALL_WITH_BOUNDS_P (exp))
|
||||
valbnd = targetm.calls.chkp_function_value_bounds (rettype,
|
||||
fndecl,
|
||||
(pass == 0));
|
||||
}
|
||||
|
||||
/* If VALREG is a PARALLEL whose first member has a zero
|
||||
offset, use that. This is for targets such as m68k that
|
||||
return the same value in multiple places. */
|
||||
if (GET_CODE (valreg) == PARALLEL)
|
||||
{
|
||||
rtx elem = XVECEXP (valreg, 0, 0);
|
||||
rtx where = XEXP (elem, 0);
|
||||
rtx offset = XEXP (elem, 1);
|
||||
if (offset == const0_rtx
|
||||
&& GET_MODE (where) == GET_MODE (valreg))
|
||||
valreg = where;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precompute all register parameters. It isn't safe to compute anything
|
||||
once we have started filling any specific hard regs. */
|
||||
precompute_register_parameters (num_actuals, args, ®_parm_seen);
|
||||
@ -3223,6 +3184,55 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
sibcall_failure = 1;
|
||||
}
|
||||
|
||||
bool any_regs = false;
|
||||
for (i = 0; i < num_actuals; i++)
|
||||
if (args[i].reg != NULL_RTX)
|
||||
{
|
||||
any_regs = true;
|
||||
targetm.calls.call_args (args[i].reg, funtype);
|
||||
}
|
||||
if (!any_regs)
|
||||
targetm.calls.call_args (pc_rtx, funtype);
|
||||
|
||||
/* Figure out the register where the value, if any, will come back. */
|
||||
valreg = 0;
|
||||
valbnd = 0;
|
||||
if (TYPE_MODE (rettype) != VOIDmode
|
||||
&& ! structure_value_addr)
|
||||
{
|
||||
if (pcc_struct_value)
|
||||
{
|
||||
valreg = hard_function_value (build_pointer_type (rettype),
|
||||
fndecl, NULL, (pass == 0));
|
||||
if (CALL_WITH_BOUNDS_P (exp))
|
||||
valbnd = targetm.calls.
|
||||
chkp_function_value_bounds (build_pointer_type (rettype),
|
||||
fndecl, (pass == 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
valreg = hard_function_value (rettype, fndecl, fntype,
|
||||
(pass == 0));
|
||||
if (CALL_WITH_BOUNDS_P (exp))
|
||||
valbnd = targetm.calls.chkp_function_value_bounds (rettype,
|
||||
fndecl,
|
||||
(pass == 0));
|
||||
}
|
||||
|
||||
/* If VALREG is a PARALLEL whose first member has a zero
|
||||
offset, use that. This is for targets such as m68k that
|
||||
return the same value in multiple places. */
|
||||
if (GET_CODE (valreg) == PARALLEL)
|
||||
{
|
||||
rtx elem = XVECEXP (valreg, 0, 0);
|
||||
rtx where = XEXP (elem, 0);
|
||||
rtx offset = XEXP (elem, 1);
|
||||
if (offset == const0_rtx
|
||||
&& GET_MODE (where) == GET_MODE (valreg))
|
||||
valreg = where;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store all bounds not passed in registers. */
|
||||
for (i = 0; i < num_actuals; i++)
|
||||
{
|
||||
@ -3582,6 +3592,8 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
for (i = 0; i < num_actuals; ++i)
|
||||
free (args[i].aligned_regs);
|
||||
|
||||
targetm.calls.end_call_args ();
|
||||
|
||||
insns = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
@ -4111,6 +4123,18 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* When expanding a normal call, args are stored in push order,
|
||||
which is the reverse of what we have here. */
|
||||
bool any_regs = false;
|
||||
for (int i = nargs; i-- > 0; )
|
||||
if (argvec[i].reg != NULL_RTX)
|
||||
{
|
||||
targetm.calls.call_args (argvec[i].reg, NULL_TREE);
|
||||
any_regs = true;
|
||||
}
|
||||
if (!any_regs)
|
||||
targetm.calls.call_args (pc_rtx, NULL_TREE);
|
||||
|
||||
/* Push the args that need to be pushed. */
|
||||
|
||||
/* ARGNUM indexes the ARGVEC array in the order in which the arguments
|
||||
@ -4351,6 +4375,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|
||||
valreg = gen_rtx_REG (TYPE_MODE (tfom), REGNO (valreg));
|
||||
}
|
||||
|
||||
targetm.calls.end_call_args ();
|
||||
|
||||
/* For calls to `setjmp', etc., inform function.c:setjmp_warnings
|
||||
that it should complain if nonvolatile values are live. For
|
||||
functions that cannot return, inform flow that control does not
|
||||
|
@ -4976,6 +4976,29 @@ except the last are treated as named.
|
||||
You need not define this hook if it always returns @code{false}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_CALL_ARGS (rtx, @var{tree})
|
||||
While generating RTL for a function call, this target hook is invoked once
|
||||
for each argument passed to the function, either a register returned by
|
||||
@code{TARGET_FUNCTION_ARG} or a memory location. It is called just
|
||||
before the point where argument registers are stored. The type of the
|
||||
function to be called is also passed as the second argument; it is
|
||||
@code{NULL_TREE} for libcalls. The @code{TARGET_END_CALL_ARGS} hook is
|
||||
invoked just after the code to copy the return reg has been emitted.
|
||||
This functionality can be used to perform special setup of call argument
|
||||
registers if a target needs it.
|
||||
For functions without arguments, the hook is called once with @code{pc_rtx}
|
||||
passed instead of an argument register.
|
||||
Most ports do not need to implement anything for this hook.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (void)
|
||||
This target hook is invoked while generating RTL for a function call,
|
||||
just after the point where the return reg is copied into a pseudo. It
|
||||
signals that all the call argument and return registers for the just
|
||||
emitted call are now no longer in use.
|
||||
Most ports do not need to implement anything for this hook.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_PRETEND_OUTGOING_VARARGS_NAMED (cumulative_args_t @var{ca})
|
||||
If you need to conditionally change ABIs so that one works with
|
||||
@code{TARGET_SETUP_INCOMING_VARARGS}, but the other works like neither
|
||||
|
@ -3860,6 +3860,10 @@ These machine description macros help implement varargs:
|
||||
|
||||
@hook TARGET_STRICT_ARGUMENT_NAMING
|
||||
|
||||
@hook TARGET_CALL_ARGS
|
||||
|
||||
@hook TARGET_END_CALL_ARGS
|
||||
|
||||
@hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED
|
||||
|
||||
@hook TARGET_LOAD_BOUNDS_FOR_ARG
|
||||
|
@ -244,6 +244,11 @@ hook_void_tree (tree a ATTRIBUTE_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
hook_void_rtx_tree (rtx, tree)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
hook_void_constcharptr (const char *a ATTRIBUTE_UNUSED)
|
||||
{
|
||||
|
@ -71,6 +71,7 @@ extern void hook_void_constcharptr (const char *);
|
||||
extern void hook_void_rtx_insn_int (rtx_insn *, int);
|
||||
extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
|
||||
extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx);
|
||||
extern void hook_void_rtx_tree (rtx, tree);
|
||||
extern void hook_void_tree (tree);
|
||||
extern void hook_void_tree_treeptr (tree, tree *);
|
||||
extern void hook_void_int_int (int, int);
|
||||
|
@ -4001,6 +4001,33 @@ into the stack. Arguments meaning is similar to\n\
|
||||
int *pretend_args_size, int second_time),
|
||||
default_setup_incoming_vararg_bounds)
|
||||
|
||||
DEFHOOK
|
||||
(call_args,
|
||||
"While generating RTL for a function call, this target hook is invoked once\n\
|
||||
for each argument passed to the function, either a register returned by\n\
|
||||
@code{TARGET_FUNCTION_ARG} or a memory location. It is called just\n\
|
||||
before the point where argument registers are stored. The type of the\n\
|
||||
function to be called is also passed as the second argument; it is\n\
|
||||
@code{NULL_TREE} for libcalls. The @code{TARGET_END_CALL_ARGS} hook is\n\
|
||||
invoked just after the code to copy the return reg has been emitted.\n\
|
||||
This functionality can be used to perform special setup of call argument\n\
|
||||
registers if a target needs it.\n\
|
||||
For functions without arguments, the hook is called once with @code{pc_rtx}\n\
|
||||
passed instead of an argument register.\n\
|
||||
Most ports do not need to implement anything for this hook.",
|
||||
void, (rtx, tree),
|
||||
hook_void_rtx_tree)
|
||||
|
||||
DEFHOOK
|
||||
(end_call_args,
|
||||
"This target hook is invoked while generating RTL for a function call,\n\
|
||||
just after the point where the return reg is copied into a pseudo. It\n\
|
||||
signals that all the call argument and return registers for the just\n\
|
||||
emitted call are now no longer in use.\n\
|
||||
Most ports do not need to implement anything for this hook.",
|
||||
void, (void),
|
||||
hook_void_void)
|
||||
|
||||
DEFHOOK
|
||||
(strict_argument_naming,
|
||||
"Define this hook to return @code{true} if the location where a function\n\
|
||||
|
Loading…
x
Reference in New Issue
Block a user