[llvm] 365f861 - [PowerPC][PCRelative] Thread Local Storage Support for Initial Exec

Kamau Bridgeman via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 08:13:29 PDT 2020


Author: Kamau Bridgeman
Date: 2020-08-21T10:13:11-05:00
New Revision: 365f861c45bb504c7b61f64943916fc570818cd1

URL: https://github.com/llvm/llvm-project/commit/365f861c45bb504c7b61f64943916fc570818cd1
DIFF: https://github.com/llvm/llvm-project/commit/365f861c45bb504c7b61f64943916fc570818cd1.diff

LOG: [PowerPC][PCRelative] Thread Local Storage Support for Initial Exec

This patch is the initial support for the Intial Exec Thread Local
Local Storage model to produce code sequence and relocations correct
to the ABI for the model when using PC relative memory operations.

Reviewed By: stefanp

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

Added: 
    llvm/test/CodeGen/PowerPC/pcrel-tls-initial-exec.ll
    llvm/test/MC/PowerPC/pcrel-tls-initial-exec-address-load-reloc.s
    llvm/test/MC/PowerPC/pcrel-tls-initial-exec-value-load-reloc.s

Modified: 
    llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
    llvm/lib/Target/PowerPC/PPC.h
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
    llvm/lib/Target/PowerPC/PPCMCInstLower.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
index dd0343905e96..2cf021a4cf6f 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
@@ -101,6 +101,7 @@
 #undef R_PPC64_PCREL34
 #undef R_PPC64_GOT_PCREL34
 #undef R_PPC64_GOT_TLSGD_PCREL34
+#undef R_PPC64_GOT_TPREL_PCREL34
 #undef R_PPC64_IRELATIVE
 #undef R_PPC64_REL16
 #undef R_PPC64_REL16_LO
@@ -200,6 +201,7 @@ ELF_RELOC(R_PPC64_PCREL_OPT,            123)
 ELF_RELOC(R_PPC64_PCREL34,              132)
 ELF_RELOC(R_PPC64_GOT_PCREL34,          133)
 ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34,    148)
+ELF_RELOC(R_PPC64_GOT_TPREL_PCREL34,    150)
 ELF_RELOC(R_PPC64_IRELATIVE,            248)
 ELF_RELOC(R_PPC64_REL16,                249)
 ELF_RELOC(R_PPC64_REL16_LO,             250)

diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 28b5a4bc9364..a88714ecc014 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -300,6 +300,8 @@ class MCSymbolRefExpr : public MCExpr {
     VK_PPC_GOT_TLSLD_HA,    // symbol at got@tlsld at ha
     VK_PPC_GOT_PCREL,       // symbol at got@pcrel
     VK_PPC_GOT_TLSGD_PCREL, // symbol at got@tlsgd at pcrel
+    VK_PPC_GOT_TPREL_PCREL, // symbol at got@tprel at pcrel
+    VK_PPC_TLS_PCREL,       // symbol at tls@pcrel
     VK_PPC_TLSLD,           // symbol at tlsld
     VK_PPC_LOCAL,           // symbol at local
     VK_PPC_NOTOC,           // symbol at notoc

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 1b10510e474b..07680e95e8e1 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -324,6 +324,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
     return "got at pcrel";
   case VK_PPC_GOT_TLSGD_PCREL:
     return "got at tlsgd@pcrel";
+  case VK_PPC_GOT_TPREL_PCREL:
+    return "got at tprel@pcrel";
+  case VK_PPC_TLS_PCREL:
+    return "tls at pcrel";
   case VK_PPC_TLSLD: return "tlsld";
   case VK_PPC_LOCAL: return "local";
   case VK_PPC_NOTOC: return "notoc";
@@ -457,6 +461,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
     .Case("got at tlsld@ha", VK_PPC_GOT_TLSLD_HA)
     .Case("got at pcrel", VK_PPC_GOT_PCREL)
     .Case("got at tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL)
+    .Case("got at tprel@pcrel", VK_PPC_GOT_TPREL_PCREL)
+    .Case("tls at pcrel", VK_PPC_TLS_PCREL)
     .Case("notoc", VK_PPC_NOTOC)
     .Case("gdgot", VK_Hexagon_GD_GOT)
     .Case("gdplt", VK_Hexagon_GD_PLT)

diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 81008d3ea566..ef1947692960 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -651,7 +651,8 @@ struct PPCOperand : public MCParsedAsmOperand {
       return CreateImm(CE->getValue(), S, E, IsPPC64);
 
     if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val))
-      if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS)
+      if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS ||
+          SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL)
         return CreateTLSReg(SRE, S, E, IsPPC64);
 
     if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) {

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
index e55da7ecf3ee..006cd57f517e 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
@@ -141,6 +141,9 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:
         Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
         break;
+      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL:
+        Type = ELF::R_PPC64_GOT_TPREL_PCREL34;
+        break;
       }
       break;
     case FK_Data_4:
