function.c (pad_to_arg_alignment): Take STACK_POINTER_OFFSET into account when aligni...
authorGeoffrey Keating <geoffk@apple.com>
Tue, 7 Oct 2003 19:48:23 +0000 (19:48 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Tue, 7 Oct 2003 19:48:23 +0000 (19:48 +0000)
2003-10-07  Geoffrey Keating  <geoffk@apple.com>

* function.c (pad_to_arg_alignment): Take STACK_POINTER_OFFSET into
account when aligning arguments.
* calls.c (STACK_POINTER_OFFSET): Move default from here ...
* defaults.h (STACK_POINTER_OFFSET): ... to here.
* config/sparc/sparc.h (STACK_BOUNDARY): Add comment about how
it's wrong when TARGET_ARCH64 && TARGET_STACK_BIAS.
(SPARC_STACK_BOUNDARY_HACK): Define.
* config/rs6000/rs6000.c (function_arg): On non-SVR4 systems,
arrange for vector parameters to varargs functions to be passed
in both memory and GPRs when appropriate.
(rs6000_va_arg): Vector arguments passed in memory are 16-byte
aligned.

Index: testsuite/ChangeLog
2003-10-07  Geoffrey Keating  <geoffk@apple.com>

* gcc.dg/darwin-abi-2.c: New file.
* gcc.c-torture/execute/va-arg-24.c: New file.

From-SVN: r72199

gcc/ChangeLog
gcc/calls.c
gcc/config/rs6000/rs6000.c
gcc/config/sparc/sparc.h
gcc/defaults.h
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/va-arg-24.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/darwin-abi-2.c [new file with mode: 0644]

index 83438d615f824f0ae422a75ac40b84bc0f0e62ad..54c7374e87d7f8faffd41f303b90dce21f096058 100644 (file)
@@ -1,5 +1,18 @@
 2003-10-07  Geoffrey Keating  <geoffk@apple.com>
 
+       * function.c (pad_to_arg_alignment): Take STACK_POINTER_OFFSET into
+       account when aligning arguments.
+       * calls.c (STACK_POINTER_OFFSET): Move default from here ...
+       * defaults.h (STACK_POINTER_OFFSET): ... to here.
+       * config/sparc/sparc.h (STACK_BOUNDARY): Add comment about how
+       it's wrong when TARGET_ARCH64 && TARGET_STACK_BIAS.
+       (SPARC_STACK_BOUNDARY_HACK): Define.
+       * config/rs6000/rs6000.c (function_arg): On non-SVR4 systems,
+       arrange for vector parameters to varargs functions to be passed
+       in both memory and GPRs when appropriate.
+       (rs6000_va_arg): Vector arguments passed in memory are 16-byte
+       aligned.
+
        * hooks.c (hook_bool_tree_true): New.
        (hook_rtx_tree_int_null): New.
        (hook_rtx_rtx_null): Use NULL, not 0.
index aa649801ec2e26e39689c3194774837027c865f1..18df59a92c27f3e04b02c6d1d9fead4eca3286d6 100644 (file)
@@ -41,10 +41,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cgraph.h"
 #include "except.h"
 
-#ifndef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET    0
-#endif
-
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
 
index 29a584c1016dcb6c39aefdd972ed032daf120eb9..d6183b8c31afdc9fa06cbffa9801c48f2e471273 100644 (file)
@@ -544,134 +544,149 @@ rs6000_override_options (const char *default_cpu)
   /* Simplify the entries below by making a mask for any POWER
      variant and any PowerPC variant.  */
 
-#define POWER_MASKS (MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING)
-#define POWERPC_MASKS (MASK_POWERPC | MASK_PPC_GPOPT \
-                      | MASK_PPC_GFXOPT | MASK_POWERPC64)
-#define POWERPC_OPT_MASKS (MASK_PPC_GPOPT | MASK_PPC_GFXOPT)
+  enum {
+    POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
+    POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
+    POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT 
+                    | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC),
+    POWERPC_OPT_MASKS = MASK_PPC_GPOPT | MASK_PPC_GFXOPT | MASK_ALTIVEC,
+    
+    SET_MASKS = (POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT)
+  };
+
+  /* FIXME: In this table, there are a few places where SET_MASKS is
+     used with MASK_POWERPC64 masked off; these indicate processors
+     that are 64-bit but that don't yet have 64-bit switched on by
+     default because it doesn't work in the rest of the backend.
+     There are also some places that SET_MASKS is used with other
+     flags, those are because earlier versions of this table didn't
+     specifically set or clear those flags and I didn't know what the
+     processor supported.  Please delete this comment when all of those
+     cases are gone.  */
 
   static struct ptt
     {
       const char *const name;          /* Canonical processor name.  */
       const enum processor_type processor; /* Processor type enum value.  */
       const int target_enable; /* Target flags to enable.  */
-      const int target_disable;        /* Target flags to disable.  */
+      const int target_set;    /* Target flags to change.  */
     } const processor_target_table[]
       = {{"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_MASKS},
+           SET_MASKS},
         {"power", PROCESSOR_POWER,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"power2", PROCESSOR_POWER,
            MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
-           POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"power3", PROCESSOR_PPC630,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS & ~MASK_POWERPC64 & ~MASK_PPC_GPOPT},
         {"power4", PROCESSOR_POWER4,
-            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-            POWER_MASKS},
+            POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS & ~MASK_POWERPC64 & ~MASK_PPC_GPOPT},
         {"powerpc", PROCESSOR_POWERPC,
-           MASK_POWERPC | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK,
+           SET_MASKS},
         {"powerpc64", PROCESSOR_POWERPC64,
-           MASK_POWERPC | MASK_POWERPC64 | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS},
+           POWERPC_BASE_MASK | MASK_POWERPC64,
+           SET_MASKS},
         {"rios", PROCESSOR_RIOS1,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"rios1", PROCESSOR_RIOS1,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"rsc", PROCESSOR_PPC601,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"rsc1", PROCESSOR_PPC601,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"rios2", PROCESSOR_RIOS2,
            MASK_POWER | MASK_MULTIPLE | MASK_STRING | MASK_POWER2,
-           POWERPC_MASKS | MASK_NEW_MNEMONICS},
+           SET_MASKS},
         {"rs64a", PROCESSOR_RS64A,
-           MASK_POWERPC | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS},
+           POWERPC_BASE_MASK,
+           SET_MASKS},
         {"401", PROCESSOR_PPC403,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"403", PROCESSOR_PPC403,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN,
+           SET_MASKS},
         {"405", PROCESSOR_PPC405,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"405fp", PROCESSOR_PPC405,
-           MASK_POWERPC | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK,
+           SET_MASKS},
         {"440", PROCESSOR_PPC440,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"440fp", PROCESSOR_PPC440,
-           MASK_POWERPC | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK,
+           SET_MASKS},
         {"505", PROCESSOR_MPCCORE,
-           MASK_POWERPC | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK,
+           SET_MASKS},
         {"601", PROCESSOR_PPC601,
-           MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_MULTIPLE | MASK_STRING,
-           MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING,
+           SET_MASKS},
         {"602", PROCESSOR_PPC603,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"603", PROCESSOR_PPC603,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"603e", PROCESSOR_PPC603,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"ec603e", PROCESSOR_PPC603,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"604", PROCESSOR_PPC604,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"604e", PROCESSOR_PPC604e,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"620", PROCESSOR_PPC620,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS & ~MASK_POWERPC64 & ~MASK_PPC_GPOPT},
         {"630", PROCESSOR_PPC630,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS & ~MASK_POWERPC64 & ~MASK_PPC_GPOPT},
         {"740", PROCESSOR_PPC750,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"750", PROCESSOR_PPC750,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"7400", PROCESSOR_PPC7400,
-            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+            POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC,
+            SET_MASKS},
         {"7450", PROCESSOR_PPC7450,
-            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+            POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC,
+            SET_MASKS},
         {"8540", PROCESSOR_PPC8540,
-           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_PPC_GFXOPT,
+           SET_MASKS},
         {"801", PROCESSOR_MPCCORE,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"821", PROCESSOR_MPCCORE,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"823", PROCESSOR_MPCCORE,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"860", PROCESSOR_MPCCORE,
-           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
-           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+           POWERPC_BASE_MASK | MASK_SOFT_FLOAT,
+           SET_MASKS},
         {"970", PROCESSOR_POWER4,
-           MASK_POWERPC | POWERPC_OPT_MASKS | MASK_NEW_MNEMONICS,
-           POWER_MASKS}};
+           POWERPC_BASE_MASK | POWERPC_OPT_MASKS | MASK_ALTIVEC,
+           SET_MASKS & ~MASK_POWERPC64}};
 
   const size_t ptt_size = ARRAY_SIZE (processor_target_table);
 
