[lld] r260677 - [lld] [ELF/AArch64] Add support to some GD/LE/IS TLS relocations

Adhemerval Zanella via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 12 05:43:04 PST 2016


Author: azanella
Date: Fri Feb 12 07:43:03 2016
New Revision: 260677

URL: http://llvm.org/viewvc/llvm-project?rev=260677&view=rev
Log:
[lld] [ELF/AArch64] Add support to some GD/LE/IS TLS relocations

This patch adds some TLS relocations and relaxations for AArch64.
Some Global-Dynamic relocation are handled by optimizing them to
Local-Exec (Initial-Exec is not yet supported). They are:

 - R_AARCH64_TLSDESC_ADR_PAGE21
 - R_AARCH64_TLSDESC_LD64_LO12_NC
 - R_AARCH64_TLSDESC_ADD_LO12_NC
 - R_AARCH64_TLSDESC_CALL

Also some Init-Exec is optimized to Local-Exec if possible. They are:

 - R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
 - R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC

Finally some Local-Exec relocation are handled in relocateOne:

 - R_AARCH64_TLSLE_ADD_TPREL_HI12
 - R_AARCH64_TLSLE_ADD_TPREL_LO12_NC

This work is mainly for compiler bootstrap, where static binaries is
showing good progress (although shared object still lacking support
from both TLS aarch64 backend and some other issues).


Added:
    lld/trunk/test/ELF/aarch64-tls-gdle.s
    lld/trunk/test/ELF/aarch64-tls-iele.s
    lld/trunk/test/ELF/aarch64-tls-le.s
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=260677&r1=260676&r2=260677&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Fri Feb 12 07:43:03 2016
@@ -83,6 +83,8 @@ public:
   void writeGotPltHeader(uint8_t *Buf) const override;
   unsigned getDynRel(unsigned Type) const override;
   unsigned getTlsGotRel(unsigned Type) const override;
+  bool isTlsLocalDynamicRel(unsigned Type) const override;
+  bool isTlsGlobalDynamicRel(unsigned Type) const override;
   bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;
   void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
   void writePltZero(uint8_t *Buf) const override;
@@ -115,6 +117,8 @@ class X86_64TargetInfo final : public Ta
 public:
   X86_64TargetInfo();
   unsigned getTlsGotRel(unsigned Type) const override;
+  bool isTlsLocalDynamicRel(unsigned Type) const override;
+  bool isTlsGlobalDynamicRel(unsigned Type) const override;
   bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;
   void writeGotPltHeader(uint8_t *Buf) const override;
   void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
@@ -170,6 +174,7 @@ class AArch64TargetInfo final : public T
 public:
   AArch64TargetInfo();
   unsigned getDynRel(unsigned Type) const override;
+  bool isTlsGlobalDynamicRel(unsigned Type) const override;
   void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
   void writePltZero(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
@@ -182,6 +187,17 @@ 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;
+  unsigned relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
+                    uint64_t SA, const SymbolBody *S) const override;
+  bool canRelaxTls(unsigned Type, const SymbolBody *S) const override;
+
+private:
+  void relocateTlsGdToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
+                         uint64_t P, uint64_t SA) const;
+  void relocateTlsIeToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
+                         uint64_t P, uint64_t SA) const;
+
+  static const uint64_t TcbSize = 16;
 };
 
 class AMDGPUTargetInfo final : public TargetInfo {
@@ -251,14 +267,6 @@ bool TargetInfo::needsCopyRel(uint32_t T
   return false;
 }
 
-bool TargetInfo::isTlsLocalDynamicRel(unsigned Type) const {
-  return Type == TlsLocalDynamicRel;
-}
-
-bool TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
-  return Type == TlsGlobalDynamicRel;
-}
-
 bool TargetInfo::isTlsDynRel(unsigned Type, const SymbolBody &S) const {
   return false;
 }