@@ -410,6 +413,9 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
         else
           Type = ELF::R_PPC_TLS;
         break;
+      case MCSymbolRefExpr::VK_PPC_TLS_PCREL:
+        Type = ELF::R_PPC64_TLS;
+        break;
       }
       break;
     case PPC::fixup_ppc_imm34:

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index bd0ee922a16c..447a02834b9b 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -232,9 +232,10 @@ PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
     // Currently these are the only valid PCRelative Relocations.
     assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL ||
-            SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL) &&
+            SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL ||
+            SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) &&
            "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or "
-           "VK_PPC_GOT_TLSGD_PCREL");
+           "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TPREL_PCREL");
     // Generate the fixup for the relocation.
     Fixups.push_back(
         MCFixup::create(0, Expr,
@@ -346,8 +347,12 @@ unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
 
   // Add a fixup for the TLS register, which simply provides a relocation
   // hint to the linker that this statement is part of a relocation sequence.
-  // Return the thread-pointer register's encoding.
-  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
+  // Return the thread-pointer register's encoding. Add a one byte displacement
+  // if using PC relative memops.
+  const MCExpr *Expr = MO.getExpr();
+  const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
+  bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL;
+  Fixups.push_back(MCFixup::create(IsPCRel ? 1 : 0, Expr,
                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
   const Triple &TT = STI.getTargetTriple();
   bool isPPC64 = TT.isPPC64();

diff  --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h
index 70ca65b4325e..e8a9032bfbee 100644
--- a/llvm/lib/Target/PowerPC/PPC.h
+++ b/llvm/lib/Target/PowerPC/PPC.h
@@ -113,11 +113,20 @@ namespace llvm {
     /// TLS General Dynamic model.
     MO_TLSGD_FLAG = 32,
 
+    /// MO_TPREL_FLAG - If this bit is set the symbol reference is relative to
+    /// TLS Initial Exec model.
+    MO_TPREL_FLAG = 64,
+
     /// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set
     /// they should produce the relocation @got at tlsgd@pcrel.
     /// Fix up is VK_PPC_GOT_TLSGD_PCREL
     MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG,
 
+    /// MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set
+    /// they should produce the relocation @got at tprel@pcrel.
+    /// Fix up is VK_PPC_GOT_TPREL_PCREL
+    MO_GOT_TPREL_PCREL_FLAG = MO_GOT_FLAG | MO_TPREL_FLAG | MO_PCREL_FLAG,
+
     /// The next are not flags but distinct values.
     MO_ACCESS_MASK = 0xf00,
 

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index cd2b9307de3f..ce9fdf895610 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -2978,25 +2978,34 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
   }
 
   if (Model == TLSModel::InitialExec) {
-    SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
-    SDValue TGATLS = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
-                                                PPCII::MO_TLS);
-    SDValue GOTPtr;
-    if (is64bit) {
-      setUsesTOCBasePtr(DAG);
-      SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
-      GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl,
-                           PtrVT, GOTReg, TGA);
+    bool IsPCRel = Subtarget.isUsingPCRelativeCalls();
+    SDValue TGA = DAG.getTargetGlobalAddress(
+        GV, dl, PtrVT, 0, IsPCRel ? PPCII::MO_GOT_TPREL_PCREL_FLAG : 0);
+    SDValue TGATLS = DAG.getTargetGlobalAddress(
+        GV, dl, PtrVT, 0,
+        IsPCRel ? (PPCII::MO_TLS | PPCII::MO_PCREL_FLAG) : PPCII::MO_TLS);
+    SDValue TPOffset;
+    if (IsPCRel) {
+      SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
+      TPOffset = DAG.getLoad(MVT::i64, dl, DAG.getEntryNode(), MatPCRel,
+                             MachinePointerInfo());
     } else {
-      if (!TM.isPositionIndependent())
-        GOTPtr = DAG.getNode(PPCISD::PPC32_GOT, dl, PtrVT);
-      else if (picLevel == PICLevel::SmallPIC)
-        GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT);
-      else
-        GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);
+      SDValue GOTPtr;
+      if (is64bit) {
+        setUsesTOCBasePtr(DAG);
+        SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
+        GOTPtr =
+            DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA);
+      } else {
+        if (!TM.isPositionIndependent())
+          GOTPtr = DAG.getNode(PPCISD::PPC32_GOT, dl, PtrVT);
+        else if (picLevel == PICLevel::SmallPIC)
+          GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT);
+        else
+          GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);
+      }
+      TPOffset = DAG.getNode(PPCISD::LD_GOT_TPREL_L, dl, PtrVT, TGA, GOTPtr);
     }