@@ -697,8 +712,8 @@ rs6000_override_options (const char *default_cpu)
 
                if (ptr->set_arch_p)
                  {
+                   target_flags &= ~processor_target_table[j].target_set;
                    target_flags |= processor_target_table[j].target_enable;
-                   target_flags &= ~processor_target_table[j].target_disable;
                  }
                break;
              }
@@ -3732,10 +3747,25 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
   if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
     {
-      if (cum->vregno <= ALTIVEC_ARG_MAX_REG && cum->nargs_prototype >= 0)
+      if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
        cum->vregno++;
       else
-       cum->words += RS6000_ARG_SIZE (mode, type);
+       {
+         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);
+         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));
+           }
+       }
     }
   else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode)
           && !cum->stdarg
@@ -3913,8 +3943,37 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
     {
       if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
        return gen_rtx_REG (mode, cum->vregno);
+      else if (named || abi == ABI_V4)
+       return NULL_RTX;
       else
-       return NULL;
+       {
+         /* Vector parameters to varargs functions under AIX or Darwin
+            get passed in memory and possibly also in GPRs.  */
+         int align, align_words;
+         rtx reg;
+
+         /* Vector parameters must be 16-byte aligned.  This places them at
+            2 mod 4 in terms of words.  */
+         align = ((6 - (cum->words & 3)) & 3);
+         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)));
+       }
     }
   else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
     return rs6000_spe_function_arg (cum, mode, type);
