]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Access external function via GOT slot for -fno-plt
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 Jun 2016 16:30:43 +0000 (16:30 +0000)
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 Jun 2016 16:30:43 +0000 (16:30 +0000)
i386 psABI has been updated to clarify that R_386_GOT32X and R_386_GOT32
relocations can be used to access GOT without base register when PIC is
disabled:

https://groups.google.com/forum/#!topic/ia32-abi/awsRSvJOJfs

32-bit x86 assembler and linker from binutils 2.26.1 and 2.27 support

call/jmp *_start@GOT
cmpl $0, bar@GOT

for both normal and IFUNC functions.  We check if 32-bit x86 assembler
and linker have the fix for:

https://sourceware.org/bugzilla/show_bug.cgi?id=20244

before accessing external function via GOT slot for -fno-plt in both PIC
and non-PIC modes.

PR target/66232
PR target/67400
* configure.ac (as_ix86_tls_ldm_opt): Renamed to ...
(as_ix86_gas_32_opt): This.
(ld_ix86_tls_ldm_opt): Renamed to ...
(ld_ix86_gld_32_opt): This.
(R_386_TLS_LDM reloc): Updated.
(R_386_GOT32X reloc): New assembler/linker check.
(HAVE_AS_IX86_GOT32X): New.  Defined to 1 if 32-bit assembler and
linker support "jmp *_start@GOT" and "cmpl $0, bar@GOT".  Otherise,
defined to 0.
* config.in: Regenerated.
* configure: Likewise.
* config/i386/i386.c (ix86_force_load_from_GOT_p): Return
true if HAVE_AS_IX86_GOT32X is 1 in 32-bit mode.
(ix86_legitimate_address_p): Allow UNSPEC_GOT for -fno-plt
if ix86_force_load_from_GOT_p returns true.
(ix86_print_operand_address_as): Also support UNSPEC_GOT if
ix86_force_load_from_GOT_p returns true.
(ix86_expand_move): Generate UNSPEC_GOT in 32-bit mode to load
the external function address via the GOT slot.
(ix86_nopic_noplt_attribute_p): Check both TARGET_64BIT and
HAVE_AS_IX86_GOT32X before returning false.
(ix86_output_call_insn): Generate "%!jmp/call\t*%p0@GOT" in
32-bit mode if ix86_nopic_noplt_attribute_p returns true.

gcc/testsuite/

PR target/66232
PR target/67400
* gcc.target/i386/pr66232-14.c: New file.
* gcc.target/i386/pr66232-15.c: Likewise.
* gcc.target/i386/pr66232-16.c: Likewise.
* gcc.target/i386/pr66232-17.c: Likewise.
* gcc.target/i386/pr67400-1.c: Don't disable for ia32.  Scan for
ia32 if R_386_GOT32X relocation is supported.
* gcc.target/i386/pr67400-2.c: Likewise.
* gcc.target/i386/pr67400-3.c: Likewise.
* gcc.target/i386/pr67400-4.c: Likewise.
* gcc.target/i386/pr67400-6.c: Likewise.
* gcc.target/i386/pr67400-7.c: Likewise.
* lib/target-supports.exp (check_effective_target_got32x_reloc):
New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@237736 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/ChangeLog
gcc/config.in
gcc/config/i386/i386.c
gcc/configure
gcc/configure.ac
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr66232-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-15.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-16.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-17.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr67400-1.c
gcc/testsuite/gcc.target/i386/pr67400-2.c
gcc/testsuite/gcc.target/i386/pr67400-3.c
gcc/testsuite/gcc.target/i386/pr67400-4.c
gcc/testsuite/gcc.target/i386/pr67400-6.c
gcc/testsuite/gcc.target/i386/pr67400-7.c
gcc/testsuite/lib/target-supports.exp

