summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-08-28 19:14:49 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-06-23 09:48:52 -0700
commit7b0dbad23261aba50507025c59eacccb445d2ed7 (patch)
treed9d6edb3ed2c89e2cd6299b0e04c4b6d971131ef
parentafa7ed877d72f2514673901cbd2c7779f8d4f880 (diff)
downloadgcc-hjl/no-plt/got32x.tar.gz
i386: Access external function via GOT slot for -fno-plthjl/no-plt/got32x
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.
-rw-r--r--gcc/config.in9
-rw-r--r--gcc/config/i386/i386.c51
-rwxr-xr-xgcc/configure62
-rw-r--r--gcc/configure.ac39
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-14.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-15.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-16.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-17.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-4.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-6.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67400-7.c6
-rw-r--r--gcc/testsuite/lib/target-supports.exp51
15 files changed, 262 insertions, 41 deletions
diff --git a/gcc/config.in b/gcc/config.in
index 2deb8edf681..5f801761d2c 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -425,6 +425,12 @@
#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
@@ -628,7 +634,8 @@
#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
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9c7b015e9c8..f7944f994eb 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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";
}
diff --git a/gcc/configure b/gcc/configure
index bfd2b8c64f5..94ba9bd0fd1 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -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_32_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_32_opt="-melf_i386_sol2"
else
- ld_ix86_tls_ldm_opt="-melf_i386"
+ ld_ix86_gld_32_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_32_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_32_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_32_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_32_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*-*-*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index fabd48e5a25..b0f38d1e430 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -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_32_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_32_opt="-melf_i386_sol2"
else
- ld_ix86_tls_ldm_opt="-melf_i386"
+ ld_ix86_gld_32_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_32_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_32_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_32_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_32_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*-*-*)
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-14.c b/gcc/testsuite/gcc.target/i386/pr66232-14.c
new file mode 100644
index 00000000000..804e5a5c304
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-14.c
@@ -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
index 00000000000..3d2f6da46b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-15.c
@@ -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
index 00000000000..d67f1a594dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-16.c
@@ -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
index 00000000000..bf6f37515a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-17.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-1.c b/gcc/testsuite/gcc.target/i386/pr67400-1.c
index 18b3790c033..8af66503dbf 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-1.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-2.c b/gcc/testsuite/gcc.target/i386/pr67400-2.c
index 8f61c3f91ea..23dd4bf4593 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-2.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-3.c b/gcc/testsuite/gcc.target/i386/pr67400-3.c
index 40d35210668..649c9809708 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-3.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-4.c b/gcc/testsuite/gcc.target/i386/pr67400-4.c
index a329bbf4bf1..5f6883dbb54 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-4.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-6.c b/gcc/testsuite/gcc.target/i386/pr67400-6.c
index bb766cd243f..652add4d31a 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-6.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-6.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67400-7.c b/gcc/testsuite/gcc.target/i386/pr67400-7.c
index 32ae85f2328..900e87a17f4 100644
--- a/gcc/testsuite/gcc.target/i386/pr67400-7.c
+++ b/gcc/testsuite/gcc.target/i386/pr67400-7.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 1b1d03aecdf..51042b5b63d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6975,6 +6975,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 {} {