[lld] r263653 - Split relaxTls into one per relaxation type.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 16 12:03:58 PDT 2016


Author: rafael
Date: Wed Mar 16 14:03:58 2016
New Revision: 263653

URL: http://llvm.org/viewvc/llvm-project?rev=263653&view=rev
Log:
Split relaxTls into one per relaxation type.

This reduces code duplication in each target.

Modified:
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=263653&r1=263652&r2=263653&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Mar 16 14:03:58 2016
@@ -92,20 +92,20 @@ public:
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
-  size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody &S) const override;
+
+  size_t relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA) const override;
+  size_t relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
+  size_t relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
+  size_t relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA) const override;
+
   bool isGotRelative(uint32_t Type) const override;
   bool refersToGotEntry(uint32_t Type) const override;
-
-private:
-  void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsIeToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
-                         uint64_t P, uint64_t SA) const;
 };
 
 class X86_64TargetInfo final : public TargetInfo {
@@ -130,18 +130,17 @@ public:
                    uint8_t *PairedLoc = nullptr) const override;
   bool isRelRelative(uint32_t Type) const override;
   bool isSizeRel(uint32_t Type) const override;
-  size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody &S) const override;
 
-private:
-  void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
-  void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
+  size_t relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA) const override;
+  size_t relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
+  size_t relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
+  size_t relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA) const override;
 };
 
 class PPCTargetInfo final : public TargetInfo {
@@ -184,15 +183,15 @@ public:
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
-  size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody &S) const override;
 
-private:
-  void relocateTlsGdToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
-                         uint64_t P, uint64_t SA) const;
-  void relocateTlsIeToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
-                         uint64_t P, uint64_t SA) const;
+  size_t relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
+  size_t relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                        uint64_t P, uint64_t SA,
+                        const SymbolBody &S) const override;
 
+private:
   static const uint64_t TcbSize = 16;
 };
 
