aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.cc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2023-12-05 09:44:52 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2023-12-05 09:44:52 +0000
commit672fad57c1f99ff893019e2da4620e26b9b31dd2 (patch)
tree30d06172a99e58577072b0122069e80c052e38a9 /gcc/calls.cc
parent4f71c391ca020e5b080116826658b2c94ee32eb0 (diff)
downloadgcc-672fad57c1f99ff893019e2da4620e26b9b31dd2.zip
gcc-672fad57c1f99ff893019e2da4620e26b9b31dd2.tar.gz
gcc-672fad57c1f99ff893019e2da4620e26b9b31dd2.tar.bz2
Add a new target hook: TARGET_START_CALL_ARGS
We have the following two hooks into the call expansion code: - TARGET_CALL_ARGS is called for each argument before arguments are moved into hard registers. - TARGET_END_CALL_ARGS is called after the end of the call sequence (specifically, after any return value has been moved to a pseudo). This patch adds a TARGET_START_CALL_ARGS hook that is called before the TARGET_CALL_ARGS sequence. This means that TARGET_START_CALL_REGS and TARGET_END_CALL_REGS bracket the region in which argument registers might be live. They also bracket a region in which the only call emiitted by target-independent code is the call to the target function itself. (For example, TARGET_START_CALL_ARGS happens after any use of memcpy to copy arguments, and TARGET_END_CALL_ARGS happens before any use of memcpy to copy the result.) Also, the patch adds the cumulative argument structure as an argument to the hooks, so that the target can use it to record and retrieve information about the call as a whole. The TARGET_CALL_ARGS docs said: 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 ``TARGET_FUNCTION_ARG`` or a memory location. It is called just - before the point where argument registers are stored. The last bit was true for normal calls, but for libcalls the hook was invoked earlier, before stack arguments have been copied. I don't think this caused a practical difference for nvptx (the only port to use the hooks) since I wouldn't expect any libcalls to take stack parameters. gcc/ * doc/tm.texi.in: Add TARGET_START_CALL_ARGS. * doc/tm.texi: Regenerate. * target.def (start_call_args): New hook. (call_args, end_call_args): Add a parameter for the cumulative argument information. * hooks.h (hook_void_rtx_tree): Delete. * hooks.cc (hook_void_rtx_tree): Likewise. * targhooks.h (hook_void_CUMULATIVE_ARGS): Declare. (hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise. * targhooks.cc (hook_void_CUMULATIVE_ARGS): New function. (hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise. * calls.cc (expand_call): Call start_call_args before computing and storing stack parameters. Pass the cumulative argument information to call_args and end_call_args. (emit_library_call_value_1): Likewise. * config/nvptx/nvptx.cc (nvptx_call_args): Add a cumulative argument parameter. (nvptx_end_call_args): Likewise.
Diffstat (limited to 'gcc/calls.cc')
-rw-r--r--gcc/calls.cc61
1 files changed, 33 insertions, 28 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc
index cc4210c..4a1aea1 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -3563,15 +3563,26 @@ expand_call (tree exp, rtx target, int ignore)
sibcall_failure = true;
}
+ /* Set up the next argument register. For sibling calls on machines
+ with register windows this should be the incoming register. */
+ if (pass == 0)
+ next_arg_reg = targetm.calls.function_incoming_arg
+ (args_so_far, function_arg_info::end_marker ());
+ else
+ next_arg_reg = targetm.calls.function_arg
+ (args_so_far, function_arg_info::end_marker ());
+
+ targetm.calls.start_call_args (args_so_far);
+
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);
+ targetm.calls.call_args (args_so_far, args[i].reg, funtype);
}
if (!any_regs)
- targetm.calls.call_args (pc_rtx, funtype);
+ targetm.calls.call_args (args_so_far, pc_rtx, funtype);
/* Figure out the register where the value, if any, will come back. */
valreg = 0;
@@ -3634,15 +3645,6 @@ expand_call (tree exp, rtx target, int ignore)
later safely search backwards to find the CALL_INSN. */
before_call = get_last_insn ();
- /* Set up next argument register. For sibling calls on machines
- with register windows this should be the incoming register. */
- if (pass == 0)
- next_arg_reg = targetm.calls.function_incoming_arg
- (args_so_far, function_arg_info::end_marker ());
- else
- next_arg_reg = targetm.calls.function_arg
- (args_so_far, function_arg_info::end_marker ());
-
if (pass == 1 && (return_flags & ERF_RETURNS_ARG))
{
int arg_nr = return_flags & ERF_RETURN_ARG_MASK;
@@ -3941,7 +3943,7 @@ 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 ();
+ targetm.calls.end_call_args (args_so_far);
insns = get_insns ();
end_sequence ();
@@ -4499,17 +4501,9 @@ 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);
+ rtx call_cookie
+ = targetm.calls.function_arg (args_so_far,
+ function_arg_info::end_marker ());
/* Push the args that need to be pushed. */
@@ -4627,6 +4621,20 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
fun = prepare_call_address (NULL, fun, NULL, &call_fusage, 0, 0);
+ targetm.calls.start_call_args (args_so_far);
+
+ /* 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 (args_so_far, argvec[i].reg, NULL_TREE);
+ any_regs = true;
+ }
+ if (!any_regs)
+ targetm.calls.call_args (args_so_far, pc_rtx, NULL_TREE);
+
/* Now load any reg parms into their regs. */
/* ARGNUM indexes the ARGVEC array in the order in which the arguments
@@ -4733,10 +4741,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
get_identifier (XSTR (orgfun, 0)),
build_function_type (tfom, NULL_TREE),
original_args_size.constant, args_size.constant,
- struct_value_size,
- targetm.calls.function_arg (args_so_far,
- function_arg_info::end_marker ()),
- valreg,
+ struct_value_size, call_cookie, valreg,
old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far);
if (flag_ipa_ra)
@@ -4756,7 +4761,7 @@ 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 ();
+ targetm.calls.end_call_args (args_so_far);
/* For calls to `setjmp', etc., inform function.cc:setjmp_warnings
that it should complain if nonvolatile values are live. For