re PR c/3711 (ICE in instantiate_virtual_regs_1, at function.c:3880)
authorJakub Jelinek <jakub@redhat.com>
Fri, 8 Mar 2002 13:45:13 +0000 (14:45 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 8 Mar 2002 13:45:13 +0000 (14:45 +0100)
PR c/3711
* builtins.c (std_expand_builtin_va_arg): Do all computations on
trees.

* gcc.c-torture/execute/20020307-2.c: New test.

From-SVN: r50438

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20020307-2.c [new file with mode: 0644]

index b951136272edeb8e8fa4bae9eef8d498d85b5f05..ea61862664c5367f71f09daaa90fe61cc640c035 100644 (file)
@@ -1,3 +1,9 @@
+2002-03-08  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/3711
+       * builtins.c (std_expand_builtin_va_arg): Do all computations on
+       trees.
+
 Fri Mar  8 06:48:45 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * rtl.c (copy_most_rtx): Move from here ...
index c4aebd3a801ab1950dad6087cc4b1f93e6fdba92..806dd0dc5d229d4c4d1aa751819a094b796a0f17 100644 (file)
@@ -2986,37 +2986,54 @@ rtx
 std_expand_builtin_va_arg (valist, type)
      tree valist, type;
 {
-  tree addr_tree, t;
-  HOST_WIDE_INT align;
-  HOST_WIDE_INT rounded_size;
+  tree addr_tree, t, type_size = NULL;
+  tree align, alignm1;
+  tree rounded_size;
   rtx addr;
 
   /* Compute the rounded size of the type.  */
-  align = PARM_BOUNDARY / BITS_PER_UNIT;
-  rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
+  align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
+  alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
+  if (type == error_mark_node
+      || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
+      || TREE_OVERFLOW (type_size))
+    rounded_size = size_zero_node;
+  else
+    rounded_size = fold (build (MULT_EXPR, sizetype,
+                               fold (build (TRUNC_DIV_EXPR, sizetype,
+                                            fold (build (PLUS_EXPR, sizetype,
+                                                         type_size, alignm1)),
+                                            align)),
+                               align));
 
   /* Get AP.  */
   addr_tree = valist;
-  if (PAD_VARARGS_DOWN)
+  if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
     {
       /* Small args are padded downward.  */
-
-      HOST_WIDE_INT adj
-       = rounded_size > align ? rounded_size : int_size_in_bytes (type);
-
-      addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
-                        build_int_2 (rounded_size - adj, 0));
+      addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
+                              fold (build (COND_EXPR, sizetype,
+                                           fold (build (GT_EXPR, sizetype,
+                                                        rounded_size,
+                                                        align)),
+                                           size_zero_node,
+                                           fold (build (MINUS_EXPR, sizetype,
+                                                        rounded_size,
+                                                        type_size))))));
     }
 
   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
   addr = copy_to_reg (addr);
 
   /* Compute new value for AP.  */
-  t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
-            build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                   build_int_2 (rounded_size, 0)));
-  TREE_SIDE_EFFECTS (t) = 1;
-  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+  if (! integer_zerop (rounded_size))
+    {
+      t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
+                build (PLUS_EXPR, TREE_TYPE (valist), valist,
+                       rounded_size));
+      TREE_SIDE_EFFECTS (t) = 1;
+      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+    }
 
   return addr;
 }
index ffe70aa345d7f189281f728f5c86f707acf1866c..1c069289aa8f5d79ce2ae6ee971286a2d245d167 100644 (file)
@@ -1,3 +1,7 @@
+2002-03-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.c-torture/execute/20020307-2.c: New test.
+
 Thu Mar  7 10:05:31 2002  Jeffrey A Law  (law@redhat.com)
 
        * g77.f-torture/compile/20020307-1.f: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20020307-2.c b/gcc/testsuite/gcc.c-torture/execute/20020307-2.c
new file mode 100644 (file)
index 0000000..0e67a2c
--- /dev/null
@@ -0,0 +1,55 @@
+/* PR c/3711
+   This testcase ICEd on IA-32 at -O0 and was miscompiled otherwise,
+   because std_expand_builtin_va_arg didn't handle variable size types.  */
+
+#include <stdarg.h>
+
+extern void abort (void);
+extern void exit (int);
+
+void bar (int c)
+{
+  static int d = '0';
+
+  if (c != d++)
+    abort ();
+  if (c < '0' || c > '9')
+    abort ();
+}
+
+void foo (int size, ...)
+{
+  struct
+  {
+    char x[size];
+  } d;
+  va_list ap;
+  int i;
+
+  va_start (ap, size);
+  d = va_arg (ap, typeof (d));
+  for (i = 0; i < size; i++)
+    bar (d.x[i]);
+  d = va_arg (ap, typeof (d));
+  for (i = 0; i < size; i++)
+    bar (d.x[i]);
+  va_end (ap);
+}
+
+int main (void)
+{
+  struct { char a[5]; } x, y;
+          
+  x.a[0] = '0';
+  x.a[1] = '1';
+  x.a[2] = '2';
+  x.a[3] = '3';
+  x.a[4] = '4';
+  y.a[0] = '5';
+  y.a[1] = '6';
+  y.a[2] = '7';
+  y.a[3] = '8';
+  y.a[4] = '9';
+  foo (5, x, y);
+  exit (0);
+}