* config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Nov 2003 21:52:36 +0000 (21:52 +0000)
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Nov 2003 21:52:36 +0000 (21:52 +0000)
(USE_ALTIVEC_FOR_ARG_P): Likewise.
* config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h.
Take a pointer as the CUM parameter.  Update callers.
(USE_ALTIVEC_FOR_ARG_P): Likewise.  Also correct for Darwin/AIX
32-bit ABIs.
(function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P.  Correct case
of vector parameters as named arguments of stdarg function.
(function_arg): Likewise.

* config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when
-maltivec is specified, not the non-existent -faltivec.

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

gcc/ChangeLog
gcc/config/rs6000/darwin.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/altivec-varargs-1.c [new file with mode: 0644]

index 9279d35..f889c2c 100644 (file)
@@ -1,3 +1,18 @@
+2003-11-06  Geoffrey Keating  <geoffk@apple.com>
+
+       * config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
+       (USE_ALTIVEC_FOR_ARG_P): Likewise.
+       * config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h.
+       Take a pointer as the CUM parameter.  Update callers.
+       (USE_ALTIVEC_FOR_ARG_P): Likewise.  Also correct for Darwin/AIX
+       32-bit ABIs.
+       (function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P.  Correct case
+       of vector parameters as named arguments of stdarg function.
+       (function_arg): Likewise.
+
+       * config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when
+       -maltivec is specified, not the non-existent -faltivec.
+
 2003-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * config/s390/s390-protos.h (s390_function_value): Declare.
index e417e0d..929290f 100644 (file)
@@ -100,7 +100,7 @@ do {                                                                        \
 
 #define ASM_SPEC "-arch ppc \
   %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
-  %{!Zforce_cpusubtype_ALL:%{faltivec:-force_cpusubtype_ALL}}"
+  %{!Zforce_cpusubtype_ALL:%{maltivec:-force_cpusubtype_ALL}}"
 
 #undef SUBTARGET_EXTRA_SPECS
 #define SUBTARGET_EXTRA_SPECS                  \
index ad0169a..9a0efb0 100644 (file)
@@ -3618,6 +3618,19 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
 }
 \f
+/* Nonzero if we can use a floating-point register to pass this arg.  */
+#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE)                \
+  (GET_MODE_CLASS (MODE) == MODE_FLOAT         \
+   && (CUM)->fregno <= FP_ARG_MAX_REG          \
+   && TARGET_HARD_FLOAT && TARGET_FPRS)
+
+/* Nonzero if we can use an AltiVec register to pass this arg.  */
+#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED)     \
+  (ALTIVEC_VECTOR_MODE (MODE)                          \
+   && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG             \
+   && TARGET_ALTIVEC_ABI                               \
+   && (DEFAULT_ABI == ABI_V4 || (NAMED)))
+
 /* Return a nonzero value to say to return the function value in
    memory, just as large structures are always returned.  TYPE will be
    the data type of the value, and FNTYPE will be the type of the
@@ -3802,23 +3815,35 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
   if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
     {
-      if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
+      if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
        cum->vregno++;
-      else
+      
+      /* In variable-argument functions, vector arguments get GPRs allocated
+        even if they are going to be passed in a vector register.  */
+      if (cum->stdarg && DEFAULT_ABI != ABI_V4)
        {
          int align;
          
-         /* Vector parameters must be 16-byte aligned.  This places them at
-            2 mod 4 in terms of words (on both ABIs).  */
-         align = ((6 - (cum->words & 3)) & 3);
+         /* Vector parameters must be 16-byte aligned.  This places
+            them at 2 mod 4 in terms of words in 32-bit mode, since
+            the parameter save area starts at offset 24 from the
+            stack.  In 64-bit mode, they just have to start on an
+            even word, since the parameter save area is 16-byte
+            aligned.  Space for GPRs is reserved even if the argument
+            will be passed in memory.  */
+         if (TARGET_32BIT)
+           align = ((6 - (cum->words & 3)) & 3);
+         else
+           align = cum->words & 1;
          cum->words += align + RS6000_ARG_SIZE (mode, type);
-
+         
          if (TARGET_DEBUG_ARG)
            {
              fprintf (stderr, "function_adv: words = %2d, align=%d, ", 
                       cum->words, align);
              fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
-                      cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
+                      cum->nargs_prototype, cum->prototype, 
+                      GET_MODE_NAME (mode));
            }
        }
     }
@@ -4099,40 +4124,43 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
       return GEN_INT (cum->call_cookie);
     }
 
-  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+  if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
+    return gen_rtx_REG (mode, cum->vregno);
+  else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
     {
-      if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
-       return gen_rtx_REG (mode, cum->vregno);
-      else if (named || abi == ABI_V4)
+      if (named || abi == ABI_V4)
        return NULL_RTX;
       else
        {
          /* Vector parameters to varargs functions under AIX or Darwin
             get passed in memory and possibly also in GPRs.  */
          int align, align_words;
-         rtx reg;
+         enum machine_mode part_mode = mode;
 
          /* Vector parameters must be 16-byte aligned.  This places them at
-            2 mod 4 in terms of words.  */
-         align = ((6 - (cum->words & 3)) & 3);
+            2 mod 4 in terms of words in 32-bit mode, since the parameter
+            save area starts at offset 24 from the stack.  In 64-bit mode,
+            they just have to start on an even word, since the parameter
+            save area is 16-byte aligned.  */
+         if (TARGET_32BIT)
+           align = ((6 - (cum->words & 3)) & 3);
+         else
+           align = cum->words & 1;
          align_words = cum->words + align;
 
          /* Out of registers?  Memory, then.  */
          if (align_words >= GP_ARG_NUM_REG)
            return NULL_RTX;
          
-         /* The vector value goes in both memory and GPRs.  Varargs
-            vector regs will always be saved in R5-R8 or R9-R12.  */
-         reg = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
-
-         return gen_rtx_PARALLEL (mode,
-                                  gen_rtvec (2,
-                                             gen_rtx_EXPR_LIST (VOIDmode,
-                                                                NULL_RTX, 
-                                                                const0_rtx),
-                                             gen_rtx_EXPR_LIST (VOIDmode,
-                                                                reg, 
-                                                                const0_rtx)));
+         /* The vector value goes in GPRs.  Only the part of the
+            value in GPRs is reported here.  */
+         if (align_words + CLASS_MAX_NREGS (mode, GENERAL_REGS)
+             > GP_ARG_NUM_REG)
+           /* Fortunately, there are only two possibilites, the value
+              is either wholly in GPRs or half in GPRs and half not.  */
+           part_mode = DImode;
+         
+         return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
        }
     }
   else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