@@ -358,7 +357,37 @@ bool TargetInfo::isTlsGlobalDynamicRel(u
 size_t TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                             uint64_t P, uint64_t SA,
                             const SymbolBody &S) const {
-  return 0;
+  if (isTlsGlobalDynamicRel(Type)) {
+    if (S.isPreemptible())
+      return relaxTlsGdToIe(Loc, BufEnd, Type, P, SA);
+    return relaxTlsGdToLe(Loc, BufEnd, Type, P, SA, S);
+  }
+  if (isTlsLocalDynamicRel(Type))
+    return relaxTlsLdToLe(Loc, BufEnd, Type, P, SA);
+  assert(isTlsInitialExecRel(Type));
+  return relaxTlsIeToLe(Loc, BufEnd, Type, P, SA, S);
+}
+
+size_t TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                  uint64_t P, uint64_t SA,
+                                  const SymbolBody &S) const {
+  llvm_unreachable("Should not have claimed to be relaxable");
+}
+
+size_t TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                  uint64_t P, uint64_t SA) const {
+  llvm_unreachable("Should not have claimed to be relaxable");
+}
+
+size_t TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                  uint64_t P, uint64_t SA,
+                                  const SymbolBody &S) const {
+  llvm_unreachable("Should not have claimed to be relaxable");
+}
+
+size_t TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                  uint64_t P, uint64_t SA) const {
+  llvm_unreachable("Should not have claimed to be relaxable");
 }
 
 X86TargetInfo::X86TargetInfo() {
@@ -537,30 +566,28 @@ bool X86TargetInfo::needsDynRelative(uin
   return Config->Shared && Type == R_386_TLS_IE;
 }
 
-size_t X86TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
-                               uint64_t P, uint64_t SA,
-                               const SymbolBody &S) const {
-  switch (Type) {
-  case R_386_TLS_GD:
-    if (S.isPreemptible())
-      relocateTlsGdToIe(Loc, BufEnd, P, SA);
-    else
-      relocateTlsGdToLe(Loc, BufEnd, P, SA);
-    // The next relocation should be against __tls_get_addr, so skip it
-    return 1;
-  case R_386_TLS_GOTIE:
-  case R_386_TLS_IE:
-    relocateTlsIeToLe(Type, Loc, BufEnd, P, SA);
-    return 0;
-  case R_386_TLS_LDM:
-    relocateTlsLdToLe(Loc, BufEnd, P, SA);
-    // The next relocation should be against __tls_get_addr, so skip it
-    return 1;
-  case R_386_TLS_LDO_32:
-    relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
-    return 0;
-  }
-  llvm_unreachable("unknown TLS optimization");
+size_t X86TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                     uint32_t Type, uint64_t P, uint64_t SA,
+                                     const SymbolBody &S) const {
+  // GD can be optimized to LE:
+  //   leal x at tlsgd(, %ebx, 1),
+  //   call __tls_get_addr at plt
+  // Can be converted to:
+  //   movl %gs:0,%eax
+  //   addl $x at ntpoff,%eax
+  // But gold emits subl $foo at tpoff,%eax instead of addl.
+  // These instructions are completely equal in behavior.
+  // This method generates subl to be consistent with gold.
+  const uint8_t Inst[] = {
+      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
+      0x81, 0xe8, 0x00, 0x00, 0x00, 0x00  // subl 0(%ebx), %eax
+  };
+  memcpy(Loc - 3, Inst, sizeof(Inst));
+  relocateOne(Loc + 5, BufEnd, R_386_32, P,
+              Out<ELF32LE>::TlsPhdr->p_memsz - SA);
+
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.1
@@ -571,8 +598,9 @@ size_t X86TargetInfo::relaxTls(uint8_t *
 // Is converted to:
 //   movl %gs:0, %eax
 //   addl x at gotntpoff(%ebx), %eax
-void X86TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                                      uint64_t SA) const {
+size_t X86TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd,
+                                     uint32_t Type, uint64_t P,
+                                     uint64_t SA) const {
   const uint8_t Inst[] = {
       0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
       0x03, 0x83, 0x00, 0x00, 0x00, 0x00  // addl 0(%ebx), %eax
@@ -581,43 +609,9 @@ void X86TargetInfo::relocateTlsGdToIe(ui
   relocateOne(Loc + 5, BufEnd, R_386_32, P,
               SA - Out<ELF32LE>::Got->getVA() -
                   Out<ELF32LE>::Got->getNumEntries() * 4);
-}
 
-// GD can be optimized to LE:
-//   leal x at tlsgd(, %ebx, 1),
-//   call __tls_get_addr at plt
-// Can be converted to:
-//   movl %gs:0,%eax
-//   addl $x at ntpoff,%eax
-// But gold emits subl $foo at tpoff,%eax instead of addl.
-// These instructions are completely equal in behavior.
-// This method generates subl to be consistent with gold.
-void X86TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                                      uint64_t SA) const {
-  const uint8_t Inst[] = {
-      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
-      0x81, 0xe8, 0x00, 0x00, 0x00, 0x00  // subl 0(%ebx), %eax
-  };
-  memcpy(Loc - 3, Inst, sizeof(Inst));
-  relocateOne(Loc + 5, BufEnd, R_386_32, P,
-              Out<ELF32LE>::TlsPhdr->p_memsz - SA);
-}
-
-// LD can be optimized to LE:
-//   leal foo(%reg),%eax
-//   call ___tls_get_addr
-// Is converted to:
-//   movl %gs:0,%eax
-//   nop
-//   leal 0(%esi,1),%esi
-void X86TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                                      uint64_t SA) const {
-  const uint8_t Inst[] = {
-      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
-      0x90,                               // nop
-      0x8d, 0x74, 0x26, 0x00              // leal 0(%esi,1),%esi
-  };
-  memcpy(Loc - 2, Inst, sizeof(Inst));
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 // In some conditions, relocations can be optimized to avoid using GOT.
@@ -625,9 +619,10 @@ void X86TargetInfo::relocateTlsLdToLe(ui
 // Read "ELF Handling For Thread-Local Storage, 5.1
 // IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
 // by Ulrich Drepper for details.
-void X86TargetInfo::relocateTlsIeToLe(uint32_t Type, uint8_t *Loc,
-                                      uint8_t *BufEnd, uint64_t P,
-                                      uint64_t SA) const {
+
+size_t X86TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                     uint32_t Type, uint64_t P, uint64_t SA,
+                                     const SymbolBody &S) const {
   // Ulrich's document section 6.2 says that @gotntpoff can
   // be used with MOVL or ADDL instructions.
   // @indntpoff is similar to @gotntpoff, but for use in
@@ -662,6 +657,34 @@ void X86TargetInfo::relocateTlsIeToLe(ui
       *Op = 0x80 | Reg | (Reg << 3);
   }
   relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
+
+  return 0;
+}
+
+size_t X86TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                     uint32_t Type, uint64_t P,
+                                     uint64_t SA) const {
+  if (Type == R_386_TLS_LDO_32) {
+    relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
+    return 0;
+  }
+
+  // LD can be optimized to LE:
+  //   leal foo(%reg),%eax
+  //   call ___tls_get_addr
+  // Is converted to:
+  //   movl %gs:0,%eax
+  //   nop
+  //   leal 0(%esi,1),%esi
+  const uint8_t Inst[] = {
+      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
+      0x90,                               // nop
+      0x8d, 0x74, 0x26, 0x00              // leal 0(%esi,1),%esi
+  };
+  memcpy(Loc - 2, Inst, sizeof(Inst));
+
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 X86_64TargetInfo::X86_64TargetInfo() {
@@ -781,27 +804,6 @@ bool X86_64TargetInfo::isSizeRel(uint32_
 
 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
 // x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
-// how LD can be optimized to LE:
-//   leaq bar at tlsld(%rip), %rdi
-//   callq __tls_get_addr at PLT
-//   leaq bar at dtpoff(%rax), %rcx
-// Is converted to:
-//  .word 0x6666
-//  .byte 0x66
-//  mov %fs:0,%rax
-//  leaq bar at tpoff(%rax), %rcx
-void X86_64TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd,
-                                         uint64_t P, uint64_t SA) const {
-  const uint8_t Inst[] = {
-      0x66, 0x66,                                          //.word 0x6666
-      0x66,                                                //.byte 0x66
-      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
-  };
-  memcpy(Loc - 3, Inst, sizeof(Inst));
-}
-
-// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
-// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
 // how GD can be optimized to LE:
 //  .byte 0x66
 //  leaq x at tlsgd(%rip), %rdi
@@ -811,14 +813,18 @@ void X86_64TargetInfo::relocateTlsLdToLe
 // Is converted to:
 //  mov %fs:0x0,%rax
 //  lea x at tpoff,%rax
-void X86_64TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
-                                         uint64_t P, uint64_t SA) const {
+size_t X86_64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                        uint32_t Type, uint64_t P, uint64_t SA,
+                                        const SymbolBody &S) const {
   const uint8_t Inst[] = {
       0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
       0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00              // lea x at tpoff,%rax
   };
   memcpy(Loc - 4, Inst, sizeof(Inst));
   relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA);
+
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
@@ -832,14 +838,18 @@ void X86_64TargetInfo::relocateTlsGdToLe
 // Is converted to:
 //  mov %fs:0x0,%rax
 //  addq x at tpoff,%rax
-void X86_64TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd,
-                                         uint64_t P, uint64_t SA) const {
+size_t X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd,
+                                        uint32_t Type, uint64_t P,
+                                        uint64_t SA) const {
   const uint8_t Inst[] = {
       0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
       0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00              // addq x at tpoff,%rax
   };
   memcpy(Loc - 4, Inst, sizeof(Inst));
   relocateOne(Loc + 8, BufEnd, R_X86_64_PC32, P + 12, SA);
+
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
@@ -847,8 +857,9 @@ void X86_64TargetInfo::relocateTlsGdToIe
 // This function does that. Read "ELF Handling For Thread-Local Storage,
 // 5.5 x86-x64 linker optimizations" (http://www.akkadia.org/drepper/tls.pdf)
 // by Ulrich Drepper for details.
-void X86_64TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
-                                         uint64_t P, uint64_t SA) const {
+size_t X86_64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                        uint32_t Type, uint64_t P, uint64_t SA,
+                                        const SymbolBody &S) const {
   // Ulrich's document section 6.5 says that @gottpoff(%rip) must be
   // used in MOVQ or ADDQ instructions only.
   // "MOVQ foo at GOTTPOFF(%RIP), %REG" is transformed to "MOVQ $foo, %REG".
@@ -875,40 +886,40 @@ void X86_64TargetInfo::relocateTlsIeToLe
     *Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d;
   *RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3));
   relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
+  return 0;
 }
 
