[lld] r336559 - [PPC64] Add TLS local dynamic to local exec relaxation
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 9 09:35:51 PDT 2018
Author: syzaara
Date: Mon Jul 9 09:35:51 2018
New Revision: 336559
URL: http://llvm.org/viewvc/llvm-project?rev=336559&view=rev
Log:
[PPC64] Add TLS local dynamic to local exec relaxation
This patch adds the target call back relaxTlsLdToLe to support TLS relaxation
from local dynamic to local exec model.
Differential Revision: https://reviews.llvm.org/D48293
Added:
lld/trunk/test/ELF/ppc64-tls-ld-le.s
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
lld/trunk/ELF/InputSection.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=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Mon Jul 9 09:35:51 2018
@@ -55,6 +55,7 @@ public:
RelExpr Expr) const override;
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;
};
} // namespace
@@ -165,6 +166,52 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc,
}
}
+
+void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
+ // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
+ // The local dynamic code sequence for a global `x` will look like:
+ // Instruction Relocation Symbol
+ // addis r3, r2, x at got@tlsld at ha R_PPC64_GOT_TLSLD16_HA x
+ // addi r3, r3, x at got@tlsld at l R_PPC64_GOT_TLSLD16_LO x
+ // bl __tls_get_addr(x at tlsgd) R_PPC64_TLSLD x
+ // R_PPC64_REL24 __tls_get_addr
+ // nop None None
+
+ // Relaxing to local exec entails converting:
+ // addis r3, r2, x at got@tlsld at ha into nop
+ // addi r3, r3, x at got@tlsld at l into addis r3, r13, 0
+ // bl __tls_get_addr(x at tlsgd) into nop
+ // nop into addi r3, r3, 4096
+
+ uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+ switch (Type) {
+ case R_PPC64_GOT_TLSLD16_HA:
+ write32(Loc - EndianOffset, 0x60000000); // nop
+ break;
+ case R_PPC64_GOT_TLSLD16_LO:
+ write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13, 0
+ break;
+ case R_PPC64_TLSLD:
+ write32(Loc, 0x60000000); // nop
+ write32(Loc + 4, 0x38631000); // addi r3, r3, 4096
+ break;
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ relocateOne(Loc, Type, Val);
+ break;
+ default:
+ llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
+ }
+}
+
RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const {
switch (Type) {
@@ -230,6 +277,7 @@ RelExpr PPC64::getRelExpr(RelType Type,
case R_PPC64_TLSGD:
return R_TLSDESC_CALL;
case R_PPC64_TLSLD:
+ return R_TLSLD_HINT;
case R_PPC64_TLS:
return R_HINT;
default:
@@ -431,6 +479,8 @@ RelExpr PPC64::adjustRelaxExpr(RelType T
RelExpr Expr) const {
if (Expr == R_RELAX_TLS_GD_TO_IE)
return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
+ if (Expr == R_RELAX_TLS_LD_TO_LE)
+ return R_RELAX_TLS_LD_TO_LE_ABS;
return Expr;
}
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Jul 9 09:35:51 2018
@@ -483,6 +483,7 @@ static uint64_t getRelocTargetVA(const I
case R_INVALID:
return 0;
case R_ABS:
+ case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
return Sym.getVA(A);
case R_ADDEND:
@@ -516,6 +517,7 @@ static uint64_t getRelocTargetVA(const I
case R_HINT:
case R_NONE:
case R_TLSDESC_CALL:
+ case R_TLSLD_HINT:
llvm_unreachable("cannot relocate hint relocs");
case R_MIPS_GOTREL:
return Sym.getVA(A) - InX::MipsGot->getGp(File);
@@ -767,6 +769,7 @@ void InputSectionBase::relocateAlloc(uin
Target->relaxTlsIeToLe(BufLoc, Type, TargetVA);
break;
case R_RELAX_TLS_LD_TO_LE:
+ case R_RELAX_TLS_LD_TO_LE_ABS:
Target->relaxTlsLdToLe(BufLoc, Type, TargetVA);
break;
case R_RELAX_TLS_GD_TO_LE:
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Jul 9 09:35:51 2018
@@ -188,13 +188,17 @@ handleTlsRelocation(RelType Type, Symbol
return 1;
}
- if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC>(Expr)) {
+ if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC,
+ R_TLSLD_HINT>(Expr)) {
// Local-Dynamic relocs can be relaxed to Local-Exec.
if (!Config->Shared) {
C.Relocations.push_back(
- {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
- return 2;
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+ Offset, Addend, &Sym});
+ return Target->TlsGdRelaxSkip;
}
+ if (Expr == R_TLSLD_HINT)
+ return 1;
if (InX::Got->addTlsIndex())
InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got,
InX::Got->getTlsIndexOff(), nullptr);
@@ -203,9 +207,10 @@ handleTlsRelocation(RelType Type, Symbol
}
// Local-Dynamic relocs can be relaxed to Local-Exec.
- if (isRelExprOneOf<R_ABS, R_TLSLD_GOT_FROM_END, R_TLSLD_PC>(Expr) &&
- !Config->Shared) {
- C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+ if (Expr == R_ABS && !Config->Shared) {
+ C.Relocations.push_back(
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
+ Offset, Addend, &Sym});
return 1;
}
@@ -357,8 +362,8 @@ static bool isStaticLinkTimeConstant(Rel
R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
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>(
- E))
+ R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT,
+ R_TLSLD_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=336559&r1=336558&r2=336559&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Mon Jul 9 09:35:51 2018
@@ -73,6 +73,7 @@ enum RelExpr {
R_RELAX_TLS_GD_TO_LE_NEG,
R_RELAX_TLS_IE_TO_LE,
R_RELAX_TLS_LD_TO_LE,
+ R_RELAX_TLS_LD_TO_LE_ABS,
R_SIZE,
R_TLS,
R_TLSDESC,
@@ -84,6 +85,7 @@ enum RelExpr {
R_TLSLD_GOT,
R_TLSLD_GOT_FROM_END,
R_TLSLD_GOT_OFF,
+ R_TLSLD_HINT,
R_TLSLD_PC,
};
Added: lld/trunk/test/ELF/ppc64-tls-ld-le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-tls-ld-le.s?rev=336559&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-tls-ld-le.s (added)
+++ lld/trunk/test/ELF/ppc64-tls-ld-le.s Mon Jul 9 09:35:51 2018
@@ -0,0 +1,84 @@
+// REQUIRES: ppc
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
+
+ .text
+ .abiversion 2
+ .globl _start # -- Begin function _start
+ .p2align 4
+ .type _start, at function
+_start: # @_start
+.Lfunc_begin0:
+.Lfunc_gep0:
+ addis 2, 12, .TOC.-.Lfunc_gep0 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep0 at l
+.Lfunc_lep0:
+ .localentry _start, .Lfunc_lep0-.Lfunc_gep0
+# %bb.0: # %entry
+ mflr 0
+ std 31, -8(1)
+ std 0, 16(1)
+ stdu 1, -64(1)
+ mr 31, 1
+ std 30, 48(31) # 8-byte Folded Spill
+ li 3, 0
+ stw 3, 44(31)
+ addis 3, 2, a at got@tlsld at ha
+ addi 3, 3, a at got@tlsld at l
+ bl __tls_get_addr(a at tlsld)
+ nop
+ addis 3, 3, a at dtprel@ha
+ addi 3, 3, a at dtprel@l
+ lwz 30, 0(3)
+ extsw 3, 30
+ ld 30, 48(31) # 8-byte Folded Reload
+ addi 1, 1, 64
+ ld 0, 16(1)
+ ld 31, -8(1)
+ mtlr 0
+ blr
+ .long 0
+ .quad 0
+.Lfunc_end0:
+ .size _start, .Lfunc_end0-.Lfunc_begin0
+ # -- End function
+.globl __tls_get_addr
+.type __tls_get_addr, at function
+__tls_get_addr:
+ .type a, at object # @a
+ .section .tdata,"awT", at progbits
+ .p2align 2
+a:
+ .long 2 # 0x2
+ .size a, 4
+
+// Verify that the input has local-dynamic tls relocation types
+// InputRelocs: Relocation section '.rela.text'
+// InputRelocs: R_PPC64_GOT_TLSLD16_HA {{0+}} a + 0
+// InputRelocs: R_PPC64_GOT_TLSLD16_LO {{0+}} a + 0
+// InputRelocs: R_PPC64_TLSLD {{0+}} a + 0
+
+// Verify that the local-dynamic sequence is relaxed to local exec.
+// Dis: _start:
+// Dis: nop
+// Dis: addis 3, 13, 0
+// Dis: nop
+// Dis: addi 3, 3, 4096
+
+// #ha(a at dtprel) --> (0x0 -0x8000 + 0x8000) >> 16 = 0
+// #lo(a at dtprel) --> (0x0 -0x8000) = -0x8000 = -32768
+// Dis: addis 3, 3, 0
+// Dis: addi 3, 3, -32768
+
+// Verify that no local-dynamic relocations exist for the dynamic linker.
+// OutputRelocs-NOT: R_PPC64_DTPMOD64
More information about the llvm-commits
mailing list