From c05977599ac4c3dd31db05744ea89dc2428718c4 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 23 Jun 2016 16:30:43 +0000 Subject: [PATCH] i386: Access external function via GOT slot for -fno-plt 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. From-SVN: r237736 --- gcc/ChangeLog | 28 ++++++++++ gcc/config.in | 9 +++- gcc/config/i386/i386.c | 51 ++++++++++++------ gcc/configure | 62 ++++++++++++++++++++-- gcc/configure.ac | 39 ++++++++++++-- gcc/testsuite/ChangeLog | 18 +++++++ gcc/testsuite/gcc.target/i386/pr66232-14.c | 13 +++++ gcc/testsuite/gcc.target/i386/pr66232-15.c | 14 +++++ gcc/testsuite/gcc.target/i386/pr66232-16.c | 13 +++++ gcc/testsuite/gcc.target/i386/pr66232-17.c | 13 +++++ gcc/testsuite/gcc.target/i386/pr67400-1.c | 8 +-- gcc/testsuite/gcc.target/i386/pr67400-2.c | 8 +-- gcc/testsuite/gcc.target/i386/pr67400-3.c | 3 +- gcc/testsuite/gcc.target/i386/pr67400-4.c | 5 +- gcc/testsuite/gcc.target/i386/pr67400-6.c | 8 +-- gcc/testsuite/gcc.target/i386/pr67400-7.c | 6 +-- gcc/testsuite/lib/target-supports.exp | 51 ++++++++++++++++++ 17 files changed, 308 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-14.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-15.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-16.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-17.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ffa702a73f6..c36062eb617 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2016-06-23 H.J. Lu + + 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 * tree-inline.c (remap_decl): Preserve DECL_ORIGINAL_TYPE invariant. 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..800ab269e24 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_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*-*-*) diff --git a/gcc/configure.ac b/gcc/configure.ac index fabd48e5a25..db3c6036916 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_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*-*-*) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e3c95486b48..95d90b6249e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2016-06-23 H.J. Lu + + 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 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 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 62267cf21aa..6dd59e8c7d6 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -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 {} { -- 2.30.2