]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR target/45843 (__builtin_va_arg overwrites into adjacent stack location)
authorJakub Jelinek <jakub@redhat.com>
Fri, 1 Oct 2010 13:13:31 +0000 (15:13 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 1 Oct 2010 13:13:31 +0000 (15:13 +0200)
Backport from mainline
2010-09-30  Jakub Jelinek  <jakub@redhat.com>

PR target/45843
* config/i386/i386.c (ix86_gimplify_va_arg): Use
INTVAL (XEXP (slot, 1)) as prev_size.

2010-06-21  Jakub Jelinek  <jakub@redhat.com>

PR target/44575
* config/i386/i386.c (ix86_gimplify_va_arg): When copying
va_arg from a set of register save slots into a temporary,
if the container is bigger than type size, do the copying
using smaller mode or using memcpy.

Backport from mainline
2010-09-30  Jakub Jelinek  <jakub@redhat.com>

* g++.dg/torture/pr45843.C: New test.

2010-06-21  Jakub Jelinek  <jakub@redhat.com>

PR target/44575
* gcc.c-torture/execute/pr44575.c: New test.

From-SVN: r164884

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr45843.C [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr44575.c [new file with mode: 0644]

index bf70aa28306f427d329d0d4894b653d2ee159999..43a324132cc1e2c63966101c4be715b16252fc4b 100644 (file)
@@ -1,3 +1,20 @@
+2010-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       Backport from mainline
+       2010-09-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/45843
+       * config/i386/i386.c (ix86_gimplify_va_arg): Use
+       INTVAL (XEXP (slot, 1)) as prev_size.
+
+       2010-06-21  Jakub Jelinek  <jakub@redhat.com>
+       PR target/44575
+       * config/i386/i386.c (ix86_gimplify_va_arg): When copying
+       va_arg from a set of register save slots into a temporary,
+       if the container is bigger than type size, do the copying
+       using smaller mode or using memcpy.
+
 2010-10-01  Jakub Jelinek  <jakub@redhat.com>
 
        * BASE-VER: Set to 4.4.6.
index 2fc03586224dade1d78e9e6502ee6e95ecf812ab..112b1b1d92ead5315b6d4dba7a49d6cbae4438d6 100644 (file)
@@ -6956,7 +6956,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
        }
       if (need_temp)
        {
-         int i;
+         int i, prev_size = 0;
          tree temp = create_tmp_var (type, "va_arg_tmp");
 
          /* addr = &temp; */
@@ -6968,13 +6968,31 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
              rtx slot = XVECEXP (container, 0, i);
              rtx reg = XEXP (slot, 0);
              enum machine_mode mode = GET_MODE (reg);
-             tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
-             tree addr_type = build_pointer_type (piece_type);
-             tree daddr_type = build_pointer_type_for_mode (piece_type,
-                                                            ptr_mode, true);
+             tree piece_type;
+             tree addr_type;
+             tree daddr_type;
              tree src_addr, src;
              int src_offset;
              tree dest_addr, dest;
+             int cur_size = GET_MODE_SIZE (mode);
+
+             gcc_assert (prev_size <= INTVAL (XEXP (slot, 1)));
+             prev_size = INTVAL (XEXP (slot, 1));
+             if (prev_size + cur_size > size)
+               {
+                 cur_size = size - prev_size;
+                 mode = mode_for_size (cur_size * BITS_PER_UNIT, MODE_INT, 1);
+                 if (mode == BLKmode)
+                   mode = QImode;
+               }
+             piece_type = lang_hooks.types.type_for_mode (mode, 1);
+             if (mode == GET_MODE (reg))
+               addr_type = build_pointer_type (piece_type);
+             else
+               addr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
+                                                        true);
+             daddr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
+                                                       true);
 
              if (SSE_REGNO_P (REGNO (reg)))
                {
@@ -6989,14 +7007,26 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
              src_addr = fold_convert (addr_type, src_addr);
              src_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, src_addr,
                                      size_int (src_offset));
-             src = build_va_arg_indirect_ref (src_addr);
 
              dest_addr = fold_convert (daddr_type, addr);
              dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
-                                      size_int (INTVAL (XEXP (slot, 1))));
-             dest = build_va_arg_indirect_ref (dest_addr);
+                                      size_int (prev_size));
+             if (cur_size == GET_MODE_SIZE (mode))
+               {
+                 src = build_va_arg_indirect_ref (src_addr);
+                 dest = build_va_arg_indirect_ref (dest_addr);
 
-             gimplify_assign (dest, src, pre_p);
+                 gimplify_assign (dest, src, pre_p);
+               }
+             else
+               {
+                 tree copy
+                   = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+                                      3, dest_addr, src_addr,
+                                      size_int (cur_size));
+                 gimplify_and_add (copy, pre_p);
+               }
+             prev_size += cur_size;
            }
        }
 
index ac1281daaaba7db3b8644e0876fa68e15da6358b..ee343be18d32ccae07622d1f003ef3215a86d278 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-01  Jakub Jelinek  <jakub@redhat.com>
+
+       Backport from mainline
+       2010-09-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/torture/pr45843.C: New test.
+
+       2010-06-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/44575
+       * gcc.c-torture/execute/pr44575.c: New test.
+
 2010-10-01  Release Manager
 
        * GCC 4.4.5 released.
diff --git a/gcc/testsuite/g++.dg/torture/pr45843.C b/gcc/testsuite/g++.dg/torture/pr45843.C
new file mode 100644 (file)
index 0000000..f77b8cb
--- /dev/null
@@ -0,0 +1,28 @@
+// PR target/45843
+// { dg-do run }
+
+#include <stdarg.h>
+
+extern "C" void abort ();
+struct S { struct T { } a[14]; char b; };
+struct S arg, s;
+
+void
+foo (int z, ...)
+{
+  char c;
+  va_list ap;
+  va_start (ap, z);
+  c = 'a';
+  arg = va_arg (ap, struct S);
+  if (c != 'a')
+    abort ();
+  va_end (ap);
+}
+
+int
+main ()
+{
+  foo (1, s);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr44575.c b/gcc/testsuite/gcc.c-torture/execute/pr44575.c
new file mode 100644 (file)
index 0000000..62a7d78
--- /dev/null
@@ -0,0 +1,49 @@
+/* PR target/44575 */
+
+#include <stdarg.h>
+
+int fails = 0;
+struct S { float a[3]; };
+struct S a[5];
+
+void
+check (int z, ...)
+{
+  struct S arg, *p;
+  va_list ap;
+  int j = 0, k = 0;
+  int i;
+  va_start (ap, z);
+  for (i = 2; i < 4; ++i)
+    {
+      p = 0;
+      j++;
+      k += 2;
+      switch ((z << 4) | i)
+       {
+       case 0x12:
+       case 0x13:
+         p = &a[2];
+         arg = va_arg (ap, struct S);
+         break;
+       default:
+         ++fails;
+         break;
+       }
+      if (p && p->a[2] != arg.a[2])
+       ++fails;
+      if (fails)
+       break;
+    }
+  va_end (ap);
+}
+
+int
+main ()
+{
+  a[2].a[2] = -49026;
+  check (1, a[2], a[2]);
+  if (fails)
+    abort ();
+  return 0;
+}