aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-07-25 09:54:07 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2005-07-25 09:54:07 +0200
commit0dc42b03d364d14f6e31d4021201f8a1d6323da6 (patch)
treea7f628578c0ccef5e4f29a6a9c7f07ba9b4a9bc9 /gcc/calls.c
parent31f74accb27dfe58e1926dbbcb0b9d57e55bde42 (diff)
downloadgcc-0dc42b03d364d14f6e31d4021201f8a1d6323da6.zip
gcc-0dc42b03d364d14f6e31d4021201f8a1d6323da6.tar.gz
gcc-0dc42b03d364d14f6e31d4021201f8a1d6323da6.tar.bz2
calls.c (store_one_arg): Check for sibling call MEM arguments from already clobbered incoming argument area.
* calls.c (store_one_arg): Check for sibling call MEM arguments from already clobbered incoming argument area. * gcc.c-torture/execute/20050713-1.c: New test. From-SVN: r102350
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 8e87886..ea6eaeb 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -4076,6 +4076,38 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
stack_arg_under_construction--;
}
+ /* Check for overlap with already clobbered argument area. */
+ if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
+ {
+ int i = -1;
+ unsigned int k;
+ rtx x = arg->value;
+
+ if (XEXP (x, 0) == current_function_internal_arg_pointer)
+ i = 0;
+ else if (GET_CODE (XEXP (x, 0)) == PLUS
+ && XEXP (XEXP (x, 0), 0) ==
+ current_function_internal_arg_pointer
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ i = INTVAL (XEXP (XEXP (x, 0), 1));
+ else
+ i = -1;
+
+ if (i >= 0)
+ {
+#ifdef ARGS_GROW_DOWNWARD
+ i = -i - arg->locate.size.constant;
+#endif
+ for (k = 0; k < arg->locate.size.constant; k++)
+ if (i + k < stored_args_map->n_bits
+ && TEST_BIT (stored_args_map, i + k))
+ {
+ sibcall_failure = 1;
+ break;
+ }
+ }
+ }
+
/* Don't allow anything left on stack from computation
of argument to alloca. */
if (flags & ECF_MAY_BE_ALLOCA)