@@ -272,6 +280,14 @@ bool TargetInfo::needsGot(uint32_t Type,
 
 bool TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { return false; }
 
+bool TargetInfo::isTlsLocalDynamicRel(unsigned Type) const {
+  return false;
+}
+
+bool TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
+  return false;
+}
+
 unsigned TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                               uint64_t P, uint64_t SA,
                               const SymbolBody *S) const {
@@ -285,8 +301,6 @@ X86TargetInfo::X86TargetInfo() {
   IRelativeRel = R_386_IRELATIVE;
   RelativeRel = R_386_RELATIVE;
   TlsGotRel = R_386_TLS_TPOFF;
-  TlsGlobalDynamicRel = R_386_TLS_GD;
-  TlsLocalDynamicRel = R_386_TLS_LDM;
   TlsModuleIndexRel = R_386_TLS_DTPMOD32;
   TlsOffsetRel = R_386_TLS_DTPOFF32;
   UseLazyBinding = true;
@@ -318,6 +332,14 @@ unsigned X86TargetInfo::getTlsGotRel(uns
   return TlsGotRel;
 }
 
+bool X86TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
+  return Type == R_386_TLS_GD;
+}
+
+bool X86TargetInfo::isTlsLocalDynamicRel(unsigned Type) const {
+  return Type == R_386_TLS_LDM;
+}
+
 bool X86TargetInfo::isTlsDynRel(unsigned Type, const SymbolBody &S) const {
   if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
       Type == R_386_TLS_GOTIE)
@@ -593,8 +615,6 @@ X86_64TargetInfo::X86_64TargetInfo() {
   RelativeRel = R_X86_64_RELATIVE;
   IRelativeRel = R_X86_64_IRELATIVE;
   TlsGotRel = R_X86_64_TPOFF64;
-  TlsLocalDynamicRel = R_X86_64_TLSLD;
-  TlsGlobalDynamicRel = R_X86_64_TLSGD;
   TlsModuleIndexRel = R_X86_64_DTPMOD64;
   TlsOffsetRel = R_X86_64_DTPOFF64;
   UseLazyBinding = true;
@@ -662,6 +682,14 @@ unsigned X86_64TargetInfo::getTlsGotRel(
   return R_X86_64_PC32;
 }
 
+bool X86_64TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
+  return Type == R_X86_64_TLSGD;
+}
+
+bool X86_64TargetInfo::isTlsLocalDynamicRel(unsigned Type) const {
+  return Type == R_X86_64_TLSLD;
+}
+
 bool X86_64TargetInfo::isTlsDynRel(unsigned Type, const SymbolBody &S) const {
   return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
 }
@@ -1153,11 +1181,20 @@ AArch64TargetInfo::AArch64TargetInfo() {
   GotRel = R_AARCH64_GLOB_DAT;
   PltRel = R_AARCH64_JUMP_SLOT;
   TlsGotRel = R_AARCH64_TLS_TPREL64;
+  TlsModuleIndexRel = R_AARCH64_TLS_DTPMOD64;
+  TlsOffsetRel = R_AARCH64_TLS_DTPREL64;
   UseLazyBinding = true;
   PltEntrySize = 16;
   PltZeroSize = 32;
 }
 
+bool AArch64TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const {
+  return Type == R_AARCH64_TLSDESC_ADR_PAGE21 ||
+         Type == R_AARCH64_TLSDESC_LD64_LO12_NC ||
+         Type == R_AARCH64_TLSDESC_ADD_LO12_NC ||
+         Type == R_AARCH64_TLSDESC_CALL;
+}
+
 unsigned AArch64TargetInfo::getDynRel(unsigned Type) const {
   if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64)
     return Type;
@@ -1220,7 +1257,11 @@ unsigned AArch64TargetInfo::getTlsGotRel
 }
 
 bool AArch64TargetInfo::isTlsDynRel(unsigned Type, const SymbolBody &S) const {
-  return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
+  return Type == R_AARCH64_TLSDESC_ADR_PAGE21 ||
+         Type == R_AARCH64_TLSDESC_LD64_LO12_NC ||
+         Type == R_AARCH64_TLSDESC_ADD_LO12_NC ||
+         Type == R_AARCH64_TLSDESC_CALL ||
+         Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
          Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
 }
 
@@ -1273,13 +1314,17 @@ bool AArch64TargetInfo::needsPlt(uint32_
   }
 }
 
-static void updateAArch64Adr(uint8_t *L, uint64_t Imm) {
+static void updateAArch64Addr(uint8_t *L, uint64_t Imm) {
   uint32_t ImmLo = (Imm & 0x3) << 29;
   uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5;
   uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5);
   write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);
 }
 
+static inline void updateAArch64Add(uint8_t *L, uint64_t Imm) {
+  or32le(L, (Imm & 0xFFF) << 10);
+}
+
 // Page(Expr) is the page address of the expression Expr, defined
 // as (Expr & ~0xFFF). (This applies even if the machine page size
 // supported by the platform has a different value.)
