diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-25 07:54:07 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-25 07:54:07 +0000 |
commit | 63864e1c15b724736e16990b93d8e31023ef5de5 (patch) | |
tree | a7f628578c0ccef5e4f29a6a9c7f07ba9b4a9bc9 /gcc/calls.c | |
parent | 91dad636769f85907fbd06680a661247f66cbf19 (diff) | |
download | gcc-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.c | 32 |
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) |