[lld] r334304 - [PPC64] Add support for local-exec TLS model

Zaara Syeda via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 8 10:04:09 PDT 2018


Author: syzaara
Date: Fri Jun  8 10:04:09 2018
New Revision: 334304

URL: http://llvm.org/viewvc/llvm-project?rev=334304&view=rev
Log:
[PPC64] Add support for local-exec TLS model

This patch adds the relocations needed support the local-exec TLS model:

R_PPC64_TPREL16
R_PPC64_TPREL16_HA
R_PPC64_TPREL16_LO
R_PPC64_TPREL16_HI
R_PPC64_TPREL16_DS
R_PPC64_TPREL16_LO_DS
R_PPC64_TPREL16_HIGHER
R_PPC64_TPREL16_HIGHERA
R_PPC64_TPREL16_HIGHEST
R_PPC64_TPREL16_HIGHESTA

Differential Revision: https://reviews.llvm.org/D47598

Added:
    lld/trunk/test/ELF/ppc64-local-exec-tls.s
Modified:
    lld/trunk/ELF/Arch/PPC64.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Target.h

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Fri Jun  8 10:04:09 2018
@@ -79,6 +79,8 @@ PPC64::PPC64() {
   GotPltHeaderEntriesNum = 2;
   PltHeaderSize = 60;
   NeedsThunks = true;
+  TcbSize = 8;
+  TlsTpOffset = 0x7000;
 
   TlsModuleIndexRel = R_PPC64_DTPMOD64;
   TlsOffsetRel = R_PPC64_DTPREL64;
@@ -187,6 +189,17 @@ RelExpr PPC64::getRelExpr(RelType Type,
   case R_PPC64_GOT_TPREL16_DS:
   case R_PPC64_GOT_TPREL16_HI:
     return R_GOT_OFF;
+  case R_PPC64_TPREL16:
+  case R_PPC64_TPREL16_HA:
+  case R_PPC64_TPREL16_LO:
+  case R_PPC64_TPREL16_HI:
+  case R_PPC64_TPREL16_DS:
+  case R_PPC64_TPREL16_LO_DS:
+  case R_PPC64_TPREL16_HIGHER:
+  case R_PPC64_TPREL16_HIGHERA:
+  case R_PPC64_TPREL16_HIGHEST:
+  case R_PPC64_TPREL16_HIGHESTA:
+    return R_TLS;
   case R_PPC64_TLSGD:
   case R_PPC64_TLSLD:
   case R_PPC64_TLS:
@@ -277,38 +290,48 @@ void PPC64::relocateOne(uint8_t *Loc, Re
     break;
   }
   case R_PPC64_ADDR16:
+  case R_PPC64_TPREL16:
     checkInt(Loc, Val, 16, Type);
     write16(Loc, Val);
     break;
   case R_PPC64_ADDR16_DS:
+  case R_PPC64_TPREL16_DS:
     checkInt(Loc, Val, 16, Type);
     write16(Loc, (read16(Loc) & 3) | (Val & ~3));
     break;
   case R_PPC64_ADDR16_HA:
   case R_PPC64_REL16_HA:
+  case R_PPC64_TPREL16_HA:
     write16(Loc, applyPPCHa(Val));
     break;
   case R_PPC64_ADDR16_HI:
   case R_PPC64_REL16_HI:
+  case R_PPC64_TPREL16_HI:
     write16(Loc, applyPPCHi(Val));
     break;
   case R_PPC64_ADDR16_HIGHER:
+  case R_PPC64_TPREL16_HIGHER:
     write16(Loc, applyPPCHigher(Val));
     break;
   case R_PPC64_ADDR16_HIGHERA:
+  case R_PPC64_TPREL16_HIGHERA:
     write16(Loc, applyPPCHighera(Val));
     break;
   case R_PPC64_ADDR16_HIGHEST:
+  case R_PPC64_TPREL16_HIGHEST:
     write16(Loc, applyPPCHighest(Val));
     break;
   case R_PPC64_ADDR16_HIGHESTA:
+  case R_PPC64_TPREL16_HIGHESTA:
     write16(Loc, applyPPCHighesta(Val));
     break;
   case R_PPC64_ADDR16_LO:
   case R_PPC64_REL16_LO:
+  case R_PPC64_TPREL16_LO:
     write16(Loc, applyPPCLo(Val));
     break;
   case R_PPC64_ADDR16_LO_DS:
+  case R_PPC64_TPREL16_LO_DS:
     write16(Loc, (read16(Loc) & 3) | (applyPPCLo(Val) & ~3));
     break;
   case R_PPC64_ADDR32:

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Jun  8 10:04:09 2018
@@ -618,8 +618,23 @@ static uint64_t getRelocTargetVA(RelType
     // statically to zero.
     if (Sym.isTls() && Sym.isUndefWeak())
       return 0;
-    if (Target->TcbSize)
+
+    // For TLS variant 1 the TCB is a fixed size, whereas for TLS variant 2 the
+    // TCB is on unspecified size and content. Targets that implement variant 1
+    // should set TcbSize.
+    if (Target->TcbSize) {
+      // PPC64 V2 ABI has the thread pointer offset into the middle of the TLS
+      // storage area by TlsTpOffset for efficient addressing TCB and up to
+      // 4KB – 8 B of other thread library information (placed before the TCB).
+      // Subtracting this offset will get the address of the first TLS block.
+      if (Target->TlsTpOffset)
+        return Sym.getVA(A) - Target->TlsTpOffset;
+
+      // If thread pointer is not offset into the middle, the first thing in the
+      // TLS storage area is the TCB. Add the TcbSize to get the address of the
+      // first TLS block.
       return Sym.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align);
+    }
     return Sym.getVA(A) - Out::TlsPhdr->p_memsz;
   case R_RELAX_TLS_GD_TO_LE_NEG:
   case R_NEG_TLS:

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri Jun  8 10:04:09 2018
@@ -105,9 +105,15 @@ public:
   // On PPC ELF V2 abi, the first entry in the .got is the .TOC.
   unsigned GotHeaderEntriesNum = 0;
 
-  // Set to 0 for variant 2
+  // For TLS variant 1, the TCB is a fixed size specified by the Target.
+  // For variant 2, the TCB is an unspecified size.
+  // Set to 0 for variant 2.
   unsigned TcbSize = 0;
 
+  // Set to the offset (in bytes) that the thread pointer is initialized to
+  // point to, relative to the start of the thread local storage.
+  unsigned TlsTpOffset = 0;
+
   bool NeedsThunks = false;
 
   // A 4-byte field corresponding to one or more trap instructions, used to pad

Added: lld/trunk/test/ELF/ppc64-local-exec-tls.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-local-exec-tls.s?rev=334304&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-local-exec-tls.s (added)
+++ lld/trunk/test/ELF/ppc64-local-exec-tls.s Fri Jun  8 10:04:09 2018
@@ -0,0 +1,163 @@
+// REQUIRES: ppc
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+// RUN: ld.lld  %t.o -o %t
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+
+	.text
+	.abiversion 2
+	.globl	test_local_exec                    # -- Begin function test_local_exec
+	.p2align	4
+	.type	test_local_exec, at function
+test_local_exec:                                   # @test_local_exec
+.Lfunc_begin0:
+# %bb.0:                                # %entry
+	li 3, 0
+	stw 3, -12(1)
+	addis 3, 13, a at tprel@ha
+	addi 3, 3, a at tprel@l
+	ld 3, 0(3)
+	mr 4, 3
+	extsw 3, 4
+	blr
+	.long	0
+	.quad	0
+.Lfunc_end0:
+	.size	test_local_exec, .Lfunc_end0-.Lfunc_begin0
+                                        # -- End function
+test_tprel:
+.Lfunc_gep1:
+  addis 2, 12, .TOC.-.Lfunc_gep1 at ha
+  addi 2, 2, .TOC.-.Lfunc_gep1 at l
+.Lfunc_lep1:
+  .localentry test_tprel, .Lfunc_lep1-.Lfunc_gep1
+  addi 3, 13, b at tprel
+  blr
+
+
+test_hi:
+.Lfunc_gep2:
+  addis 2, 12, .TOC.-.Lfunc_gep2 at ha
+  addi  2, 2,  .TOC.-.Lfunc_gep2 at l
+.Lfunc_lep2:
+  .localentry test_hi, .Lfunc_lep2-.Lfunc_gep2
+  addis 3, 13, b at tprel@h
+  blr
+
+test_ds:
+.Lfunc_gep3:
+  addis 2, 12, .TOC.-.Lfunc_gep3 at ha
+  addi 2, 2, .TOC.-.Lfunc_gep3 at l
+.Lfunc_lep3:
+  .localentry test_ds, .Lfunc_lep3-.Lfunc_gep3
+  ld 3, b at tprel, 13
+  blr
+
+test_lo_ds:
+.Lfunc_gep4:
+  addis 2, 12, .TOC.-.Lfunc_gep4 at ha
+  addi 2, 2, .TOC.-.Lfunc_gep4 at l
+.Lfunc_lep4:
+  .localentry test_lo_ds, .Lfunc_lep4-.Lfunc_gep4
+  ld 3, b at tprel@l, 13
+  blr
+
+test_highest_a:
+.Lfunc_gep5:
+  addis 2, 12, .TOC.-.Lfunc_gep5 at ha
+  addi  2, 2,  .TOC.-.Lfunc_gep5 at l
+.Lfunc_lep5:
+  .localentry test_highest_a, .Lfunc_lep5-.Lfunc_gep5
+  lis 4, b at tprel@highesta
+  ori 4, 4, b at tprel@highera
+  lis 5, b at tprel@ha
+  addi 5, 5, b at tprel@l
+  sldi 4, 4, 32
+  or   4, 4, 5
+  add  3, 13, 4
+  blr
+
+test_highest:
+.Lfunc_gep6:
+  addis 2, 12, .TOC.-.Lfunc_gep6 at ha
+  addi  2, 2,  .TOC.-.Lfunc_gep6 at l
+.Lfunc_lep6:
+  .localentry test_highest, .Lfunc_lep6-.Lfunc_gep6
+  lis 4, b at tprel@highest
+  ori 4, 4, b at tprel@higher
+  sldi 4, 4, 32
+  oris  4, 4, b at tprel@h
+  ori   4, 4, b at tprel@l
+  add  3, 13, 4
+  blr
+
+	.type	a, at object               # @a
+	.type	b, at object               # @b
+	.section	.tdata,"awT", at progbits
+	.p2align	3
+a:
+	.quad	55                      # 0x37
+	.size	a, 8
+
+b:
+	.quad	55                      # 0x37
+	.size	b, 8
+
+// Verify that the input has every initial-exec tls relocation type.
+// InputRelocs: Relocation section '.rela.text'
+// InputRelocs: R_PPC64_TPREL16_HA {{0+}} a + 0
+// InputRelocs: R_PPC64_TPREL16_LO {{0+}} a + 0
+// InputRelocs: R_PPC64_TPREL16 {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HI {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_DS {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_LO_DS {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHESTA {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHERA {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHEST {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHER {{0+8}} b + 0
+
+// The start of the TLS storage area is 0x7000 bytes before the thread pointer (r13).
+// We are building the address of the first TLS variable, relative to the thread pointer.
+// #ha(a at tprel) --> (0 - 0x7000 + 0x8000) >> 16 = 0
+// #lo(a at tprel)) --> (0 - 0x7000) &  0xFFFF =  -0x7000 = -28672
+// Dis: test_local_exec:
+// Dis: addis 3, 13, 0
+// Dis: addi 3, 3, -28672
+
+// We are building the offset for the second TLS variable
+// Offset within tls storage - 0x7000
+// b at tprel = 8 - 0x7000 = 28664
+// Dis: test_tprel:
+// Dis: addi 3, 13, -28664
+
+// #hi(b at tprel) --> (8 - 0x7000) >> 16 = -1
+// Dis: test_hi:
+// Dis: addis 3, 13, -1
+
+// b at tprel = 8 - 0x7000 = -28664
+// Dis: test_ds:
+// Dis: ld 3, -28664(13)
+
+// #lo(b at tprel) --> (8 - 0x7000) & 0xFFFF = -28664
+// Dis: test_lo_ds:
+// Dis: ld 3, -28664(13)
+
+// #highesta(b at tprel) --> ((0x8 - 0x7000 + 0x8000) >> 48) & 0xFFFF = 0
+// #highera(b at tprel)  --> ((0x8 - 0x7000 + 0x8000) >> 32) & 0xFFFF = 0
+// #ha(k at dtprel)       --> ((0x8 - 0x7000 + 0x8000) >> 16) & 0xFFFF = 0
+// #lo(k at dtprel)       --> ((0x8 - 0x7000) & 0xFFFF = -28664
+// Dis: test_highest_a:
+// Dis: lis 4, 0
+// Dis: ori 4, 4, 0
+// Dis: lis 5, 0
+// Dis: addi 5, 5, -28664
+
+// #highest(b at tprel) --> ((0x8 - 0x7000) >> 48) & 0xFFFF = 0xFFFF = -1
+// #higher(b at tprel)  --> ((0x8 - 0x7000) >> 32) & 0xFFFF = 0xFFFF = 65535
+// #hi(k at dtprel)      --> ((0x8 - 0x7000) >> 16) & 0xFFFF = 0xFFFF = 65535
+// #lo(k at dtprel)      --> ((0x8 - 0x7000) & 0xFFFF = 33796
+// Dis: test_highest:
+// Dis: lis 4, -1
+// Dis: ori 4, 4, 65535
+// Dis: oris 4, 4, 65535
+// Dis: ori 4, 4, 36872




More information about the llvm-commits mailing list