index ffa702a73f644915004c2381287fd6d8f4603bf0..c36062eb6172eb63473dd1a36668491682c36804 100644 (file)
@@ -1,3 +1,31 @@
+2016-06-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/66232
+       PR target/67400
+       * configure.ac (as_ix86_tls_ldm_opt): Renamed to ...
+       (as_ix86_gas_32_opt): This.
+       (ld_ix86_tls_ldm_opt): Renamed to ...
+       (ld_ix86_gld_32_opt): This.
+       (R_386_TLS_LDM reloc): Updated.
+       (R_386_GOT32X reloc): New assembler/linker check.
+       (HAVE_AS_IX86_GOT32X): New.  Defined to 1 if 32-bit assembler and
+       linker support "jmp *_start@GOT" and "cmpl $0, bar@GOT".  Otherise,
+       defined to 0.
+       * config.in: Regenerated.
+       * configure: Likewise.
+       * config/i386/i386.c (ix86_force_load_from_GOT_p): Return
+       true if HAVE_AS_IX86_GOT32X is 1 in 32-bit mode.
+       (ix86_legitimate_address_p): Allow UNSPEC_GOT for -fno-plt
+       if ix86_force_load_from_GOT_p returns true.
+       (ix86_print_operand_address_as): Also support UNSPEC_GOT if
+       ix86_force_load_from_GOT_p returns true.
+       (ix86_expand_move): Generate UNSPEC_GOT in 32-bit mode to load
+       the external function address via the GOT slot.
+       (ix86_nopic_noplt_attribute_p): Check both TARGET_64BIT and
+       HAVE_AS_IX86_GOT32X before returning false.
+       (ix86_output_call_insn): Generate "%!jmp/call\t*%p0@GOT" in
+       32-bit mode if ix86_nopic_noplt_attribute_p returns true.
+
 2016-06-23  Eric Botcazou  <ebotcazou@adacore.com>
 
        * tree-inline.c (remap_decl): Preserve DECL_ORIGINAL_TYPE invariant.
index 2deb8edf681cc26b09d396b2764005ac642eb1bc..5f801761d2c1a8d2fed86620b4f723f7b650c510 100644 (file)
 #endif
 
 
+/* Define 0/1 if your assembler and linker support @GOT. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_GOT32X
+#endif
+
+
 /* Define if your assembler supports HLE prefixes. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_IX86_HLE
 #undef HAVE_AS_SPARC4
 #endif
 
-/* Define if your assembler supports SPARC5 and VIS4.0 instructions. */
+
+/* Define if your assembler supports SPARC5 and VIS 4.0 instructions. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_SPARC5_VIS4
 #endif
index 9c7b015e9c8f99ea066046bb9e232b7539eca579..f7944f994ebc2b6733d346f6ee66ab47939d0da5 100644 (file)
@@ -15125,7 +15125,8 @@ darwin_local_data_pic (rtx disp)
 bool
 ix86_force_load_from_GOT_p (rtx x)
 {
-  return (TARGET_64BIT && !TARGET_PECOFF && !TARGET_MACHO
+  return ((TARGET_64BIT || HAVE_AS_IX86_GOT32X)
+         && !TARGET_PECOFF && !TARGET_MACHO
          && !flag_plt && !flag_pic
          && ix86_cmodel != CM_LARGE
          && GET_CODE (x) == SYMBOL_REF
@@ -15602,10 +15603,16 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
          && XINT (XEXP (disp, 0), 1) != UNSPEC_MACHOPIC_OFFSET)
        switch (XINT (XEXP (disp, 0), 1))
          {
-         /* Refuse GOTOFF and GOT in 64bit mode since it is always 64bit when
-            used.  While ABI specify also 32bit relocations, we don't produce
-            them at all and use IP relative instead.  */
+         /* Refuse GOTOFF and GOT in 64bit mode since it is always 64bit
+            when used.  While ABI specify also 32bit relocations, we
+            don't produce them at all and use IP relative instead.
+            Allow GOT in 32bit mode for both PIC and non-PIC if symbol
+            should be loaded via GOT.  */
          case UNSPEC_GOT:
+           if (!TARGET_64BIT
+               && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0)))
+             goto is_legitimate_pic;
+           /* FALLTHRU */
          case UNSPEC_GOTOFF:
            gcc_assert (flag_pic);
            if (!TARGET_64BIT)
@@ -18194,7 +18201,8 @@ ix86_print_operand_address_as (FILE *file, rtx addr,
       /* Load the external function address via the GOT slot to avoid PLT.  */
       else if (GET_CODE (disp) == CONST
               && GET_CODE (XEXP (disp, 0)) == UNSPEC
-              && XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL
+              && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL
+                  || XINT (XEXP (disp, 0), 1) == UNSPEC_GOT)
               && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0)))
        output_pic_addr_const (file, disp, 0);
       else if (flag_pic)
@@ -19449,7 +19457,9 @@ ix86_expand_move (machine_mode mode, rtx operands[])
        {
          /* Load the external function address via GOT slot to avoid PLT.  */
          op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
-                               UNSPEC_GOTPCREL);
+                               (TARGET_64BIT
+                                ? UNSPEC_GOTPCREL
+                                : UNSPEC_GOT));
          op1 = gen_rtx_CONST (Pmode, op1);
          op1 = gen_const_mem (Pmode, op1);
          set_mem_alias_set (op1, ix86_GOT_alias_set ());
