OSDN Git Service

* config/sparc/sparc.c (function_arg_union_value): New 'slotno'
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Nov 2004 17:24:19 +0000 (17:24 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Nov 2004 17:24:19 +0000 (17:24 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@90396 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/union-2.c [new file with mode: 0644]

index 7d84272..23d6473 100644 (file)
@@ -1,3 +1,11 @@
+2004-11-10  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * 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 <fjahanian@apple.com>
 
        PR tree-optimization/17892
index 0f34884..87e30d4 100644 (file)
@@ -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;
        }
index b87577d..0893277 100644 (file)
@@ -1,3 +1,7 @@
+2004-11-10  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.dg/union-2.c: New test.
+
 2004-11-10  Fariborz Jahanian <fjahanian@apple.com>
 
         * 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 (file)
index 0000000..edc8a7a
--- /dev/null
@@ -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 <stdarg.h>
+
+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;
+}