[lld] r340281 - [PPC64] Add TLS initial exec to local exec relaxation
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 21 08:13:53 PDT 2018
Author: syzaara
Date: Tue Aug 21 08:13:53 2018
New Revision: 340281
URL: http://llvm.org/viewvc/llvm-project?rev=340281&view=rev
Log:
[PPC64] Add TLS initial exec to local exec relaxation
This patch adds the target call back relaxTlsIeToLe to support TLS relaxation
from initial exec to local exec model.
Differential Revision: https://reviews.llvm.org/D48091
Added:
lld/trunk/test/ELF/Inputs/ppc64-tls-ie-le.s
lld/trunk/test/ELF/ppc64-tls-ie-le.s
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=340281&r1=340280&r2=340281&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Tue Aug 21 08:13:53 2018
@@ -23,6 +23,32 @@ using namespace lld::elf;
static uint64_t PPC64TocOffset = 0x8000;
static uint64_t DynamicThreadPointerOffset = 0x8000;
+// The instruction encoding of bits 21-30 from the ISA for the Xform and Dform
+// instructions that can be used as part of the initial exec TLS sequence.
+enum XFormOpcd {
+ LBZX = 87,
+ LHZX = 279,
+ LWZX = 23,
+ LDX = 21,
+ STBX = 215,
+ STHX = 407,
+ STWX = 151,
+ STDX = 149,
+ ADD = 266,
+};
+
+enum DFormOpcd {
+ LBZ = 34,
+ LHZ = 40,
+ LWZ = 32,
+ LD = 58,
+ STB = 38,
+ STH = 44,
+ STW = 36,
+ STD = 62,
+ ADDI = 14
+};
+
uint64_t elf::getPPC64TocBase() {
// The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
// TOC starts where the first of these sections starts. We always create a
@@ -56,6 +82,7 @@ public:
void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+ void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
};
} // namespace
@@ -212,6 +239,80 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc,
}
}
+static unsigned getDFormOp(unsigned SecondaryOp) {
+ switch (SecondaryOp) {
+ case LBZX:
+ return LBZ;
+ case LHZX:
+ return LHZ;
+ case LWZX:
+ return LWZ;
+ case LDX:
+ return LD;
+ case STBX:
+ return STB;
+ case STHX:
+ return STH;
+ case STWX:
+ return STW;
+ case STDX:
+ return STD;
+ case ADD:
+ return ADDI;
+ default:
+ error("unrecognized instruction for IE to LE R_PPC64_TLS");
+ return 0;
+ }
+}
+
+void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ // The initial exec code sequence for a global `x` will look like:
+ // Instruction Relocation Symbol
+ // addis r9, r2, x at got@tprel at ha R_PPC64_GOT_TPREL16_HA x
+ // ld r9, x at got@tprel at l(r9) R_PPC64_GOT_TPREL16_LO_DS x
+ // add r9, r9, x at tls R_PPC64_TLS x
+
+ // Relaxing to local exec entails converting:
+ // addis r9, r2, x at got@tprel at ha into nop
+ // ld r9, x at got@tprel at l(r9) into addis r9, r13, x at tprel@ha
+ // add r9, r9, x at tls into addi r9, r9, x at tprel@l
+
+ // x at tls R_PPC64_TLS is a relocation which does not compute anything,
+ // it is replaced with r13 (thread pointer).
+
+ // The add instruction in the initial exec sequence has multiple variations
+ // that need to be handled. If we are building an address it will use an add
+ // instruction, if we are accessing memory it will use any of the X-form
+ // indexed load or store instructions.
+
+ unsigned Offset = (Config->EKind == ELF64BEKind) ? 2 : 0;
+ switch (Type) {
+ case R_PPC64_GOT_TPREL16_HA:
+ write32(Loc - Offset, 0x60000000); // nop
+ break;
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_DS: {
+ uint32_t RegNo = read32(Loc - Offset) & 0x03E00000; // bits 6-10
+ write32(Loc - Offset, 0x3C0D0000 | RegNo); // addis RegNo, r13
+ relocateOne(Loc, R_PPC64_TPREL16_HA, Val);
+ break;
+ }
+ case R_PPC64_TLS: {
+ uint32_t PrimaryOp = (read32(Loc) & 0xFC000000) >> 26; // bits 0-5
+ if (PrimaryOp != 31)
+ error("unrecognized instruction for IE to LE R_PPC64_TLS");
+ uint32_t SecondaryOp = (read32(Loc) & 0x000007FE) >> 1; // bits 21-30
+ uint32_t DFormOp = getDFormOp(SecondaryOp);
+ write32(Loc, ((DFormOp << 26) | (read32(Loc) & 0x03FFFFFF)));
+ relocateOne(Loc + Offset, R_PPC64_TPREL16_LO, Val);
+ break;
+ }
+ default:
+ llvm_unreachable("unknown relocation for IE to LE");
+ break;
+ }
+}
+
RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const {
switch (Type) {
@@ -279,7 +380,7 @@ RelExpr PPC64::getRelExpr(RelType Type,
case R_PPC64_TLSLD:
return R_TLSLD_HINT;
case R_PPC64_TLS:
- return R_HINT;
+ return R_TLSIE_HINT;
default:
return R_ABS;
}
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=340281&r1=340280&r2=340281&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Tue Aug 21 08:13:53 2018
@@ -270,12 +270,15 @@ handleTlsRelocation(RelType Type, Symbol
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
// defined.
- if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) &&
+ if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC, R_GOT_OFF,
+ R_TLSIE_HINT>(Expr) &&
!Config->Shared && !Sym.IsPreemptible) {
C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym});
return 1;
}
+ if (Expr == R_TLSIE_HINT)
+ return 1;
return 0;
}
@@ -358,7 +361,7 @@ static bool isStaticLinkTimeConstant(Rel
R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END,
R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT,
- R_TLSLD_HINT>(E))
+ R_TLSLD_HINT, R_TLSIE_HINT>(E))
return true;
// These never do, except if the entire file is position dependent or if
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=340281&r1=340280&r2=340281&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Tue Aug 21 08:13:53 2018
@@ -83,6 +83,7 @@ enum RelExpr {
R_TLSGD_GOT,
R_TLSGD_GOT_FROM_END,
R_TLSGD_PC,
+ R_TLSIE_HINT,
R_TLSLD_GOT,
R_TLSLD_GOT_FROM_END,
R_TLSLD_GOT_OFF,
Added: lld/trunk/test/ELF/Inputs/ppc64-tls-ie-le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/ppc64-tls-ie-le.s?rev=340281&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/ppc64-tls-ie-le.s (added)
+++ lld/trunk/test/ELF/Inputs/ppc64-tls-ie-le.s Tue Aug 21 08:13:53 2018
@@ -0,0 +1,29 @@
+ .text
+ .abiversion 2
+ .type c, at object # @c
+ .section .tdata,"awT", at progbits
+ .globl c
+c:
+ .byte 97 # 0x61
+ .size c, 1
+
+ .type s, at object # @s
+ .globl s
+ .p2align 1
+s:
+ .short 55 # 0x37
+ .size s, 2
+
+ .type i, at object # @i
+ .globl i
+ .p2align 2
+i:
+ .long 55 # 0x37
+ .size i, 4
+
+ .type l, at object # @l
+ .globl l
+ .p2align 3
+l:
+ .quad 55 # 0x37
+ .size l, 8
Added: lld/trunk/test/ELF/ppc64-tls-ie-le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-tls-ie-le.s?rev=340281&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-tls-ie-le.s (added)
+++ lld/trunk/test/ELF/ppc64-tls-ie-le.s Tue Aug 21 08:13:53 2018
@@ -0,0 +1,140 @@
+// REQUIRES: ppc
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-tls-ie-le.s -o %t2.o
+// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o -o %t
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-tls-ie-le.s -o %t2.o
+// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o -o %t
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+
+ .text
+ .abiversion 2
+test1: # @test1
+ addis 3, 2, c at got@tprel at ha
+ ld 3, c at got@tprel at l(3)
+ lbzx 3, 3, c at tls
+ blr
+test2: # @test2
+ addis 3, 2, s at got@tprel at ha
+ ld 3, s at got@tprel at l(3)
+ lhzx 3, 3, s at tls
+ blr
+test3: # @test3
+ addis 3, 2, i at got@tprel at ha
+ ld 3, i at got@tprel at l(3)
+ lwzx 3, 3, i at tls
+ blr
+test4: # @test4
+ addis 3, 2, l at got@tprel at ha
+ ld 3, l at got@tprel at l(3)
+ ldx 3, 3, l at tls
+ blr
+test5: # @test5
+ addis 4, 2, c at got@tprel at ha
+ ld 4, c at got@tprel at l(4)
+ stbx 3, 4, c at tls
+ blr
+test6: # @test6
+ addis 4, 2, s at got@tprel at ha
+ ld 4, s at got@tprel at l(4)
+ sthx 3, 4, s at tls
+ blr
+test7: # @test7
+ addis 4, 2, i at got@tprel at ha
+ ld 4, i at got@tprel at l(4)
+ stwx 3, 4, i at tls
+ blr
+test8: # @test8
+ addis 4, 2, l at got@tprel at ha
+ ld 4, l at got@tprel at l(4)
+ stdx 3, 4, l at tls
+ blr
+test9: # @test9
+ addis 3, 2, i at got@tprel at ha
+ ld 3, i at got@tprel at l(3)
+ add 3, 3, i at tls
+ blr
+test_ds: # @test_ds
+ ld 4, l at got@tprel(2)
+ stdx 3, 4, l at tls
+ blr
+
+
+// Verify that the input has initial-exec tls relocation types.
+// InputRelocs: Relocation section '.rela.text'
+// InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} c + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} c + 0
+// InputRelocs: R_PPC64_TLS {{0+}} c + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} s + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} s + 0
+// InputRelocs: R_PPC64_TLS {{0+}} s + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} i + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} i + 0
+// InputRelocs: R_PPC64_TLS {{0+}} i + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} l + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} l + 0
+// InputRelocs: R_PPC64_TLS {{0+}} l + 0
+// InputRelocs: R_PPC64_GOT_TPREL16_DS {{0+}} l + 0
+// InputRelocs: R_PPC64_TLS {{0+}} l + 0
+
+// Verify that no initial-exec relocations exist for the dynamic linker.
+// OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} c + 0
+// OutputRelocs-NPT: R_PPC64_TPREL64 {{0+}} s + 0
+// OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} i + 0
+// OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} l + 0
+
+// Dis: test1:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: lbz 3, -28672(3)
+
+// Dis: test2:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: lhz 3, -28670(3)
+
+// Dis: test3:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: lwz 3, -28668(3)
+
+// Dis: test4:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: ld 3, -28664(3)
+
+// Dis: test5:
+// Dis: nop
+// Dis: addis 4, 13, 0
+// Dis: stb 3, -28672(4)
+
+// Dis: test6:
+// Dis: nop
+// Dis: addis 4, 13, 0
+// Dis: sth 3, -28670(4)
+
+// Dis: test7:
+// Dis: nop
+// Dis: addis 4, 13, 0
+// Dis: stw 3, -28668(4)
+
+// Dis: test8:
+// Dis: nop
+// Dis: addis 4, 13, 0
+// Dis: std 3, -28664(4)
+
+// Dis: test9:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: addi 3, 3, -28668
+
+// Dis: test_ds:
+// Dis: addis 4, 13, 0
+// Dis: std 3, -28664(4)
More information about the llvm-commits
mailing list