@@ -28016,18 +28026,19 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
   return call;
 }
 
-/* Return true if the function being called was marked with attribute "noplt"
-   or using -fno-plt and we are compiling for non-PIC and x86_64.  We need to
-   handle the non-PIC case in the backend because there is no easy interface
-   for the front-end to force non-PLT calls to use the GOT.  This is currently
-   used only with 64-bit ELF targets to call the function marked "noplt"
-   indirectly.  */
+/* Return true if the function being called was marked with attribute
+   "noplt" or using -fno-plt and we are compiling for non-PIC.  We need
+   to handle the non-PIC case in the backend because there is no easy
+   interface for the front-end to force non-PLT calls to use the GOT.
+   This is currently used only with 64-bit or 32-bit GOT32X ELF targets
+   to call the function marked "noplt" indirectly.  */
 
 static bool
 ix86_nopic_noplt_attribute_p (rtx call_op)
 {
   if (flag_pic || ix86_cmodel == CM_LARGE
-      || !TARGET_64BIT || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
+      || !(TARGET_64BIT || HAVE_AS_IX86_GOT32X)
+      || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
       || SYMBOL_REF_LOCAL_P (call_op))
     return false;
 
@@ -28055,7 +28066,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
       if (direct_p)
        {
          if (ix86_nopic_noplt_attribute_p (call_op))
-           xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+           {
+             if (TARGET_64BIT)
+               xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+             else
+               xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
+           }
          else
            xasm = "%!jmp\t%P0";
        }
@@ -28103,7 +28119,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
   if (direct_p)
     {
       if (ix86_nopic_noplt_attribute_p (call_op))
-       xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+       {
+         if (TARGET_64BIT)
+           xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
+         else
+           xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
+       }
       else
        xasm = "%!call\t%P0";
     }
index bfd2b8c64f5614b75556f9c6164b4113c3b3b5ec..800ab269e24c00595b3f5414e00abae5e7aecd49 100755 (executable)
@@ -25899,13 +25899,13 @@ _ACEOF
 
     # Enforce 32-bit output with gas and gld.
     if test x$gas = xyes; then
-      as_ix86_tls_ldm_opt="--32"
+      as_ix86_gas_opt="--32"
     fi
     if echo "$ld_ver" | grep GNU > /dev/null; then
       if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; then
-        ld_ix86_tls_ldm_opt="-melf_i386_sol2"
+        ld_ix86_gld_opt="-melf_i386_sol2"
       else
-        ld_ix86_tls_ldm_opt="-melf_i386"
+        ld_ix86_gld_opt="-melf_i386"
       fi
     fi
     conftest_s='
@@ -25927,7 +25927,7 @@ else
   gcc_cv_as_ix86_tlsldm=no
   if test x$gcc_cv_as != x; then
     $as_echo "$conftest_s" > conftest.s
-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_tls_ldm_opt -o conftest.o conftest.s >&5'
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_opt -o conftest.o conftest.s >&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -25935,7 +25935,7 @@ else
   test $ac_status = 0; }; }
     then
        if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
-           && $gcc_cv_ld $ld_ix86_tls_ldm_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
+           && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
           if $gcc_cv_objdump -d conftest 2>/dev/null | grep nop > /dev/null \
              || dis conftest 2>/dev/null | grep nop > /dev/null; then
             gcc_cv_as_ix86_tlsldm=yes
