[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