summaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-25 07:54:07 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-25 07:54:07 +0000
commit63864e1c15b724736e16990b93d8e31023ef5de5 (patch)
treea7f628578c0ccef5e4f29a6a9c7f07ba9b4a9bc9 /gcc/calls.c
parent91dad636769f85907fbd06680a661247f66cbf19 (diff)
downloadgcc-63864e1c15b724736e16990b93d8e31023ef5de5.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102350 138bc75d-0d04-0410-961f-82ee72b054a4
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 8e87886de1d..ea6eaeb82f7 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)