-// This function applies a TLS relocation with an optimization as described
-// in the Ulrich's document. As a result of rewriting instructions at the
-// relocation target, relocations immediately follow the TLS relocation (which
-// would be applied to rewritten instructions) may have to be skipped.
-// This function returns a number of relocations that need to be skipped.
-size_t X86_64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
-                                  uint64_t P, uint64_t SA,
-                                  const SymbolBody &S) const {
-  switch (Type) {
-  case R_X86_64_DTPOFF32:
-    relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
-    return 0;
-  case R_X86_64_DTPOFF64:
+// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
+// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
+// how LD can be optimized to LE:
+//   leaq bar at tlsld(%rip), %rdi
+//   callq __tls_get_addr at PLT
+//   leaq bar at dtpoff(%rax), %rcx
+// Is converted to:
+//  .word 0x6666
+//  .byte 0x66
+//  mov %fs:0,%rax
+//  leaq bar at tpoff(%rax), %rcx
+size_t X86_64TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                        uint32_t Type, uint64_t P,
+                                        uint64_t SA) const {
+  if (Type == R_X86_64_DTPOFF64) {
     write64le(Loc, SA - Out<ELF64LE>::TlsPhdr->p_memsz);
     return 0;
-  case R_X86_64_GOTTPOFF:
-    relocateTlsIeToLe(Loc, BufEnd, P, SA);
-    return 0;
-  case R_X86_64_TLSGD: {
-    if (S.isPreemptible())
-      relocateTlsGdToIe(Loc, BufEnd, P, SA);
-    else
-      relocateTlsGdToLe(Loc, BufEnd, P, SA);
-    // The next relocation should be against __tls_get_addr, so skip it
-    return 1;
   }
-  case R_X86_64_TLSLD:
-    relocateTlsLdToLe(Loc, BufEnd, P, SA);
-    // The next relocation should be against __tls_get_addr, so skip it
-    return 1;
+  if (Type == R_X86_64_DTPOFF32) {
+    relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
+    return 0;
   }
-  llvm_unreachable("unknown TLS optimization");
+
+  const uint8_t Inst[] = {
+      0x66, 0x66,                                          //.word 0x6666
+      0x66,                                                //.byte 0x66
+      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
+  };
+  memcpy(Loc - 3, Inst, sizeof(Inst));
+  // The next relocation should be against __tls_get_addr, so skip it
+  return 1;
 }
 
 void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
@@ -1455,33 +1466,9 @@ void AArch64TargetInfo::relocateOne(uint
   }
 }
 
-size_t AArch64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
-                                   uint64_t P, uint64_t SA,
-                                   const SymbolBody &S) const {
-  switch (Type) {
-  case R_AARCH64_TLSDESC_ADR_PAGE21:
-  case R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case R_AARCH64_TLSDESC_ADD_LO12_NC:
-  case R_AARCH64_TLSDESC_CALL: {
-    if (S.isPreemptible())
-      fatal("unsupported TLS optimization");
-    uint64_t X = S.getVA<ELF64LE>();
-    relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
-    return 0;
-  }
-  case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
-  case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
-    relocateTlsIeToLe(Type, Loc, BufEnd, P, S.getVA<ELF64LE>());
-    return 0;
-  }
-  llvm_unreachable("unknown TLS optimization");
-}
-
-// Global-Dynamic relocations can be relaxed to Local-Exec if both binary is
-// an executable and target is final (can notbe preempted).
-void AArch64TargetInfo::relocateTlsGdToLe(uint32_t Type, uint8_t *Loc,
-                                          uint8_t *BufEnd, uint64_t P,
-                                          uint64_t SA) const {
+size_t AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                         uint32_t Type, uint64_t P, uint64_t SA,
+                                         const SymbolBody &S) const {
   // TLSDESC Global-Dynamic relocation are in the form:
   //   adrp    x0, :tlsdesc:v             [R_AARCH64_TLSDESC_ADR_PAGE21]
   //   ldr     x1, [x0, #:tlsdesc_lo12:v  [R_AARCH64_TLSDESC_LD64_LO12_NC]
@@ -1492,7 +1479,7 @@ void AArch64TargetInfo::relocateTlsGdToL
   //   movk    x0, #0x10
   //   nop
   //   nop
-
+  SA = S.getVA<ELF64LE>();
   uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
   uint64_t X = SA + TPOff;
   checkUInt<32>(X, Type);
@@ -1516,13 +1503,14 @@ void AArch64TargetInfo::relocateTlsGdToL
     llvm_unreachable("unsupported Relocation for TLS GD to LE relax");
   }
   write32le(Loc, NewInst);