@@ -25958,6 +25958,58 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+    conftest_s='
+       .data
+bar:
+       .byte 1
+       .text
+       .global _start
+_start:
+        cmpl $0, bar@GOT
+        jmp *_start@GOT'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_GOT32X reloc" >&5
+$as_echo_n "checking assembler for R_386_GOT32X reloc... " >&6; }
+if test "${gcc_cv_as_ix86_got32x+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_ix86_got32x=no
+  if test x$gcc_cv_as != x; then
+    $as_echo "$conftest_s" > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_opt -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+           && test x$gcc_cv_readelf != x \
+           && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+              | grep R_386_GOT32X > /dev/null 2>&1 \
+           && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o > /dev/null 2>&1; then
+          if $gcc_cv_objdump -dw conftest 2>&1 \
+             | grep 0xffffff > /dev/null 2>&1; then
+            gcc_cv_as_ix86_got32x=no
+          else
+            gcc_cv_as_ix86_got32x=yes
+          fi
+        fi
+        rm -f conftest
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ix86_got32x" >&5
+$as_echo "$gcc_cv_as_ix86_got32x" >&6; }
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_GOT32X `if test x"$gcc_cv_as_ix86_got32x" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
     ;;
 
   ia64*-*-*)
index fabd48e5a2588efdd291a644e583a3952b410bad..db3c6036916df3185101e6d5b6e90652df8824f4 100644 (file)
@@ -4164,13 +4164,13 @@ tls_ld:
 
     # Enforce 32-bit output with gas and gld.
     if test x$gas = xyes; then
-      as_ix86_tls_ldm_opt="--32"
+      as_ix86_gas_opt="--32"
     fi
     if echo "$ld_ver" | grep GNU > /dev/null; then
       if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; then
-        ld_ix86_tls_ldm_opt="-melf_i386_sol2"
+        ld_ix86_gld_opt="-melf_i386_sol2"
       else
-        ld_ix86_tls_ldm_opt="-melf_i386"
+        ld_ix86_gld_opt="-melf_i386"
       fi
     fi
     conftest_s='
@@ -4186,10 +4186,10 @@ _start:
 value:'
     gcc_GAS_CHECK_FEATURE([R_386_TLS_LDM reloc],
         gcc_cv_as_ix86_tlsldm,,
-       [$as_ix86_tls_ldm_opt],
+       [$as_ix86_gas_opt],
        [$conftest_s],
        [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
-           && $gcc_cv_ld $ld_ix86_tls_ldm_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
+           && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
           if $gcc_cv_objdump -d conftest 2>/dev/null | grep nop > /dev/null \
              || dis conftest 2>/dev/null | grep nop > /dev/null; then
             gcc_cv_as_ix86_tlsldm=yes
@@ -4200,6 +4200,35 @@ value:'
       [`if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; fi`],
       [Define to 1 if your assembler and linker support @tlsldm.])
 
+    conftest_s='
+       .data
+bar:
+       .byte 1
+       .text
+       .global _start
+_start:
+        cmpl $0, bar@GOT
+        jmp *_start@GOT'
+    gcc_GAS_CHECK_FEATURE([R_386_GOT32X reloc],
+        gcc_cv_as_ix86_got32x,,
+       [$as_ix86_gas_opt],
+       [$conftest_s],
+       [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+           && test x$gcc_cv_readelf != x \
+           && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+              | grep R_386_GOT32X > /dev/null 2>&1 \
+           && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o > /dev/null 2>&1; then
+          if $gcc_cv_objdump -dw conftest 2>&1 \
+             | grep 0xffffff > /dev/null 2>&1; then
+            gcc_cv_as_ix86_got32x=no
+          else
+            gcc_cv_as_ix86_got32x=yes
+          fi
+        fi
+        rm -f conftest])
+    AC_DEFINE_UNQUOTED(HAVE_AS_IX86_GOT32X,
+      [`if test x"$gcc_cv_as_ix86_got32x" = xyes; then echo 1; else echo 0; fi`],
+      [Define 0/1 if your assembler and linker support @GOT.])
     ;;
 
   ia64*-*-*)
index e3c95486b48fcb084730078459cb1baf58bd1365..95d90b6249e00e10c7dbe06088e3539cb782536c 100644 (file)
@@ -1,3 +1,21 @@
+2016-06-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/66232
+       PR target/67400
+       * gcc.target/i386/pr66232-14.c: New file.
+       * gcc.target/i386/pr66232-15.c: Likewise.
+       * gcc.target/i386/pr66232-16.c: Likewise.
+       * gcc.target/i386/pr66232-17.c: Likewise.
+       * gcc.target/i386/pr67400-1.c: Don't disable for ia32.  Scan for
+       ia32 if R_386_GOT32X relocation is supported.
+       * gcc.target/i386/pr67400-2.c: Likewise.
+       * gcc.target/i386/pr67400-3.c: Likewise.
+       * gcc.target/i386/pr67400-4.c: Likewise.
+       * gcc.target/i386/pr67400-6.c: Likewise.
+       * gcc.target/i386/pr67400-7.c: Likewise.
+       * lib/target-supports.exp (check_effective_target_got32x_reloc):
+       New.
+
 2016-06-23  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libgfortran/48852
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-14.c b/gcc/testsuite/gcc.target/i386/pr66232-14.c
new file mode 100644 (file)
index 0000000..804e5a5
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-15.c b/gcc/testsuite/gcc.target/i386/pr66232-15.c
new file mode 100644 (file)
index 0000000..3d2f6da
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-16.c b/gcc/testsuite/gcc.target/i386/pr66232-16.c
new file mode 100644 (file)
index 0000000..d67f1a5
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-17.c b/gcc/testsuite/gcc.target/i386/pr66232-17.c
new file mode 100644 (file)
index 0000000..bf6f375
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */
index 18b3790c03310ec37791727636e38c90f58cad12..8af66503dbf5c3c733558322596e1cd29ab5431c 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fno-pic -fno-plt" } */
 
 extern void bar (void);
@@ -9,5 +9,7 @@ foo (void)
   return &bar;
 }
 
-/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
-/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "\(mov|lea\)l\[ \t\]*\(\\\$|\)bar," { target { ia32 && got32x_reloc } } } } */
index 8f61c3f91ea03436992d007cfe5832776cc70f80..23dd4bf45939240a94e0a519a83f4e4beb2c1e45 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fno-pic -fno-plt" } */
 
 extern void bar (void);
@@ -10,5 +10,7 @@ foo (void)
   p = &bar;
 }
 
-/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
-/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
index 40d3521066807b3690bc27521c4a97a52c81ead9..649c9809708c923fd9903547f4ba81c0ba2e4896 100644 (file)
@@ -13,4 +13,5 @@ foo (void)
 }
 
 /* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */
-/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
index a329bbf4bf1e8277775a40f44371f65d04964fc5..5f6883dbb54e3cdfcfc9d0e0a47fe0d2911e8535 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fno-pic -fno-plt" } */
 
 extern void bar (void) __attribute__ ((visibility ("hidden")));
@@ -10,4 +10,5 @@ foo (void)
 }
 
 /* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */
-/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
index bb766cd243f15f646cf1f54d8653801a1e1753fe..652add4d31aeb564e2eb010a3125b265e4c3698b 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fno-pic -fno-plt" } */
 
 extern int bar (void);
@@ -9,5 +9,7 @@ check (void *p)
   return p != &bar;
 }
 
-/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" } } */
-/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */
+/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
index 32ae85f232823aa60f59b61db17a05517e0e821f..900e87a17f4e44eb56c7de317dfd34afeb7c6640 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fno-pic -fno-plt" } */
 
 extern void bar (void);
@@ -9,5 +9,5 @@ foo (void)
   return &bar+1;
 }
 
-/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */
-/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," { target { ! ia32 } } } } */
index 62267cf21aaae1870949f56e3403c6047705d9e8..6dd59e8c7d6bed3504bce0fb1e351541c28855ce 100644 (file)
@@ -7012,6 +7012,57 @@ proc check_effective_target_pie_copyreloc { } {
     return $pie_copyreloc_available_saved
 }
 
+# Return 1 if the x86 target supports R_386_GOT32X relocation, 0
+# otherwise.  Cache the result.
+
+proc check_effective_target_got32x_reloc { } {
+    global got32x_reloc_available_saved
+    global tool
+    global GCC_UNDER_TEST
+
+    if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+       return 0
+    }
+
+    # Need auto-host.h to check linker support.
+    if { ![file exists ../../auto-host.h ] } {
+       return 0
+    }
+
+    if [info exists got32x_reloc_available_saved] {
+       verbose "check_effective_target_got32x_reloc returning saved $got32x_reloc_available_saved" 2
+    } else {
+       # Include the current process ID in the file names to prevent
+       # conflicts with invocations for multiple testsuites.
+
+       set src got32x[pid].c
+       set obj got32x[pid].o
+
+       set f [open $src "w"]
+       puts $f "#include \"../../auto-host.h\""
+       puts $f "#if HAVE_AS_IX86_GOT32X == 0"
+       puts $f "# error Assembler does not support R_386_GOT32X."
+       puts $f "#endif"
+       close $f
+
+       verbose "check_effective_target_got32x_reloc compiling testfile $src" 2
+       set lines [${tool}_target_compile $src $obj object ""]
+
+       file delete $src
+       file delete $obj
+
+       if [string match "" $lines] then {
+           verbose "check_effective_target_got32x_reloc testfile compilation passed" 2
+           set got32x_reloc_available_saved 1
+       } else {
+           verbose "check_effective_target_got32x_reloc testfile compilation failed" 2
+           set got32x_reloc_available_saved 0
+       }
+    }
+
+    return $got32x_reloc_available_saved
+}
+
 # Return 1 if the target uses comdat groups.
 
 proc check_effective_target_comdat_group {} {