rs6000.c (function_arg_pass_by_reference): Return true for variable sized types.
authorDavid Edelsohn <edelsohn@gnu.org>
Wed, 29 Jan 2003 17:37:25 +0000 (17:37 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Wed, 29 Jan 2003 17:37:25 +0000 (12:37 -0500)
        * config/rs6000/rs6000.c (function_arg_pass_by_reference):
        Return true for variable sized types.
        (rs6000_va_arg): Handle variable sized types passed by reference
        on non-SVR4 ABI.

From-SVN: r62095

gcc/ChangeLog
gcc/config/rs6000/rs6000.c

index 744f12683d5f54051024bb2f3b6085e5d042f400..8d908ff23a6a0eed02eea29c2958c4b40b8dd7c9 100644 (file)
@@ -1,3 +1,10 @@
+2003-01-29  David Edelsohn  <edelsohn@gnu.org>
+
+       * config/rs6000/rs6000.c (function_arg_pass_by_reference):
+       Return true for variable sized types.
+       (rs6000_va_arg): Handle variable sized types passed by reference
+       on non-SVR4 ABI.
+
 2003-01-29  Richard Earnshaw  <rearnsha@arm.com>
 
        * arm.c (arm_legtimize_address): New function.
index 31eb55e2ec75822389b29df75add975840a8694d..41284e87cc87120f79e3803d73ee6389c06661f1 100644 (file)
@@ -3314,7 +3314,10 @@ function_arg_partial_nregs (cum, mode, type, named)
    the argument itself.  The pointer is passed in whatever way is
    appropriate for passing a pointer to that type.
 
-   Under V.4, structures and unions are passed by reference.  */
+   Under V.4, structures and unions are passed by reference.
+
+   As an extension to all ABIs, variable sized types are passed by
+   reference.  */
 
 int
 function_arg_pass_by_reference (cum, mode, type, named)
@@ -3332,8 +3335,7 @@ function_arg_pass_by_reference (cum, mode, type, named)
 
       return 1;
     }
-
-  return 0;
+  return type && int_size_in_bytes (type) <= 0;
 }
 \f
 /* Perform any needed actions needed for a function that is receiving a
@@ -3569,7 +3571,28 @@ rs6000_va_arg (valist, type)
   rtx lab_false, lab_over, addr_rtx, r;
 
   if (DEFAULT_ABI != ABI_V4)
-    return std_expand_builtin_va_arg (valist, type);
+    {
+      /* Variable sized types are passed by reference.  */
+      if (int_size_in_bytes (type) <= 0)
+       {
+         u = build_pointer_type (type);
+
+         /* Args grow upward.  */
+         t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
+                    build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
+         TREE_SIDE_EFFECTS (t) = 1;
+
+         t = build1 (NOP_EXPR, build_pointer_type (u), t);
+         TREE_SIDE_EFFECTS (t) = 1;
+
+         t = build1 (INDIRECT_REF, u, t);
+         TREE_SIDE_EFFECTS (t) = 1;
+
+         return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+       }
+      else
+       return std_expand_builtin_va_arg (valist, type);
+    }
 
   f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
   f_fpr = TREE_CHAIN (f_gpr);