In ptx assembly we need to decorate call insns with the arguments that
are being passed. We also need to know the exact function type. This is
kind of hard to do with the existing infrastructure since things like
function_arg are called at other times rather than just when emitting a
call, so this patch adds two more hooks, one called just before argument
registers are loaded (once for each arg), and the other just after the
call is complete.
Bernd
gcc/
* 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.
------------------------------------------------------------------------
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi.orig
+++ gcc/doc/tm.texi
@@ -5027,6 +5027,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
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in.orig
+++ gcc/doc/tm.texi.in
@@ -3929,6 +3929,10 @@ These machine description macros help im
@hook TARGET_STRICT_ARGUMENT_NAMING
+@hook TARGET_CALL_ARGS
+
+@hook TARGET_END_CALL_ARGS
+
@hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED
@node Trampolines
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c.orig
+++ gcc/hooks.c
@@ -245,6 +245,11 @@ hook_void_tree (tree a ATTRIBUTE_UNUSED)
}
void
+hook_void_rtx_tree (rtx, tree)
+{
+}
+
+void
hook_void_constcharptr (const char *a ATTRIBUTE_UNUSED)
{
}
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h.orig
+++ gcc/hooks.h
@@ -70,6 +70,7 @@ extern void hook_void_constcharptr (cons
extern void hook_void_rtx_int (rtx, 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);
Index: gcc/target.def
===================================================================
--- gcc/target.def.orig
+++ gcc/target.def
@@ -3825,6 +3825,33 @@ not generate any instructions in this ca
default_setup_incoming_varargs)
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\
argument is passed depends on whether or not it is a named argument.\n\
Index: gcc/calls.c
===================================================================
--- gcc/calls.c.orig
+++ gcc/calls.c
@@ -3011,6 +3011,33 @@ expand_call (tree exp, rtx target, int i
funexp = rtx_for_function_call (fndecl, addr);
+ /* 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);
+
+ if (CALL_EXPR_STATIC_CHAIN (exp))
+ static_chain_value = expand_normal (CALL_EXPR_STATIC_CHAIN (exp));
+ else
+ static_chain_value = 0;
+
+#ifdef REG_PARM_STACK_SPACE
+ /* Save the fixed argument area if it's part of the caller's frame and
+ is clobbered by argument setup for this call. */
+ if (ACCUMULATE_OUTGOING_ARGS && pass)
+ save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
+ &low_to_save, &high_to_save);
+#endif
+
+ 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;
if (TYPE_MODE (rettype) != VOIDmode
@@ -3037,23 +3064,6 @@ expand_call (tree exp, rtx target, int i
}
}
- /* 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);
-
- if (CALL_EXPR_STATIC_CHAIN (exp))
- static_chain_value = expand_normal (CALL_EXPR_STATIC_CHAIN (exp));
- else
- static_chain_value = 0;
-
-#ifdef REG_PARM_STACK_SPACE
- /* Save the fixed argument area if it's part of the caller's frame and
- is clobbered by argument setup for this call. */
- if (ACCUMULATE_OUTGOING_ARGS && pass)
- save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
- &low_to_save, &high_to_save);
-#endif
-
/* Now store (and compute if necessary) all non-register parms.
These come before register parms, since they can require block-moves,
which could clobber the registers used for register parms.
@@ -3458,6 +3468,8 @@ expand_call (tree exp, rtx target, int i
for (i = 0; i < num_actuals; ++i)
free (args[i].aligned_regs);
+ targetm.calls.end_call_args ();
+
insns = get_insns ();
end_sequence ();
@@ -3985,6 +3997,18 @@ emit_library_call_value_1 (int retval, r
}
#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
@@ -4224,6 +4248,8 @@ emit_library_call_value_1 (int retval, r
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