[clang] 3d34053 - [X86, MC] Add relocation R_X86_64_REX2_GOTPCRELX (#106681)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 24 03:39:53 PDT 2024
Author: Shengchen Kan
Date: 2024-09-24T18:39:48+08:00
New Revision: 3d34053af61ff45e05d230d2678eb8e95322eb14
URL: https://github.com/llvm/llvm-project/commit/3d34053af61ff45e05d230d2678eb8e95322eb14
DIFF: https://github.com/llvm/llvm-project/commit/3d34053af61ff45e05d230d2678eb8e95322eb14.diff
LOG: [X86,MC] Add relocation R_X86_64_REX2_GOTPCRELX (#106681)
For
mov name at GOTPCREL(%rip), %reg
test %reg, name at GOTPCREL(%rip)
binop name at GOTPCREL(%rip), %reg
where binop is one of adc, add, and, cmp, or, sbb, sub, xor
instructions, add
`R_X86_64_REX2_GOTPCRELX`/`R_X86_64_CODE_4_GOTPCRELX` = 43
if the instruction starts at 4 bytes before the relocation offset. It
similar to R_X86_64_GOTPCRELX.
Linker can treat `R_X86_64_REX2_GOTPCRELX`/`R_X86_64_CODE_4_GOTPCRELX`
as `R_X86_64_GOTPCREL` or convert the above instructions to
lea name(%rip), %reg
mov $name, %reg
test $name, %reg
binop $name, %reg
if the first byte of the instruction at the relocation `offset - 4` is
`0xd5` (namely, encoded w/ REX2 prefix) when possible.
Binutils patch:
https://github.com/bminor/binutils-gdb/commit/3d5a60de52556f6a53d71d7e607c6696450ae3e4
Binutils mailthread:
https://sourceware.org/pipermail/binutils/2023-December/131462.html
ABI discussion: https://groups.google.com/g/x86-64-abi/c/KbzaNHRB6QU
Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation
Added:
Modified:
clang/test/Driver/relax.s
llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
llvm/test/MC/ELF/relocation-alias.s
llvm/test/MC/X86/gotpcrelx.s
llvm/test/MC/X86/reloc-directive-elf-64.s
Removed:
################################################################################
diff --git a/clang/test/Driver/relax.s b/clang/test/Driver/relax.s
index 154d4db0a31385..b4a696a328eb56 100644
--- a/clang/test/Driver/relax.s
+++ b/clang/test/Driver/relax.s
@@ -8,5 +8,7 @@
// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s
// REL: R_X86_64_REX_GOTPCRELX foo
+// REL: R_X86_64_REX2_GOTPCRELX foo
movq foo at GOTPCREL(%rip), %rax
+ movq foo at GOTPCREL(%rip), %r16
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
index 18fdcf9472dc48..161b1969abfeb4 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
@@ -43,3 +43,4 @@ ELF_RELOC(R_X86_64_TLSDESC, 36)
ELF_RELOC(R_X86_64_IRELATIVE, 37)
ELF_RELOC(R_X86_64_GOTPCRELX, 41)
ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
+ELF_RELOC(R_X86_64_REX2_GOTPCRELX, 43)
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 1a4f7e93eeb74a..92618bdabbe519 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -145,8 +145,8 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
static cl::opt<bool> X86RelaxRelocations(
"x86-relax-relocations",
- cl::desc(
- "Emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL on x86-64 ELF"),
+ cl::desc("Emit GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX instead of "
+ "GOTPCREL on x86-64 ELF"),
cl::init(true));
MCBINDOPT(X86RelaxRelocations);
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 1d08853faf582e..2f6b55b0d6023e 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -629,15 +629,19 @@ std::optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const {
const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
+ // clang-format off
{"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ {"reloc_riprel_4byte_movq_load_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ {"reloc_riprel_4byte_relax_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_signed_4byte", 0, 32, 0},
{"reloc_signed_4byte_relax", 0, 32, 0},
{"reloc_global_offset_table", 0, 32, 0},
{"reloc_global_offset_table8", 0, 64, 0},
{"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ // clang-format on
};
// Fixup kinds from .reloc directive are like R_386_NONE/R_X86_64_NONE. They
@@ -678,7 +682,9 @@ static unsigned getFixupKindSize(unsigned Kind) {
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
case X86::reloc_global_offset_table:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index 0b2efdfc16cc5d..90222278d1ad6f 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -74,7 +74,9 @@ static X86_64RelType getType64(MCFixupKind Kind,
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
return RT64_32;
case X86::reloc_branch_4byte_pcrel:
Modifier = MCSymbolRefExpr::VK_PLT;
@@ -205,7 +207,7 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
case MCSymbolRefExpr::VK_GOTPCREL:
checkIs32(Ctx, Loc, Type);
// Older versions of ld.bfd/ld.gold/lld
- // do not support GOTPCRELX/REX_GOTPCRELX,
+ // do not support GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX,
// and we want to keep back-compatibility.
if (!Ctx.getTargetOptions()->X86RelaxRelocations)
return ELF::R_X86_64_GOTPCREL;
@@ -217,6 +219,9 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
case X86::reloc_riprel_4byte_relax_rex:
case X86::reloc_riprel_4byte_movq_load:
return ELF::R_X86_64_REX_GOTPCRELX;
+ case X86::reloc_riprel_4byte_relax_rex2:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
+ return ELF::R_X86_64_REX2_GOTPCRELX;
}
llvm_unreachable("unexpected relocation type!");
case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
index 2d5217115d07cb..29bb7eebae3f22 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
@@ -16,10 +16,14 @@ namespace X86 {
enum Fixups {
reloc_riprel_4byte = FirstTargetFixupKind, // 32-bit rip-relative
reloc_riprel_4byte_movq_load, // 32-bit rip-relative in movq
+ reloc_riprel_4byte_movq_load_rex2, // 32-bit rip-relative in movq
+ // with rex2 prefix
reloc_riprel_4byte_relax, // 32-bit rip-relative in relaxable
// instruction
reloc_riprel_4byte_relax_rex, // 32-bit rip-relative in relaxable
// instruction with rex prefix
+ reloc_riprel_4byte_relax_rex2, // 32-bit rip-relative in relaxable
+ // instruction with rex2 prefix
reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4
// this will be sign extended at
// runtime.
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 71d42863fd5857..206436191c2584 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -568,8 +568,10 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc,
if (FixupKind == FK_PCRel_4 ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load_rex2) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex2) ||
FixupKind == MCFixupKind(X86::reloc_branch_4byte_pcrel)) {
ImmOffset -= 4;
// If this is a pc-relative load off _GLOBAL_OFFSET_TABLE_:
@@ -637,12 +639,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
default:
return X86::reloc_riprel_4byte;
case X86::MOV64rm:
- // movq loads is a subset of reloc_riprel_4byte_relax_rex. It is a
+ // movq loads is a subset of reloc_riprel_4byte_relax_rex/rex2. It is a
// special case because COFF and Mach-O don't support ELF's more
- // flexible R_X86_64_REX_GOTPCRELX relaxation.
- // TODO: Support new relocation for REX2.
- assert(Kind == REX || Kind == REX2);
- return X86::reloc_riprel_4byte_movq_load;
+ // flexible R_X86_64_REX_GOTPCRELX/R_X86_64_REX2_GOTPCRELX relaxation.
+ return Kind == REX2 ? X86::reloc_riprel_4byte_movq_load_rex2
+ : X86::reloc_riprel_4byte_movq_load;
case X86::ADC32rm:
case X86::ADD32rm:
case X86::AND32rm:
@@ -665,11 +666,9 @@ void X86MCCodeEmitter::emitMemModRMByte(
case X86::SBB64rm:
case X86::SUB64rm:
case X86::XOR64rm:
- // We haven't support relocation for REX2 prefix, so temporarily use REX
- // relocation.
- // TODO: Support new relocation for REX2.
- return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
- : X86::reloc_riprel_4byte_relax;
+ return Kind == REX2 ? X86::reloc_riprel_4byte_relax_rex2
+ : Kind == REX ? X86::reloc_riprel_4byte_relax_rex
+ : X86::reloc_riprel_4byte_relax;
}
}();
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
index ec95b1ffec387d..41ce5c9fcb82ad 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
@@ -66,8 +66,10 @@ class X86MachObjectWriter : public MCMachObjectTargetWriter {
static bool isFixupKindRIPRel(unsigned Kind) {
return Kind == X86::reloc_riprel_4byte ||
Kind == X86::reloc_riprel_4byte_movq_load ||
+ Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
Kind == X86::reloc_riprel_4byte_relax ||
- Kind == X86::reloc_riprel_4byte_relax_rex;
+ Kind == X86::reloc_riprel_4byte_relax_rex ||
+ Kind == X86::reloc_riprel_4byte_relax_rex2;
}
static unsigned getFixupKindLog2Size(unsigned Kind) {
@@ -83,7 +85,9 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
case X86::reloc_branch_4byte_pcrel:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
index 10fc176b59d8ab..7740500fb41830 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
@@ -66,8 +66,10 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
case FK_PCRel_4:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_branch_4byte_pcrel:
return COFF::IMAGE_REL_AMD64_REL32;
case FK_Data_4:
diff --git a/llvm/test/MC/ELF/relocation-alias.s b/llvm/test/MC/ELF/relocation-alias.s
index 51fb0c37052fe7..66bf2ceea508ba 100644
--- a/llvm/test/MC/ELF/relocation-alias.s
+++ b/llvm/test/MC/ELF/relocation-alias.s
@@ -16,7 +16,10 @@ movabsq $memcpy+2, %rax
# CHECK: movq (%rip), %rax
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX abs-0x4
+# CHECK: movq (%rip), %r16
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX abs-0x4
movq abs at GOTPCREL(%rip), %rax
+movq abs at GOTPCREL(%rip), %r16
abs = 42
# CHECK: movabsq $0, %rbx
diff --git a/llvm/test/MC/X86/gotpcrelx.s b/llvm/test/MC/X86/gotpcrelx.s
index e63e3e9a946fd1..5a8ba454bc904c 100644
--- a/llvm/test/MC/X86/gotpcrelx.s
+++ b/llvm/test/MC/X86/gotpcrelx.s
@@ -37,6 +37,16 @@
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX sbb
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX sub
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX xor
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX mov
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX test
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX adc
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX add
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX and
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX cmp
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX or
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX sbb
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX sub
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX xor
# CHECK-NEXT: }
# NORELAX-NEXT: R_X86_64_GOTPCREL mov
@@ -71,6 +81,16 @@
# NORELAX-NEXT: R_X86_64_GOTPCREL sbb
# NORELAX-NEXT: R_X86_64_GOTPCREL sub
# NORELAX-NEXT: R_X86_64_GOTPCREL xor
+# NORELAX-NEXT: R_X86_64_GOTPCREL mov
+# NORELAX-NEXT: R_X86_64_GOTPCREL test
+# NORELAX-NEXT: R_X86_64_GOTPCREL adc
+# NORELAX-NEXT: R_X86_64_GOTPCREL add
+# NORELAX-NEXT: R_X86_64_GOTPCREL and
+# NORELAX-NEXT: R_X86_64_GOTPCREL cmp
+# NORELAX-NEXT: R_X86_64_GOTPCREL or
+# NORELAX-NEXT: R_X86_64_GOTPCREL sbb
+# NORELAX-NEXT: R_X86_64_GOTPCREL sub
+# NORELAX-NEXT: R_X86_64_GOTPCREL xor
# NORELAX-NEXT: }
movl mov at GOTPCREL(%rip), %eax
@@ -108,10 +128,22 @@ sbb sbb at GOTPCREL(%rip), %rax
sub sub at GOTPCREL(%rip), %rax
xor xor at GOTPCREL(%rip), %rax
+movq mov at GOTPCREL(%rip), %r16
+test %r16, test at GOTPCREL(%rip)
+adc adc at GOTPCREL(%rip), %r16
+add add at GOTPCREL(%rip), %r16
+and and at GOTPCREL(%rip), %r16
+cmp cmp at GOTPCREL(%rip), %r16
+or or at GOTPCREL(%rip), %r16
+sbb sbb at GOTPCREL(%rip), %r16
+sub sub at GOTPCREL(%rip), %r16
+xor xor at GOTPCREL(%rip), %r16
+
# COMMON-NEXT: Section ({{.*}}) .rela.norelax {
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0x0
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFD
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFC
+# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFD
# COMMON-NEXT: }
# COMMON-NEXT: ]
@@ -123,3 +155,5 @@ movl mov at GOTPCREL+4(%rip), %eax
movq mov at GOTPCREL+1(%rip), %rax
## We could emit R_X86_64_GOTPCRELX, but it is probably unnecessary.
movl mov at GOTPCREL+0(%rip), %eax
+## Don't emit R_X86_64_GOTPCRELX.
+movq mov at GOTPCREL+1(%rip), %r16
diff --git a/llvm/test/MC/X86/reloc-directive-elf-64.s b/llvm/test/MC/X86/reloc-directive-elf-64.s
index 8f5d8c895e7d76..323603efc70618 100644
--- a/llvm/test/MC/X86/reloc-directive-elf-64.s
+++ b/llvm/test/MC/X86/reloc-directive-elf-64.s
@@ -9,6 +9,7 @@
# PRINT-NEXT: .reloc 0, R_X86_64_64, .data+2
# PRINT-NEXT: .reloc 0, R_X86_64_GOTPCRELX, foo+3
# PRINT-NEXT: .reloc 0, R_X86_64_REX_GOTPCRELX, 5
+# PRINT-NEXT: .reloc 0, R_X86_64_REX2_GOTPCRELX, 7
# PRINT: .reloc 0, BFD_RELOC_NONE, 9
# PRINT-NEXT: .reloc 0, BFD_RELOC_8, 9
# PRINT-NEXT: .reloc 0, BFD_RELOC_16, 9
@@ -21,6 +22,7 @@
# CHECK-NEXT: 0x0 R_X86_64_64 .data 0x2
# CHECK-NEXT: 0x0 R_X86_64_GOTPCRELX foo 0x3
# CHECK-NEXT: 0x0 R_X86_64_REX_GOTPCRELX - 0x5
+# CHECK-NEXT: 0x0 R_X86_64_REX2_GOTPCRELX - 0x7
# CHECK-NEXT: 0x0 R_X86_64_NONE - 0x9
# CHECK-NEXT: 0x0 R_X86_64_8 - 0x9
# CHECK-NEXT: 0x0 R_X86_64_16 - 0x9
@@ -37,6 +39,7 @@
.reloc 0, R_X86_64_64, .data+2
.reloc 0, R_X86_64_GOTPCRELX, foo+3
.reloc 0, R_X86_64_REX_GOTPCRELX, 5
+ .reloc 0, R_X86_64_REX2_GOTPCRELX, 7
.reloc 0, BFD_RELOC_NONE, 9
.reloc 0, BFD_RELOC_8, 9
More information about the cfe-commits
mailing list