On ptx we need to decorate call insns with the arguments that are being passed. This is kind of hard to do with the existing infrastructure, 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.
gcc/ * target.def (start_call_args, end_call_args): New hooks. * hooks.c (hook_void_rtx): New empty function. * hooks.h (hook_void_rtx): Declare. * doc/tm.texi.in (TARGET_START_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 (revision 422422) +++ gcc/doc/tm.texi (revision 422423) @@ -5150,6 +5150,26 @@ 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_START_CALL_ARGS (rtx) +While generating RTL for a function call, this target hook is invoked once +for each argument register returned by @code{TARGET_FUNCTION_ARG}, +just before the point where argument registers are stored. The +corresponding @code{TARGET_END_CALL_ARGS} hook will be 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} +as its argument. +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 (revision 422422) +++ gcc/doc/tm.texi.in (revision 422423) @@ -4064,6 +4064,10 @@ These machine description macros help im @hook TARGET_STRICT_ARGUMENT_NAMING +@hook TARGET_START_CALL_ARGS + +@hook TARGET_END_CALL_ARGS + @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED @node Trampolines Index: gcc/hooks.c =================================================================== --- gcc/hooks.c (revision 422422) +++ gcc/hooks.c (revision 422423) @@ -245,6 +245,11 @@ hook_void_tree (tree a ATTRIBUTE_UNUSED) } void +hook_void_rtx (rtx) +{ +} + +void hook_void_constcharptr (const char *a ATTRIBUTE_UNUSED) { } Index: gcc/hooks.h =================================================================== --- gcc/hooks.h (revision 422422) +++ gcc/hooks.h (revision 422423) @@ -66,6 +66,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 (rtx); 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 (revision 422422) +++ gcc/target.def (revision 422423) @@ -3738,6 +3738,30 @@ not generate any instructions in this ca default_setup_incoming_varargs) DEFHOOK +(start_call_args, + "While generating RTL for a function call, this target hook is invoked once\n\ +for each argument register returned by @code{TARGET_FUNCTION_ARG},\n\ +just before the point where argument registers are stored. The\n\ +corresponding @code{TARGET_END_CALL_ARGS} hook will be invoked just after the\n\ +code to copy the return reg has been emitted. This functionality can be used\n\ +to perform special setup of call argument registers if a target needs it.\n\ +For functions without arguments, the hook is called once with @code{pc_rtx}\n\ +as its argument.\n\ +Most ports do not need to implement anything for this hook.", + void, (rtx), + hook_void_rtx) + +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 (revision 422422) +++ gcc/calls.c (revision 422423) @@ -2989,6 +2989,32 @@ 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 + + if (num_actuals == 0) + targetm.calls.start_call_args (pc_rtx); + else + for (i = 0; i < num_actuals; i++) + if (args[i].reg != NULL_RTX) + targetm.calls.start_call_args (args[i].reg); + else + targetm.calls.start_call_args (args[i].stack); + /* Figure out the register where the value, if any, will come back. */ valreg = 0; if (TYPE_MODE (rettype) != VOIDmode @@ -3015,23 +3041,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. @@ -3425,6 +3434,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 (); @@ -3961,6 +3972,13 @@ emit_library_call_value_1 (int retval, r } #endif + if (nargs == 0) + targetm.calls.start_call_args (pc_rtx); + else + for (int i = 0; i < nargs; i++) + if (argvec[i].reg != NULL_RTX) + targetm.calls.start_call_args (argvec[i].reg); + /* Push the args that need to be pushed. */ /* ARGNUM indexes the ARGVEC array in the order in which the arguments @@ -4201,6 +4219,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