+
+  return 0;
 }
 
-// Initial-Exec relocations can be relaxed to Local-Exec if symbol is final
-// (can not be preempted).
-void AArch64TargetInfo::relocateTlsIeToLe(uint32_t Type, uint8_t *Loc,
-                                          uint8_t *BufEnd, uint64_t P,
-                                          uint64_t SA) const {
+size_t AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
+                                         uint32_t Type, uint64_t P, uint64_t SA,
+                                         const SymbolBody &S) const {
+  SA = S.getVA<ELF64LE>();
   uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
   uint64_t X = SA + TPOff;
   checkUInt<32>(X, Type);
@@ -1541,6 +1529,8 @@ void AArch64TargetInfo::relocateTlsIeToL
     llvm_unreachable("invalid Relocation for TLS IE to LE Relax");
   }
   write32le(Loc, NewInst);
+
+  return 0;
 }
 
 // Implementing relocations for AMDGPU is low priority since most

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=263653&r1=263652&r2=263653&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Mar 16 14:03:58 2016
@@ -69,8 +69,8 @@ public:
   bool canRelaxTls(uint32_t Type, const SymbolBody *S) const;
   template <class ELFT>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const;
-  virtual size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
-                          uint64_t P, uint64_t SA, const SymbolBody &S) const;
+  size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
+                  uint64_t SA, const SymbolBody &S) const;
   virtual ~TargetInfo();
 
   unsigned PageSize = 4096;
@@ -100,6 +100,17 @@ public:
 private:
   virtual bool needsCopyRelImpl(uint32_t Type) const;
   virtual bool needsPltImpl(uint32_t Type) const;
+
+  virtual size_t relaxTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                uint64_t P, uint64_t SA) const;
+  virtual size_t relaxTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                uint64_t P, uint64_t SA,
+                                const SymbolBody &S) const;
+  virtual size_t relaxTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                uint64_t P, uint64_t SA,
+                                const SymbolBody &S) const;
+  virtual size_t relaxTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+                                uint64_t P, uint64_t SA) const;
 };
 
 uint64_t getPPC64TocBase();




More information about the llvm-commits mailing list