@@ -1312,20 +1357,20 @@ void AArch64TargetInfo::relocateOne(uint
   case R_AARCH64_ADR_GOT_PAGE: {
     uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
     checkInt<33>(X, Type);
-    updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
+    updateAArch64Addr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
     break;
   }
   case R_AARCH64_ADR_PREL_LO21: {
     uint64_t X = SA - P;
     checkInt<21>(X, Type);
-    updateAArch64Adr(Loc, X & 0x1FFFFF);
+    updateAArch64Addr(Loc, X & 0x1FFFFF);
     break;
   }
   case R_AARCH64_ADR_PREL_PG_HI21:
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
     uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
     checkInt<33>(X, Type);
-    updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
+    updateAArch64Addr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
     break;
   }
   case R_AARCH64_CALL26:
@@ -1378,11 +1423,130 @@ void AArch64TargetInfo::relocateOne(uint
     or32le(Loc, (X & 0xFFFC) << 3);
     break;
   }
+  case R_AARCH64_TLSLE_ADD_TPREL_HI12: {
+    uint64_t V = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align) + SA;
+    checkInt<24>(V, Type);
+    updateAArch64Add(Loc, (V & 0xFFF000) >> 12);
+    break;
+  }
+  case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: {
+    uint64_t V = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align) + SA;
+    updateAArch64Add(Loc, V & 0xFFF);
+    break;
+  }
   default:
     fatal("unrecognized reloc " + Twine(Type));
   }
 }
 