-    SDValue TPOffset = DAG.getNode(PPCISD::LD_GOT_TPREL_L, dl,
-                                   PtrVT, TGA, GOTPtr);
     return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
   }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index 30217d33b020..5c59e0f7b2af 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -2274,7 +2274,9 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
       {MO_GOT_FLAG, "ppc-got"},
       {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"},
       {MO_TLSGD_FLAG, "ppc-tlsgd"},
-      {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}};
+      {MO_TPREL_FLAG, "ppc-tprel"},
+      {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"},
+      {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}};
   return makeArrayRef(TargetFlags);
 }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
index 8332136722f8..795abed413e0 100644
--- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
@@ -74,7 +74,9 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
       RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
       break;
     case PPCII::MO_TLS:
-      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
+      bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG;
+      RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL
+                        : MCSymbolRefExpr::VK_PPC_TLS;
       break;
   }
 
@@ -86,6 +88,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
     RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
   else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
     RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL;
+  else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG)
+    RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL;
 
   const MachineInstr *MI = MO.getParent();
   const MachineFunction *MF = MI->getMF();

diff  --git a/llvm/test/CodeGen/PowerPC/pcrel-tls-initial-exec.ll b/llvm/test/CodeGen/PowerPC/pcrel-tls-initial-exec.ll
new file mode 100644
index 000000000000..7789e23515ab
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/pcrel-tls-initial-exec.ll
@@ -0,0 +1,48 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr10 -ppc-asm-full-reg-names -enable-ppc-pcrel-tls < %s | \
+; RUN:   FileCheck %s --check-prefix=CHECK-S
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr10 -ppc-asm-full-reg-names --filetype=obj \
+; RUN:   -enable-ppc-pcrel-tls < %s | llvm-objdump --mcpu=pwr10 -dr - | \
+; RUN:   FileCheck %s --check-prefix=CHECK-O
+
+; These test cases are to ensure that when using pc relative memory operations
+; ABI correct code and relocations are produced for Initial Exec TLS Model.
+; Note that with R_PPC64_TLS relocations, to distinguish PC relative
+; TLS the relocation has a field value displaced by one byte from the
+; beginning of the instruction.
+
+ at x = external thread_local global i32, align 4
+
+define i32* @InitialExecAddressLoad() {
+; CHECK-S-LABEL: InitialExecAddressLoad:
+; CHECK-S:       # %bb.0: # %entry
+; CHECK-S-NEXT:    pld r3, x at got@tprel at pcrel(0), 1
+; CHECK-S-NEXT:    add r3, r3, x at tls@pcrel
+; CHECK-S-NEXT:    blr
+; CHECK-O-LABEL: <InitialExecAddressLoad>:
+; CHECK-O:         00 00 10 04 00 00 60 e4      	pld 3, 0(0), 1
+; CHECK-O-NEXT:    0000000000000000:  R_PPC64_GOT_TPREL_PCREL34	x
+; CHECK-O-NEXT:    14 6a 63 7c                  	add 3, 3, 13
+; CHECK-O-NEXT:    0000000000000009:  R_PPC64_TLS	x
+; CHECK-O-NEXT:    20 00 80 4e                  	blr
+entry:
+  ret i32* @x
+}
+
+define i32 @InitialExecValueLoad() {
+; CHECK-S-LABEL: InitialExecValueLoad:
+; CHECK-S:       # %bb.0: # %entry
+; CHECK-S-NEXT:    pld r3, x at got@tprel at pcrel(0), 1
+; CHECK-S-NEXT:    lwzx r3, r3, x at tls@pcrel
+; CHECK-S-NEXT:    blr
+; CHECK-O-LABEL: <InitialExecValueLoad>:
+; CHECK-O:         00 00 10 04 00 00 60 e4      	pld 3, 0(0), 1
+; CHECK-O-NEXT:    0000000000000020:  R_PPC64_GOT_TPREL_PCREL34	x
+; CHECK-O-NEXT:    2e 68 63 7c                  	lwzx 3, 3, 13
+; CHECK-O-NEXT:    0000000000000029:  R_PPC64_TLS	x
+; CHECK-O-NEXT:    20 00 80 4e                  	blr
+entry:
+  %0 = load i32, i32* @x, align 4
+  ret i32 %0
+}

