summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2016-06-23 16:30:43 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2016-06-23 16:30:43 +0000
commit6fb2f18178a7a2d8d7a166e8d418cddc7f0d5430 (patch)
treeb69135bb367453ba3dfca8641a5f27c9cdc26160 /gcc/config/i386
parent88be2b3c486cb31e026fe212db72e7765d278597 (diff)
downloadgcc-6fb2f18178a7a2d8d7a166e8d418cddc7f0d5430.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@237736 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/i386.c51
1 files changed, 36 insertions, 15 deletions
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";
}