sparc.h (EXPAND_BUILTIN_VA_START): Define.
authorRichard Henderson <rth@cygnus.com>
Sun, 5 Sep 1999 00:16:18 +0000 (17:16 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 5 Sep 1999 00:16:18 +0000 (17:16 -0700)
        * sparc.h (EXPAND_BUILTIN_VA_START): Define.
        (EXPAND_BUILTIN_VA_ARG): Define.
        * sparc.c (sparc_va_start): New.
        (sparc_va_arg): New.

From-SVN: r29115

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h

index fe084e32f75d913518f173319d9aa8f204aa3717..d417604b255b973de628f698f4b70384584357f1 100644 (file)
@@ -1,3 +1,10 @@
+Sat Sep  4 17:15:13 1999  Richard Henderson  <rth@cygnus.com>
+
+       * sparc.h (EXPAND_BUILTIN_VA_START): Define.
+       (EXPAND_BUILTIN_VA_ARG): Define.
+       * sparc.c (sparc_va_start): New.
+       (sparc_va_arg): New.
+
 Sun Sep  5 11:11:59 1999  Michael Hayes  <m.hayes@elec.canterbury.ac.nz>
 
        * config/c4x/c4x.h (DBR_OUTPUT_SEQEND): Use XVECEXP not XEXPs.
index ad51856714db0e603400732971a724aab2c973c7..622e04b0774c2be4f7401fcf8cb1e15e246647d2 100644 (file)
@@ -4280,6 +4280,96 @@ sparc_builtin_saveregs ()
 
   return address;
 }
+
+/* Implement `va_start' for varargs and stdarg.  */
+
+void
+sparc_va_start (stdarg_p, valist, nextarg)
+     int stdarg_p ATTRIBUTE_UNUSED;
+     tree valist;
+     rtx nextarg;
+{
+  nextarg = expand_builtin_saveregs ();
+  std_expand_builtin_va_start (1, valist, nextarg);
+}
+
+/* Implement `va_arg'.  */
+
+rtx
+sparc_va_arg (valist, type)
+     tree valist, type;
+{
+  HOST_WIDE_INT size, rsize, align;
+  tree addr, incr, tmp;
+  rtx addr_rtx;
+  int indirect = 0;
+
+  /* Round up sizeof(type) to a word.  */
+  size = int_size_in_bytes (type);
+  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+  align = 0;
+
+  if (TARGET_ARCH64)
+    {
+      if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD)
+       align = 2 * UNITS_PER_WORD;
+
+      if (AGGREGATE_TYPE_P (type) && size > 16)
+       {
+         indirect = 1;
+         size = rsize = UNITS_PER_WORD;
+       }
+    }
+  else
+    {
+      if (AGGREGATE_TYPE_P (type)
+         || TYPE_MODE (type) == TFmode
+         || TYPE_MODE (type) == TCmode)
+       {
+         indirect = 1;
+         size = rsize = UNITS_PER_WORD;
+       }
+      else
+       {
+         /* ??? The old va-sparc.h implementation, for 8 byte objects
+            copied stuff to a temporary -- I don't see that that 
+            provides any more alignment than the stack slot did.  */
+       }
+    }
+
+  incr = valist;
+  if (align)
+    {
+      incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+                        build_int_2 (align - 1, 0)));
+      incr = fold (build (BIT_AND_EXPR, ptr_type_node, incr,
+                         build_int_2 (-align, -1)));
+    }
+
+  addr = incr = save_expr (incr);
+  if (BYTES_BIG_ENDIAN && size < rsize)
+    {
+      addr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+                         build_int_2 (rsize - size, 0)));
+    }
+  incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+                     build_int_2 (rsize, 0)));
+
+  incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
+  TREE_SIDE_EFFECTS (incr) = 1;
+  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
+
+  if (indirect)
+    {
+      addr_rtx = force_reg (Pmode, addr_rtx);
+      addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
+      MEM_ALIAS_SET (addr_rtx) = get_varargs_alias_set ();
+    }
+
+  return addr_rtx;
+}
 \f
 /* Return the string to output a conditional branch to LABEL, which is
    the operand number of the label.  OP is the conditional expression.
index 9d78988ed48a7c7a0aa3b82f57146f171d277f2f..d113248b808abba8eb1e2eb5c65e6e280424ab82 100644 (file)
@@ -2046,6 +2046,14 @@ void sparc64_initialize_trampoline ();
 extern struct rtx_def *sparc_builtin_saveregs ();
 #define EXPAND_BUILTIN_SAVEREGS() sparc_builtin_saveregs ()
 
+/* Implement `va_start' for varargs and stdarg.  */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+  sparc_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'.  */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+  sparc_va_arg (valist, type)
+
 /* Define this macro if the location where a function argument is passed
    depends on whether or not it is a named argument.