[PATCH] D92114: [X86] Don't emit R_X86_64_[REX_]GOTPCRELX for a GOT load with an offset
Fangrui Song via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 25 10:13:49 PST 2020
MaskRay created this revision.
MaskRay added reviewers: craig.topper, grimar, jhenderson, sberg.
Herald added subscribers: llvm-commits, pengfei, hiraditya, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.
MaskRay requested review of this revision.
Alternative to D91993 <https://reviews.llvm.org/D91993>.
clang may produce `movl x at GOTPCREL+4(%rip), %eax` when loading the high
32 bits of the address of a global variable in -fpic/-fpie mode.
If assembled by GNU as or newer integrated assembler (after commit
f04d92af94a8d763e91ae38fe35319e426dc466c <https://reviews.llvm.org/rGf04d92af94a8d763e91ae38fe35319e426dc466c>), the fixup emits R_X86_64_GOTPCRELX
with an addend != -4. The instruction loads from the GOT entry with an offset
and thus it is incorrect to relax the instruction.
This patch does not emit a relaxable relocation for a GOT load with an offset.
The result is good enough for LLD to work. GNU ld relaxes mov+GOTPCREL
as well, but it suppresses the relaxation if addend != -4.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D92114
Files:
llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
llvm/test/MC/ELF/got-relaxed-rex.s
llvm/test/MC/X86/gotpcrelx.s
Index: llvm/test/MC/X86/gotpcrelx.s
===================================================================
--- llvm/test/MC/X86/gotpcrelx.s
+++ llvm/test/MC/X86/gotpcrelx.s
@@ -1,5 +1,7 @@
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s | llvm-readobj -r - | FileCheck %s
-# RUN: llvm-mc -filetype=obj -triple=x86_64 -relax-relocations=false %s | llvm-readobj -r - | FileCheck --check-prefix=NORELAX %s
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefixes=CHECK,COMMON
+# RUN: llvm-mc -filetype=obj -triple=x86_64 -relax-relocations=false %s -o %t1.o
+# RUN: llvm-readobj -r %t1.o | FileCheck %s --check-prefixes=NORELAX,COMMON
# CHECK: Relocations [
# CHECK-NEXT: Section ({{.*}}) .rela.text {
@@ -16,7 +18,6 @@
# CHECK-NEXT: R_X86_64_GOTPCRELX call
# CHECK-NEXT: R_X86_64_GOTPCRELX jmp
# CHECK-NEXT: }
-# CHECK-NEXT: ]
# NORELAX: Relocations [
# NORELAX-NEXT: Section ({{.*}}) .rela.text {
@@ -33,7 +34,6 @@
# NORELAX-NEXT: R_X86_64_GOTPCREL call
# NORELAX-NEXT: R_X86_64_GOTPCREL jmp
# NORELAX-NEXT: }
-# NORELAX-NEXT: ]
movl mov at GOTPCREL(%rip), %eax
test %eax, test at GOTPCREL(%rip)
@@ -47,3 +47,15 @@
xor xor at GOTPCREL(%rip), %eax
call *call at GOTPCREL(%rip)
jmp *jmp at GOTPCREL(%rip)
+
+# COMMON-NEXT: Section ({{.*}}) .rela.norelax {
+# COMMON-NEXT: R_X86_64_GOTPCREL mov 0x0
+# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFC
+# COMMON-NEXT: }
+
+.section .norelax,"ax", at progbits
+## Clang may emit this expression to load the high 32-bit of the GOT entry.
+## Don't emit R_X86_64_GOTPCRELX.
+movl mov at GOTPCREL+4(%rip), %eax
+## We could emit R_X86_64_GOTPCRELX, but it is probably unnecessary.
+movl mov at GOTPCREL+0(%rip), %eax
Index: llvm/test/MC/ELF/got-relaxed-rex.s
===================================================================
--- llvm/test/MC/ELF/got-relaxed-rex.s
+++ llvm/test/MC/ELF/got-relaxed-rex.s
@@ -13,6 +13,11 @@
sub sub at GOTPCREL(%rip), %rax
xor xor at GOTPCREL(%rip), %rax
+.section .norelax,"ax"
+## This expression loads the GOT entry with an offset.
+## Don't emit R_X86_64_REX_GOTPCRELX.
+ movq mov at GOTPCREL+1(%rip), %rax
+
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.text {
// CHECK-NEXT: R_X86_64_REX_GOTPCRELX mov
@@ -26,4 +31,6 @@
// CHECK-NEXT: R_X86_64_REX_GOTPCRELX sub
// CHECK-NEXT: R_X86_64_REX_GOTPCRELX xor
// CHECK-NEXT: }
-// CHECK-NEXT: ]
+// CHECK-NEXT: Section ({{.*}}) .rela.norelax {
+// CHECK-NEXT: R_X86_64_GOTPCREL mov
+// CHECK-NEXT: }
Index: llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
===================================================================
--- llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -397,10 +397,11 @@
emitByte(modRMByte(0, RegOpcodeField, 5), OS);
unsigned Opcode = MI.getOpcode();
- // movq loads are handled with a special relocation form which allows the
- // linker to eliminate some loads for GOT references which end up in the
- // same linkage unit.
- unsigned FixupKind = [=]() {
+ unsigned FixupKind = [&]() {
+ // Enable relaxed relocation only for a MCSymbolRefExpr. We cannot
+ // enabled relaxed relocation if an offset is present (e.g. x at GOTPCREL+4).
+ if (!(Disp.isExpr() && isa<MCSymbolRefExpr>(Disp.getExpr())))
+ return X86::reloc_riprel_4byte;
switch (Opcode) {
default:
return X86::reloc_riprel_4byte;
@@ -416,6 +417,9 @@
case X86::XOR32rm:
return X86::reloc_riprel_4byte_relax;
case X86::MOV64rm:
+ // movq loads is a subset of reloc_riprel_4byte_relax_rex. It is a
+ // special case because Mach-O and Windows don't support ELF's more
+ // flexible relaxation.
assert(HasREX);
return X86::reloc_riprel_4byte_movq_load;
case X86::CALL64m:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D92114.307651.patch
Type: text/x-patch
Size: 3966 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201125/5fe2b65a/attachment.bin>
More information about the llvm-commits
mailing list