@@ -4302,7 +4361,29 @@ rs6000_va_arg (tree valist, tree type)
          return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
        }
       else
-       return std_expand_builtin_va_arg (valist, type);
+       {
+         /* Altivec arguments must be aligned to a 128-bit boundary.  */
+         if (ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
+           {
+             tree vtype = TREE_TYPE (valist);
+             tree new_valist, modify;
+             
+             /* Round address up to multiple of 16.  Computes
+                (addr+15)&~0xf.  */
+             new_valist = fold (build (BIT_AND_EXPR, vtype,
+                                       fold (build (PLUS_EXPR, vtype, valist,
+                                                    build_int_2 (15, 0))),
+                                       build_int_2 (~15, -1)));
+
+             /* Update valist.  */
+             modify = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
+                             new_valist);
+             TREE_SIDE_EFFECTS (modify) = 1;
+             expand_expr (modify, const0_rtx, VOIDmode, EXPAND_NORMAL);
+           }
+         
+         return std_expand_builtin_va_arg (valist, type);
+       }
     }
 
   f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
index 77de509d43047b756f5264ec5665741d5803cd6a..d2a37f3cd60e1278fb9373a7b2f7720b5435a2ea 100644 (file)
@@ -780,7 +780,13 @@ if (TARGET_ARCH64                          \
 #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
+/* FIXME, this is wrong when TARGET_ARCH64 and TARGET_STACK_BIAS, because
+   then sp+2047 is 128-bit aligned so sp is really only byte-aligned.  */
 #define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64)
+/* Temporary hack until the FIXME above is fixed.  This macro is used
+   only in pad_to_arg_alignment in function.c; see the comment there
+   for details about what it does.  */
+#define SPARC_STACK_BOUNDARY_HACK (TARGET_ARCH64 && TARGET_STACK_BIAS)
 
 /* ALIGN FRAMES on double word boundaries */
 
index 34e9f7baa63bbccdd2e1aa0b5ea64b46400aaff5..f2595b0be6740a233a2670798821141c23e9d017 100644 (file)
@@ -679,4 +679,8 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
 #define MOVE_MAX_PIECES   MOVE_MAX
 #endif
 
+#ifndef STACK_POINTER_OFFSET
+#define STACK_POINTER_OFFSET    0
+#endif
+
 #endif  /* ! GCC_DEFAULTS_H */
index 0251fe3df159f29a00cfb87f90292ff19e1db5e7..0f158ac8e1589ec436c868307418bc72de1cc2c4 100644 (file)
@@ -5511,6 +5511,16 @@ pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
 {
   tree save_var = NULL_TREE;
   HOST_WIDE_INT save_constant = 0;
+  HOST_WIDE_INT sp_offset = STACK_POINTER_OFFSET;
+
+#ifdef SPARC_STACK_BOUNDARY_HACK
+  /* The sparc port has a bug.  It sometimes claims a STACK_BOUNDARY
+     higher than the real alignment of %sp.  However, when it does this,
+     the alignment of %sp+STACK_POINTER_OFFSET will be STACK_BOUNDARY.
+     This is a temporary hack while the sparc port is fixed.  */
+  if (SPARC_STACK_BOUNDARY_HACK)
+    sp_offset = 0;
+#endif
 
   int boundary_in_bytes = boundary / BITS_PER_UNIT;
 
@@ -5527,14 +5537,17 @@ pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
     {
       if (offset_ptr->var)
        {
-         offset_ptr->var =
+         tree sp_offset_tree = ssize_int (sp_offset);
+         tree offset = size_binop (PLUS_EXPR,
+                                   ARGS_SIZE_TREE (*offset_ptr),
+                                   sp_offset_tree);
 #ifdef ARGS_GROW_DOWNWARD
-           round_down
+         tree rounded = round_down (offset, boundary / BITS_PER_UNIT);
 #else
-           round_up
+         tree rounded = round_up   (offset, boundary / BITS_PER_UNIT);
 #endif
-             (ARGS_SIZE_TREE (*offset_ptr),
-              boundary / BITS_PER_UNIT);
+
+         offset_ptr->var = size_binop (MINUS_EXPR, rounded, sp_offset_tree);
          /* ARGS_SIZE_TREE includes constant term.  */
          offset_ptr->constant = 0;
          if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
@@ -5543,11 +5556,11 @@ pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
        }
       else
        {
-         offset_ptr->constant =
+         offset_ptr->constant = -sp_offset +
 #ifdef ARGS_GROW_DOWNWARD
-           FLOOR_ROUND (offset_ptr->constant, boundary_in_bytes);
+           FLOOR_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
 #else
-           CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
+           CEIL_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
 #endif
            if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
              alignment_pad->constant = offset_ptr->constant - save_constant;
index 49f002aaf7a225636f3b4b188aeea15fd26cd7d5..4cf077551584b49d71ab99bd439f8ef0acae6f2f 100644 (file)
@@ -1,3 +1,8 @@
+2003-10-07  Geoffrey Keating  <geoffk@apple.com>
+
+       * gcc.dg/darwin-abi-2.c: New file.
+       * gcc.c-torture/execute/va-arg-24.c: New file.
+
 2003-10-06  Bob Wilson  <bob.wilson@acm.org>
 
        * g++.dg/template/spec10.C: Set exit value to zero on success.  Fix
diff --git a/gcc/testsuite/gcc.c-torture/execute/va-arg-24.c b/gcc/testsuite/gcc.c-torture/execute/va-arg-24.c
new file mode 100644 (file)
index 0000000..c8fdaf0
--- /dev/null
@@ -0,0 +1,34 @@
+/* Varargs and vectors!  */
+
+#include <stdarg.h>
+
+#define vector __attribute__((vector_size(16)))
+
+const vector unsigned int v1 = {10,11,12,13};
+const vector unsigned int v2 = {20,21,22,23};
+
+void foo(int a, ...)
+{
+  va_list args;
+  vector unsigned int v;
+
+  va_start (args, a);
+  v = va_arg (args, vector unsigned int);
+  if (a != 1 || memcmp (&v, &v1, sizeof (v)) != 0)
+    abort ();
+  a = va_arg (args, int);
+  if (a != 2)
+    abort ();
+  v = va_arg (args, vector unsigned int);
+  if (memcmp (&v, &v2, sizeof (v) != 0))
+    abort ();
+  va_end (args);
+}
+
+int main(void)
+{
+  foo (1, (vector unsigned int){10,11,12,13}, 2,
+       (vector unsigned int){14,15,16,17});
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/darwin-abi-2.c b/gcc/testsuite/gcc.dg/darwin-abi-2.c
new file mode 100644 (file)
index 0000000..81da83c
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do run { target powerpc*-*-darwin* } } */
+
+/* You might think you'd need -maltivec for this, but actually you
+   don't; GCC will happily do everything in GPRs, and it still
+   tests that the ABI is correct.  */
+
+#include <stdio.h>
+
+#define vector __attribute__((vector_size(16)))
+
+int main(void)
+{
+  vector unsigned int v = { 100, 200, 300, 400 };
+  vector unsigned int w = { 4, 5, 6, 7 };
+  char x[64];
+  sprintf (x, "%lvu,%d,%lvu", v, 1, w);
+  if (strcmp (x, "100 200 300 400,1,4 5 6 7") != 0)
+    {
+      puts (x);
+      abort ();
+    }
+  return 0;
+}