From 0dc42b03d364d14f6e31d4021201f8a1d6323da6 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 25 Jul 2005 09:54:07 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++ gcc/calls.c | 32 +++++++++++ gcc/testsuite/ChangeLog | 2 + .../gcc.c-torture/execute/20050713-1.c | 56 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20050713-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 42c8c2e32cd..396314105e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-07-25 Jakub Jelinek + + * calls.c (store_one_arg): Check for sibling call MEM arguments + from already clobbered incoming argument area. + 2005-07-24 Kaveh R. Ghazi * c-common.c (check_missing_format_attribute): New. 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 11ec1110cf5..a5d540ca5cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2005-07-25 Jakub Jelinek + * gcc.c-torture/execute/20050713-1.c: New test. + PR fortran/20063 * gfortran.fortran-torture/execute/data_4.f90: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/20050713-1.c b/gcc/testsuite/gcc.c-torture/execute/20050713-1.c new file mode 100644 index 00000000000..4d669cb8e45 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20050713-1.c @@ -0,0 +1,56 @@ +/* Test that sibling call is not used if there is an argument overlap. */ + +extern void abort (void); + +struct S +{ + int a, b, c; +}; + +int +foo2 (struct S x, struct S y) +{ + if (x.a != 3 || x.b != 4 || x.c != 5) + abort (); + if (y.a != 6 || y.b != 7 || y.c != 8) + abort (); + return 0; +} + +int +foo3 (struct S x, struct S y, struct S z) +{ + foo2 (x, y); + if (z.a != 9 || z.b != 10 || z.c != 11) + abort (); + return 0; +} + +int +bar2 (struct S x, struct S y) +{ + return foo2 (y, x); +} + +int +bar3 (struct S x, struct S y, struct S z) +{ + return foo3 (y, x, z); +} + +int +baz3 (struct S x, struct S y, struct S z) +{ + return foo3 (y, z, x); +} + +int +main (void) +{ + struct S a = { 3, 4, 5 }, b = { 6, 7, 8 }, c = { 9, 10, 11 }; + + bar2 (b, a); + bar3 (b, a, c); + baz3 (c, a, b); + return 0; +} -- 2.30.2