@@ -4183,7 +4211,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
          && (mode == DFmode || mode == DImode || mode == BLKmode))
        return rs6000_mixed_function_arg (cum, mode, type, align_words);
 
-      if (USE_FP_FOR_ARG_P (*cum, mode, type))
+      if (USE_FP_FOR_ARG_P (cum, mode, type))
        {
          if (! type
              || ((cum->nargs_prototype > 0)
@@ -4228,13 +4256,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
 int
 function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
-                           tree type, int named ATTRIBUTE_UNUSED)
+                           tree type, int named)
 {
   if (DEFAULT_ABI == ABI_V4)
     return 0;
 
-  if (USE_FP_FOR_ARG_P (*cum, mode, type)
-      || USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
+  if (USE_FP_FOR_ARG_P (cum, mode, type)
+      || USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
     {
       if (cum->nargs_prototype >= 0)
        return 0;
index 95078ec..ce38901 100644 (file)
@@ -1800,18 +1800,6 @@ typedef struct rs6000_args
 #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
   function_arg_advance (&CUM, MODE, TYPE, NAMED)
 
-/* Nonzero if we can use a floating-point register to pass this arg.  */
-#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
-  (GET_MODE_CLASS (MODE) == MODE_FLOAT  \
-   && (CUM).fregno <= FP_ARG_MAX_REG    \
-   && TARGET_HARD_FLOAT && TARGET_FPRS)
-
-/* Nonzero if we can use an AltiVec register to pass this arg.  */
-#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE)   \
-  (ALTIVEC_VECTOR_MODE (MODE)                  \
-   && (CUM).vregno <= ALTIVEC_ARG_MAX_REG      \
-   && TARGET_ALTIVEC_ABI)
-
 /* Determine where to put an argument to a function.
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
index 5c7cea5..8390d01 100644 (file)
@@ -1,3 +1,7 @@
+2003-11-06  Geoffrey Keating  <geoffk@apple.com>
+
+       * gcc.dg/altivec-varargs-1.c: New test.
+
 2003-11-05  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.c-torture/compile/20031023-4.c: XFAIL on SPARC64
diff --git a/gcc/testsuite/gcc.dg/altivec-varargs-1.c b/gcc/testsuite/gcc.dg/altivec-varargs-1.c
new file mode 100644 (file)
index 0000000..b866500
--- /dev/null
@@ -0,0 +1,74 @@
+/* { dg-do run { target powerpc*-*-darwin* powerpc*-*-*altivec* } } */
+/* { dg-options "-maltivec" } */
+/* This test requires altivec, which means it'll fail on Darwin running
+   on G3. FIXME.  */
+
+#include <stdarg.h>
+
+#define vector __attribute__((mode(V4SI)))
+
+const vector unsigned int v1 = {10,11,12,13};
+const vector unsigned int v2 = {20,21,22,23};
+const vector unsigned int v3 = {30,31,32,33};
+const vector unsigned int v4 = {40,41,42,43};
+
+void foo(vector unsigned int a, ...)
+{
+  va_list args;
+  vector unsigned int v;
+
+  va_start (args, a);
+  if (memcmp (&a, &v1, sizeof (v)) != 0)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v2, sizeof (v)) != 0)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v3, sizeof (v)) != 0)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v4, sizeof (v)) != 0)
+    abort ();
+  va_end (args);
+}
+
+void bar(vector unsigned int a, ...)
+{
+  va_list args;
+  vector unsigned int v;
+  int b;
+
+  va_start (args, a);
+  if (memcmp (&a, &v1, sizeof (v)) != 0)
+    abort ();
+  b = va_arg (args, int);
+  if (b != 2)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v2, sizeof (v)) != 0)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v3, sizeof (v)) != 0)
+    abort ();
+  va_end (args);
+}
+
+
+int main(void)
+{
+  /* In this call, in the Darwin ABI, the first argument goes into v2
+     the second one into r9-r10 and memory,
+     and the next two in memory.  */
+  foo ((vector unsigned int){10,11,12,13},
+       (vector unsigned int){20,21,22,23},
+       (vector unsigned int){30,31,32,33},
+       (vector unsigned int){40,41,42,43});
+  /* In this call, in the Darwin ABI, the first argument goes into v2
+     the second one into r9, then r10 is reserved and
+     there are two words of padding in memory, and the next two arguments
+     go after the padding.  */
+  bar ((vector unsigned int){10,11,12,13}, 2,
+       (vector unsigned int){20,21,22,23},
+       (vector unsigned int){30,31,32,33});
+  return 0;
+}