From 22d8d62798a3ce51a7e328805593bf675eddf60f Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 10 Nov 2004 18:24:19 +0100 Subject: [PATCH] sparc.c (function_arg_union_value): New 'slotno' argument. * config/sparc/sparc.c (function_arg_union_value): New 'slotno' argument. When the union is passed in the 6th slot, build a PARALLEL with only one element. (function_arg): Adjust call to function_arg_union_value. (function_value): Likewise. From-SVN: r90396 --- gcc/ChangeLog | 8 ++++++++ gcc/config/sparc/sparc.c | 14 +++++++++----- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/union-2.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/union-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d842728bed..23d6473b9f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-11-10 Eric Botcazou + + * config/sparc/sparc.c (function_arg_union_value): New 'slotno' + argument. When the union is passed in the 6th slot, build a + PARALLEL with only one element. + (function_arg): Adjust call to function_arg_union_value. + (function_value): Likewise. + 2004-11-10 Fariborz Jahanian PR tree-optimization/17892 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 0f3488492ed..87e30d49d79 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -5241,7 +5241,7 @@ static void function_arg_record_value_2 static void function_arg_record_value_1 (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool); static rtx function_arg_record_value (tree, enum machine_mode, int, int, int); -static rtx function_arg_union_value (int, enum machine_mode, int); +static rtx function_arg_union_value (int, enum machine_mode, int, int); /* A subroutine of function_arg_record_value. Traverse the structure recursively and determine how many registers will be required. */ @@ -5608,7 +5608,8 @@ function_arg_record_value (tree type, enum machine_mode mode, REGNO is the hard register the union will be passed in. */ static rtx -function_arg_union_value (int size, enum machine_mode mode, int regno) +function_arg_union_value (int size, enum machine_mode mode, int slotno, + int regno) { int nwords = ROUND_ADVANCE (size), i; rtx regs; @@ -5617,6 +5618,9 @@ function_arg_union_value (int size, enum machine_mode mode, int regno) if (nwords == 0) return gen_rtx_REG (mode, regno); + if (slotno == SPARC_INT_ARG_MAX - 1) + nwords = 1; + regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords)); for (i = 0; i < nwords; i++) @@ -5717,7 +5721,7 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, if (size > 16) abort (); /* shouldn't get here */ - return function_arg_union_value (size, mode, regno); + return function_arg_union_value (size, mode, slotno, regno); } else if (type && TREE_CODE (type) == VECTOR_TYPE) { @@ -6107,7 +6111,7 @@ function_value (tree type, enum machine_mode mode, int incoming_p) if (size > 32) abort (); /* shouldn't get here */ - return function_arg_union_value (size, mode, regbase); + return function_arg_union_value (size, mode, 0, regbase); } else if (AGGREGATE_TYPE_P (type)) { @@ -6130,7 +6134,7 @@ function_value (tree type, enum machine_mode mode, int incoming_p) try to be unduly clever, and simply follow the ABI for unions in that case. */ if (mode == BLKmode) - return function_arg_union_value (bytes, mode, regbase); + return function_arg_union_value (bytes, mode, 0, regbase); else mclass = MODE_INT; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b87577d7763..08932778d9f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-11-10 Eric Botcazou + + * gcc.dg/union-2.c: New test. + 2004-11-10 Fariborz Jahanian * gcc.c-torture/execute/ieee/unsafe-fp-assoc-1.c: diff --git a/gcc/testsuite/gcc.dg/union-2.c b/gcc/testsuite/gcc.dg/union-2.c new file mode 100644 index 00000000000..edc8a7abf11 --- /dev/null +++ b/gcc/testsuite/gcc.dg/union-2.c @@ -0,0 +1,28 @@ +/* This used to segfault on SPARC 64-bit at runtime because + the stack pointer was clobbered by the function call. */ + +/* { dg-do run } */ + +#include + +union U +{ + long l1[2]; +}; + +union U u; + +void foo (int z, ...) +{ + int i; + va_list ap; + va_start(ap,z); + i = va_arg(ap, int); + va_end(ap); +} + +int main(void) +{ + foo (1, 1, 1, 1, 1, u); + return 0; +} -- 2.30.2