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);
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++)
{
for (i = 0; i < num_actuals; ++i)
free (args[i].aligned_regs);
+ targetm.calls.end_call_args ();
+
insns = get_insns ();
end_sequence ();
}
#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
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
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
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\