diff  --git a/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-address-load-reloc.s b/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-address-load-reloc.s
new file mode 100644
index 000000000000..47b1ca51ff4a
--- /dev/null
+++ b/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-address-load-reloc.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \
+# RUN: FileCheck %s -check-prefix=MC
+# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \
+# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ
+
+# This test checks that on Power PC we can correctly convert x at got@tprel at pcrel
+# and x at tls@pcrel into R_PPC64_GOT_TPREL_PCREL34, and R_PPC64_TLS for initial
+# exec relocations with address loaded.
+# Note that with R_PPC64_TLS relocations, to distinguish PC relative
+# TLS the relocation has a field value displaced by one byte from the
+# beginning of the instruction.
+
+# MC-NOT:    error: invalid variant
+
+# READOBJ:        0x0 R_PPC64_GOT_TPREL_PCREL34 x 0x0
+# READOBJ-NEXT:   0x9 R_PPC64_TLS x 0x0
+
+InitialExec:
+	pld 3, x at got@tprel at pcrel(0), 1
+	add 3, 3, x at tls@pcrel
+	blr

diff  --git a/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-value-load-reloc.s b/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-value-load-reloc.s
new file mode 100644
index 000000000000..bc254d66c954
--- /dev/null
+++ b/llvm/test/MC/PowerPC/pcrel-tls-initial-exec-value-load-reloc.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \
+# RUN: FileCheck %s -check-prefix=MC
+# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \
+# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ
+
+# This test checks that on Power PC we can correctly convert x at got@tprel at pcrel
+# and x at tls@pcrel into R_PPC64_GOT_TPREL_PCREL34, and R_PPC64_TLS for initial
+# exec relocations with the value loaded.
+# Note that with R_PPC64_TLS relocations, to distinguish PC relative
+# TLS the relocation has a field value displaced by one byte from the
+# beginning of the instruction.
+
+# MC-NOT:    error: invalid variant
+
+# READOBJ:        0x0 R_PPC64_GOT_TPREL_PCREL34 x 0x0
+# READOBJ-NEXT:   0x9 R_PPC64_TLS x 0x0
+
+InitialExecLoad:
+	pld 3, x at got@tprel at pcrel(0), 1
+	lwzx 3, 3, x at tls@pcrel
+	blr


        


More information about the llvm-commits mailing list