aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/calls.cc61
-rw-r--r--gcc/config/nvptx/nvptx.cc4
-rw-r--r--gcc/doc/tm.texi53
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/hooks.cc5
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/target.def59
-rw-r--r--gcc/targhooks.cc10
-rw-r--r--gcc/targhooks.h5
9 files changed, 140 insertions, 60 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
diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
index 992d005..ae20802 100644
--- a/gcc/config/nvptx/nvptx.cc
+++ b/gcc/config/nvptx/nvptx.cc
@@ -1791,7 +1791,7 @@ nvptx_get_drap_rtx (void)
argument to the next call. */
static void
-nvptx_call_args (rtx arg, tree fntype)
+nvptx_call_args (cumulative_args_t, rtx arg, tree fntype)
{
if (!cfun->machine->doing_call)
{
@@ -1819,7 +1819,7 @@ nvptx_call_args (rtx arg, tree fntype)
information we recorded. */
static void
-nvptx_end_call_args (void)
+nvptx_end_call_args (cumulative_args_t)
{
cfun->machine->doing_call = false;
free_EXPR_LIST_list (&cfun->machine->call_args);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index bc8ee04..1246ed1 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5503,26 +5503,59 @@ 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})
+@deftypefn {Target Hook} void TARGET_START_CALL_ARGS (cumulative_args_t @var{complete_args})
+This target hook is invoked while generating RTL for a function call,
+after the argument values have been computed, and after stack arguments
+have been initialized, but before register arguments have been moved into
+their ABI-defined hard register locations. It precedes calls to the related
+hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}.
+The significance of this position in the call expansion is that:
+
+@itemize @bullet
+@item
+No argument registers are live.
+@item
+Although a call sequence can in general involve subcalls (such as using
+@code{memcpy} to copy large arguments), no such subcall will occur between
+the call to this hook and the generation of the main call instruction.
+@end itemize
+
+The single argument @var{complete_args} is the state of the target
+function's cumulative argument information after the final call to
+@code{TARGET_FUNCTION_ARG}.
+
+The hook can be used for things like switching processor mode, in cases
+where different calls need different processor modes. Most ports do not
+need to implement anything for this hook.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_CALL_ARGS (cumulative_args_t @var{complete_args}, rtx @var{loc}, tree @var{type})
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.
+before the point where argument registers are stored.
+
+@var{complete_args} is the state of the target function's cumulative
+argument information after the final call to @code{TARGET_FUNCTION_ARG}.
+@var{loc} is the location of the argument. @var{type} is the type of
+the function being called, or @code{NULL_TREE} for libcalls.
+
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.
+
+This functionality can be used to perform special setup of call argument
+registers, if a target needs it. Most ports do not need to implement
+anything for this hook.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (void)
+@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (cumulative_args_t @var{complete_args})
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.
+emitted call are now no longer in use. @var{complete_args} is the
+state of the target function's cumulative argument information after
+the final call to @code{TARGET_FUNCTION_ARG}.
+
Most ports do not need to implement anything for this hook.
@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 5f636ab..2b4d283 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3837,6 +3837,8 @@ These machine description macros help implement varargs:
@hook TARGET_STRICT_ARGUMENT_NAMING
+@hook TARGET_START_CALL_ARGS
+
@hook TARGET_CALL_ARGS
@hook TARGET_END_CALL_ARGS
diff --git a/gcc/hooks.cc b/gcc/hooks.cc
index e83add4..fe59bbd 100644
--- a/gcc/hooks.cc
+++ b/gcc/hooks.cc
@@ -281,11 +281,6 @@ hook_void_FILEptr_tree (FILE *, tree)
}
void
-hook_void_rtx_tree (rtx, tree)
-{
-}
-
-void
hook_void_constcharptr (const char *)
{
}
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 6aa01fc..3a02b6c 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -83,7 +83,6 @@ extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *,
const_tree);
extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx);
-extern void hook_void_rtx_tree (rtx, tree);
extern void hook_void_FILEptr_tree (FILE *, tree);
extern void hook_void_tree (tree);
extern void hook_void_tree_treeptr (tree, tree *);
diff --git a/gcc/target.def b/gcc/target.def
index 427fe52..4addee1 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4820,31 +4820,66 @@ not generate any instructions in this case.",
default_setup_incoming_varargs)
DEFHOOK
+(start_call_args,
+ "This target hook is invoked while generating RTL for a function call,\n\
+after the argument values have been computed, and after stack arguments\n\
+have been initialized, but before register arguments have been moved into\n\
+their ABI-defined hard register locations. It precedes calls to the related\n\
+hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}.\n\
+The significance of this position in the call expansion is that:\n\
+\n\
+@itemize @bullet\n\
+@item\n\
+No argument registers are live.\n\
+@item\n\
+Although a call sequence can in general involve subcalls (such as using\n\
+@code{memcpy} to copy large arguments), no such subcall will occur between\n\
+the call to this hook and the generation of the main call instruction.\n\
+@end itemize\n\
+\n\
+The single argument @var{complete_args} is the state of the target\n\
+function's cumulative argument information after the final call to\n\
+@code{TARGET_FUNCTION_ARG}.\n\
+\n\
+The hook can be used for things like switching processor mode, in cases\n\
+where different calls need different processor modes. Most ports do not\n\
+need to implement anything for this hook.",
+ void, (cumulative_args_t complete_args),
+ hook_void_CUMULATIVE_ARGS)
+
+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\
+before the point where argument registers are stored.\n\
+\n\
+@var{complete_args} is the state of the target function's cumulative\n\
+argument information after the final call to @code{TARGET_FUNCTION_ARG}.\n\
+@var{loc} is the location of the argument. @var{type} is the type of\n\
+the function being called, or @code{NULL_TREE} for libcalls.\n\
+\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)
+\n\
+This functionality can be used to perform special setup of call argument\n\
+registers, if a target needs it. Most ports do not need to implement\n\
+anything for this hook.",
+ void, (cumulative_args_t complete_args, rtx loc, tree type),
+ hook_void_CUMULATIVE_ARGS_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\
+emitted call are now no longer in use. @var{complete_args} is the\n\
+state of the target function's cumulative argument information after\n\
+the final call to @code{TARGET_FUNCTION_ARG}.\n\
+\n\
Most ports do not need to implement anything for this hook.",
- void, (void),
- hook_void_void)
+ void, (cumulative_args_t complete_args),
+ hook_void_CUMULATIVE_ARGS)
DEFHOOK
(push_argument,
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index a2dc733..afe91fe1 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -781,11 +781,21 @@ hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
}
void
+hook_void_CUMULATIVE_ARGS (cumulative_args_t)
+{
+}
+
+void
hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t ca ATTRIBUTE_UNUSED,
tree ATTRIBUTE_UNUSED)
{
}
+void
+hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree)
+{
+}
+
/* Default implementation of TARGET_PUSH_ARGUMENT. */
bool
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 26695ab..5a39e8e 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -142,8 +142,9 @@ extern bool hook_bool_CUMULATIVE_ARGS_arg_info_true
(cumulative_args_t, const function_arg_info &);
extern int hook_int_CUMULATIVE_ARGS_arg_info_0
(cumulative_args_t, const function_arg_info &);
-extern void hook_void_CUMULATIVE_ARGS_tree
- (cumulative_args_t, tree);
+extern void hook_void_CUMULATIVE_ARGS (cumulative_args_t);
+extern void hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t, tree);
+extern void hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree);
extern const char *hook_invalid_arg_for_unprototyped_fn
(const_tree, const_tree, const_tree);
extern void default_function_arg_advance