+bool AArch64TargetInfo::canRelaxTls(unsigned Type, const SymbolBody *S) const {
+  if (Config->Shared || (S && !S->isTls()))
+    return false;
+
+  // Global-Dynamic relocs can be relaxed to Initial-Exec if the target is
+  // an executable.  And if the target is local it can also be fully relaxed to
+  // Local-Exec.
+  if (isTlsGlobalDynamicRel(Type))
+    return !canBePreempted(S, true);
+
+  // Initial-Exec relocs can be relaxed to Local-Exec if the target is a local
+  // symbol.
+  if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
+      Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+    return !canBePreempted(S, true);
+
+  return false;
+}
+
+unsigned 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 (canBePreempted(S, true))
+      fatal("Unsupported TLS optimization");
+    uint64_t X = S ? S->getVA<ELF64LE>() : SA;
+    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(unsigned Type, uint8_t *Loc,
+                                          uint8_t *BufEnd, uint64_t P,
+                                          uint64_t SA) 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]
+  //   add     x0, x0, :tlsdesc_los:v     [_AARCH64_TLSDESC_ADD_LO12_NC]
+  //   .tlsdesccall                       [R_AARCH64_TLSDESC_CALL]
+  // And it can optimized to:
+  //   movz    x0, #0x0, lsl #16
+  //   movk    x0, #0x10
+  //   nop
+  //   nop
+
+  uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
+  uint64_t X = SA + TPOff;
+  checkUInt<32>(X, Type);
+
+  uint32_t NewInst;
+  switch (Type) {
+  case R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case R_AARCH64_TLSDESC_CALL:
+    // nop
+    NewInst = 0xd503201f;
+    break;
+  case R_AARCH64_TLSDESC_ADR_PAGE21:
+    // movz
+    NewInst = 0xd2a00000 | (((X >> 16) & 0xffff) << 5);
+    break;
+  case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    // movk
+    NewInst = 0xf2800000 | ((X & 0xffff) << 5);
+    break;
+  default:
+    llvm_unreachable("Unsupported Relocation for TLS GD to LE relax");
+  }
+  write32le(Loc, NewInst);
+}
+
+// Initial-Exec relocations can be relaxed to Local-Exec if symbol is final
+// (can not be preempted).
+void AArch64TargetInfo::relocateTlsIeToLe(unsigned Type, uint8_t *Loc,
+                                          uint8_t *BufEnd, uint64_t P,
+                                          uint64_t SA) const {
+  uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
+  uint64_t X = SA + TPOff;
+  checkUInt<32>(X, Type);
+
+  uint32_t Inst = read32le (Loc);
+  uint32_t NewInst;
+  if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
+    // Generate movz.
+    unsigned RegNo = (Inst & 0x1f);
+    NewInst = (0xd2a00000 | RegNo) | (((X >> 16) & 0xffff) << 5);
+  } else if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
+    // Generate movk
+    unsigned RegNo = (Inst & 0x1f);
+    NewInst = (0xf2800000 | RegNo) | ((X & 0xffff) << 5);
+  } else {
+    llvm_unreachable("Invalid Relocation for TLS IE to LE Relax");
+  }
+  write32le(Loc, NewInst);
+}
+
+
 // Implementing relocations for AMDGPU is low priority since most
 // programs don't use relocations now. Thus, this function is not
 // actually called (relocateOne is called for each relocation).

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=260677&r1=260676&r2=260677&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri Feb 12 07:43:03 2016
@@ -22,8 +22,8 @@ class SymbolBody;
 class TargetInfo {
 public:
   uint64_t getVAStart() const;
-  bool isTlsLocalDynamicRel(unsigned Type) const;
-  bool isTlsGlobalDynamicRel(unsigned Type) const;
+  virtual bool isTlsLocalDynamicRel(unsigned Type) const;
+  virtual bool isTlsGlobalDynamicRel(unsigned Type) const;
   virtual unsigned getDynRel(unsigned Type) const { return Type; }
   virtual bool isTlsDynRel(unsigned Type, const SymbolBody &S) const;
   virtual unsigned getTlsGotRel(unsigned Type) const { return TlsGotRel; }
@@ -82,8 +82,6 @@ public:
   unsigned RelativeRel;
   unsigned IRelativeRel;
   unsigned TlsGotRel = 0;
-  unsigned TlsLocalDynamicRel = 0;
-  unsigned TlsGlobalDynamicRel = 0;
   unsigned TlsModuleIndexRel;
   unsigned TlsOffsetRel;
   unsigned PltEntrySize = 8;

Added: lld/trunk/test/ELF/aarch64-tls-gdle.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-tls-gdle.s?rev=260677&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-tls-gdle.s (added)
+++ lld/trunk/test/ELF/aarch64-tls-gdle.s Fri Feb 12 07:43:03 2016
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
+# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#Local-Dynamic to Initial-Exec relax creates no
+#RELOC:      Relocations [
+#RELOC-NEXT: ]
+
+# TCB size = 0x16 and foo is first element from TLS register.
+#CHECK: Disassembly of section .text:
+#CHECK: _start:
+#CHECK:  11000:	00 00 a0 d2	movz	x0, #0, lsl #16
+#CHECK:  11004:	00 02 80 f2 	movk	x0, #0x10
+#CHECK:  11008:	1f 20 03 d5 	nop
+#CHECK:  1100c:	1f 20 03 d5 	nop
+
+.globl _start
+_start:
+ adrp    x0, :tlsdesc:foo
+ ldr     x1, [x0, :tlsdesc_lo12:foo]
+ add     x0, x0, :tlsdesc_lo12:foo
+ .tlsdesccall foo
+ blr     x1

Added: lld/trunk/test/ELF/aarch64-tls-iele.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-tls-iele.s?rev=260677&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-tls-iele.s (added)
+++ lld/trunk/test/ELF/aarch64-tls-iele.s Fri Feb 12 07:43:03 2016
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
+# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#Local-Dynamic to Initial-Exec relax creates no
+#RELOC:      Relocations [
+#RELOC-NEXT: ]
+
+# TCB size = 0x16 and foo is first element from TLS register.
+#CHECK: Disassembly of section .text:
+#CHECK: _start:
+#CHECK:  11000:	00 00 a0 d2	movz	x0, #0, lsl #16
+#CHECK:  11004:	00 02 80 f2 	movk	x0, #0x10
+
+.globl _start
+_start:
+ adrp    x0, :gottprel:foo
+ ldr     x0, [x0, :gottprel_lo12:foo]

Added: lld/trunk/test/ELF/aarch64-tls-le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-tls-le.s?rev=260677&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-tls-le.s (added)
+++ lld/trunk/test/ELF/aarch64-tls-le.s Fri Feb 12 07:43:03 2016
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
+# RUN: ld.lld %tmain.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#Local-Dynamic to Initial-Exec relax creates no
+#RELOC:      Relocations [
+#RELOC-NEXT: ]
+
+.globl _start
+_start:
+ mrs x0, TPIDR_EL0
+ add x0, x0, :tprel_hi12:v1
+ add x0, x0, :tprel_lo12_nc:v1
+
+# TCB size = 0x16 and foo is first element from TLS register.
+#CHECK: Disassembly of section .text:
+#CHECK: _start:
+#CHECK:  11000: 40 d0 3b d5     mrs     x0, TPIDR_EL0
+#CHECK:  11004: 00 00 00 91     add     x0, x0, #0
+#CHECK:  11008: 00 40 00 91     add     x0, x0, #16
+
+.type   v1, at object
+.section        .tbss,"awT", at nobits
+.globl  v1
+.p2align 2
+v1:
+.word  0
+.size  v1, 4
+




More information about the llvm-commits mailing list