OSDN Git Service

Workaround PR middle-end/55142
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 19 Nov 2012 19:17:05 +0000 (19:17 +0000)
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 19 Nov 2012 19:17:05 +0000 (19:17 +0000)
gcc/

2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>

Backported from mainline
2012-11-13  Eric Botcazou  <ebotcazou@adacore.com>
    H.J. Lu  <hongjiu.lu@intel.com>

PR middle-end/55142
* config/i386/i386.c (legitimize_pic_address): Properly handle
REG + CONST.
(ix86_print_operand_address): Set code to 'k' when forcing
addr32 prefix.  For x32, zero-extend negative displacement if
it < -16*1024*1024.

gcc/testsuite/

2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>

Backported from mainline
2012-11-13  H.J. Lu  <hongjiu.lu@intel.com>

PR middle-end/55142
* gcc.target/i386/pr55142-1.c: New file.
* gcc.target/i386/pr55142-2.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@193635 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr55142-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr55142-2.c [new file with mode: 0644]

index c7fce0b..b33aeea 100644 (file)
@@ -1,3 +1,16 @@
+2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       Backported from mainline
+       2012-11-13  Eric Botcazou  <ebotcazou@adacore.com>
+                   H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR middle-end/55142
+       * config/i386/i386.c (legitimize_pic_address): Properly handle
+       REG + CONST.
+       (ix86_print_operand_address): Set code to 'k' when forcing
+       addr32 prefix.  For x32, zero-extend negative displacement if
+       it < -16*1024*1024.
+
 2012-11-12  Eric Botcazou  <ebotcazou@adacore.com>
 
        * common.opt (fvar-tracking-uninit): Document.
index 45be11b..b805af6 100644 (file)
@@ -12330,7 +12330,6 @@ legitimize_pic_address (rtx orig, rtx reg)
 {
   rtx addr = orig;
   rtx new_rtx = orig;
-  rtx base;
 
 #if TARGET_MACHO
   if (TARGET_MACHO && !TARGET_64BIT)
@@ -12535,20 +12534,33 @@ legitimize_pic_address (rtx orig, rtx reg)
            }
          else
            {
-             base = legitimize_pic_address (XEXP (addr, 0), reg);
-             new_rtx  = legitimize_pic_address (XEXP (addr, 1),
-                                                base == reg ? NULL_RTX : reg);
+             rtx base = legitimize_pic_address (op0, reg);
+             enum machine_mode mode = GET_MODE (base);
+             new_rtx
+               = legitimize_pic_address (op1, base == reg ? NULL_RTX : reg);
 
              if (CONST_INT_P (new_rtx))
-               new_rtx = plus_constant (base, INTVAL (new_rtx));
+               {
+                 if (INTVAL (new_rtx) < -16*1024*1024
+                     || INTVAL (new_rtx) >= 16*1024*1024)
+                   {
+                     if (!x86_64_immediate_operand (new_rtx, mode))
+                       new_rtx = force_reg (mode, new_rtx);
+                     new_rtx
+                       = gen_rtx_PLUS (mode, force_reg (mode, base), new_rtx);
+                   }
+                 else
+                   new_rtx = plus_constant (base, INTVAL (new_rtx));
+               }
              else
                {
-                 if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
+                 if (GET_CODE (new_rtx) == PLUS
+                     && CONSTANT_P (XEXP (new_rtx, 1)))
                    {
-                     base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
+                     base = gen_rtx_PLUS (mode, base, XEXP (new_rtx, 0));
                      new_rtx = XEXP (new_rtx, 1);
                    }
-                 new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
+                 new_rtx = gen_rtx_PLUS (mode, base, new_rtx);
                }
            }
        }
@@ -14642,7 +14654,30 @@ ix86_print_operand_address (FILE *file, rtx addr)
            }
 #endif
          gcc_assert (!code);
