aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2014-11-06 17:20:13 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2014-11-06 17:20:13 +0000
commit2f21e1ba46762bceac682c433028627f6953ed50 (patch)
tree4999300131a9d6c5e23e1edd7447e5a3a181005a
parent11717c64bf8b17397a6267638833ae6fca606a07 (diff)
downloadgcc-2f21e1ba46762bceac682c433028627f6953ed50.zip
gcc-2f21e1ba46762bceac682c433028627f6953ed50.tar.gz
gcc-2f21e1ba46762bceac682c433028627f6953ed50.tar.bz2
Add a hook to inform a port about call arguments.
* 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. From-SVN: r217199
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/calls.c104
-rw-r--r--gcc/doc/tm.texi23
-rw-r--r--gcc/doc/tm.texi.in4
-rw-r--r--gcc/hooks.c5
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/target.def27
7 files changed, 134 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 085f0b1..75ab1fa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
2014-11-06 Bernd Schmidt <bernds@codesourcery.com>
+ * 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.
+
* expr.c (use_reg_mode): Just return for pseudo registers.
* combine.c (try_combine): Don't allow a call as one of the source
diff --git a/gcc/calls.c b/gcc/calls.c
index 43ac5d2..06b8485 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3103,45 +3103,6 @@ expand_call (tree exp, rtx target, int ignore)
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, &reg_parm_seen);
@@ -3223,6 +3184,55 @@ expand_call (tree exp, rtx target, int ignore)
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++)
{
@@ -3582,6 +3592,8 @@ 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 ();
+
insns = get_insns ();
end_sequence ();
@@ -4111,6 +4123,18 @@ 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);
+
/* Push the args that need to be pushed. */
/* ARGNUM indexes the ARGVEC array in the order in which the arguments
@@ -4351,6 +4375,8 @@ 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 ();
+
/* 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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 7af23e5..a55206d 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4976,6 +4976,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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f739fdf..e0c52c8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3860,6 +3860,10 @@ These machine description macros help implement varargs:
@hook TARGET_STRICT_ARGUMENT_NAMING
+@hook TARGET_CALL_ARGS
+
+@hook TARGET_END_CALL_ARGS
+
@hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED
@hook TARGET_LOAD_BOUNDS_FOR_ARG
diff --git a/gcc/hooks.c b/gcc/hooks.c
index b5b1587..91e17cd 100644
--- a/gcc/hooks.c
+++ b/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)
{
}
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 90b31fb..4006cad 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -71,6 +71,7 @@ extern void hook_void_constcharptr (const char *);
extern void hook_void_rtx_insn_int (rtx_insn *, 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);
diff --git a/gcc/target.def b/gcc/target.def
index 4c02c11..d6198ad 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4002,6 +4002,33 @@ into the stack. Arguments meaning is similar to\n\
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\
argument is passed depends on whether or not it is a named argument.\n\