-         code = 'l';
+         code = 'k';
+       }
+      else if (code == 0
+              && TARGET_X32
+              && disp
+              && CONST_INT_P (disp)
+              && INTVAL (disp) < -16*1024*1024)
+       {
+         /* X32 runs in 64-bit mode, where displacement, DISP, in
+            address DISP(%r64), is encoded as 32-bit immediate sign-
+            extended from 32-bit to 64-bit.  For -0x40000300(%r64),
+            address is %r64 + 0xffffffffbffffd00.  When %r64 <
+            0x40000300, like 0x37ffe064, address is 0xfffffffff7ffdd64,
+            which is invalid for x32.  The correct address is %r64
+            - 0x40000300 == 0xf7ffdd64.  To properly encode
+            -0x40000300(%r64) for x32, we zero-extend negative
+            displacement by forcing addr32 prefix which truncates
+            0xfffffffff7ffdd64 to 0xf7ffdd64.  In theory, we should
+            zero-extend all negative displacements, including -1(%rsp).
+            However, for small negative displacements, sign-extension
+            won't cause overflow.  We only zero-extend negative
+            displacements if they < -16*1024*1024, which is also used
+            to check legitimate address displacements for PIC.  */
+         code = 'k';
        }
 
       if (ASSEMBLER_DIALECT == ASM_ATT)
index 7f402b1..a040c81 100644 (file)
@@ -1,3 +1,12 @@
+2012-11-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       Backported from mainline
+       2012-11-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR middle-end/55142
+       * gcc.target/i386/pr55142-1.c: New file.
+       * gcc.target/i386/pr55142-2.c: Likewise.
+
 2012-11-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/stack_check3.ad[sb]: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr55142-1.c b/gcc/testsuite/gcc.target/i386/pr55142-1.c
new file mode 100644 (file)
index 0000000..28375b5
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -mx32 -fpic" } */
+
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef int32_t Elf32_Sword;
+typedef struct
+{
+  Elf32_Sword d_tag;
+} Elf32_Dyn;
+struct link_map
+{
+  Elf32_Dyn *l_ld;
+  Elf32_Dyn *l_info[34];
+};
+extern struct link_map _dl_rtld_map __attribute__ ((visibility ("hidden")));
+static void elf_get_dynamic_info (struct link_map *l)
+{
+  Elf32_Dyn *dyn = l->l_ld;
+  Elf32_Dyn **info;
+  info = l->l_info;
+  while (dyn->d_tag != 0)
+    {
+      if ((uint32_t) (0x6ffffeff - dyn->d_tag) < 11)
+       info[0x6ffffeff - dyn->d_tag + 12] = dyn;
+      ++dyn;
+    }
+}
+void
+foo (void)
+{
+  elf_get_dynamic_info (&_dl_rtld_map);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr55142-2.c b/gcc/testsuite/gcc.target/i386/pr55142-2.c
new file mode 100644 (file)
index 0000000..9daae9d
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O3 -mx32 -fpic" } */
+/* { dg-final { scan-assembler-not "movl\[\\t \]*%.*,\[\\t \]*-1073742592\\(%r(.x|.i|.p|\[1-9\]*)\\)" } } */
+
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Addr;
+typedef struct {
+  Elf32_Sword d_tag;
+  union {
+    Elf32_Word d_val;
+    Elf32_Addr d_ptr;
+  } d_un;
+} Elf32_Dyn;
+struct link_map {
+  Elf32_Dyn *l_ld;
+  Elf32_Dyn *l_info[34 + 16 + 3 + 12 + 11];
+};
+void
+elf_get_dynamic_info (struct link_map *l)
+{
+  Elf32_Dyn *dyn = l->l_ld;
+  Elf32_Dyn **info = l->l_info;
+  typedef Elf32_Word d_tag_utype;
+  while (dyn->d_tag != 0) {
+    if ((d_tag_utype) (0x6ffffeff - dyn->d_tag) < 11)
+      info[(0x6ffffeff - dyn->d_tag) + 34 + 16 + 3 + 12] = dyn;
+    ++dyn;
+  }
+}