[llvm] 1756b2a - [AIX][TLS] Generate TLS variables in assembly files

Victor Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 2 16:23:27 PST 2021


Author: Victor Huang
Date: 2021-03-02T18:22:48-06:00
New Revision: 1756b2adc9c1590a4a0c333d659fe7f5f80ce9fd

URL: https://github.com/llvm/llvm-project/commit/1756b2adc9c1590a4a0c333d659fe7f5f80ce9fd
DIFF: https://github.com/llvm/llvm-project/commit/1756b2adc9c1590a4a0c333d659fe7f5f80ce9fd.diff

LOG: [AIX][TLS] Generate TLS variables in assembly files

This patch allows generating TLS variables in assembly files on AIX.
Initialized and external uninitialized variables are generated with the
.csect pseudo-op and local uninitialized variables are generated with
the .comm/.lcomm pseudo-ops. The patch also adds a check to
explicitly say that TLS is not yet supported on AIX.

Reviewed by: daltenty, jasonliu, lei, nemanjai, sfertile
Originally patched by: bsaleil
Commandeered by: NeHuang

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

Added: 
    llvm/test/CodeGen/PowerPC/aix-tls-checks.ll
    llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc32.ll
    llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc64.ll

Modified: 
    llvm/include/llvm/MC/SectionKind.h
    llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/lib/MC/MCObjectFileInfo.cpp
    llvm/lib/MC/MCSectionXCOFF.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/TargetLoweringObjectFile.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/SectionKind.h b/llvm/include/llvm/MC/SectionKind.h
index 0342c4cfbbded..0fd86cc457deb 100644
--- a/llvm/include/llvm/MC/SectionKind.h
+++ b/llvm/include/llvm/MC/SectionKind.h
@@ -82,6 +82,9 @@ class SectionKind {
            /// ThreadData - Initialized TLS data objects.
            ThreadData,
 
+           /// ThreadBSSLocal - Zero-initialized TLS data objects with local linkage.
+           ThreadBSSLocal,
+
        /// GlobalWriteableData - Writeable data that is global (not thread
        /// local).
 
@@ -146,11 +149,12 @@ class SectionKind {
   }
 
   bool isThreadLocal() const {
-    return K == ThreadData || K == ThreadBSS;
+    return K == ThreadData || K == ThreadBSS || K == ThreadBSSLocal;
   }
 
-  bool isThreadBSS() const { return K == ThreadBSS; }
+  bool isThreadBSS() const { return K == ThreadBSS || K == ThreadBSSLocal; }
   bool isThreadData() const { return K == ThreadData; }
+  bool isThreadBSSLocal() const { return K == ThreadBSSLocal; }
 
   bool isGlobalWriteableData() const {
     return isBSS() || isCommon() || isData() || isReadOnlyWithRel();
@@ -194,6 +198,7 @@ class SectionKind {
   static SectionKind getMergeableConst32() { return get(MergeableConst32); }
   static SectionKind getThreadBSS() { return get(ThreadBSS); }
   static SectionKind getThreadData() { return get(ThreadData); }
+  static SectionKind getThreadBSSLocal() { return get(ThreadBSSLocal); }
   static SectionKind getBSS() { return get(BSS); }
   static SectionKind getBSSLocal() { return get(BSSLocal); }
   static SectionKind getBSSExtern() { return get(BSSExtern); }

diff  --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index f1729d1280bb4..0c8a92180969c 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2157,8 +2157,8 @@ TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
       return cast<MCSectionXCOFF>(
                  getSectionForFunctionDescriptor(cast<Function>(GO), TM))
           ->getQualNameSymbol();
-    if ((TM.getDataSections() && !GO->hasSection()) || GOKind.isCommon() ||
-        GOKind.isBSSLocal())
+    if ((TM.getDataSections() && !GO->hasSection()) || GO->hasCommonLinkage() ||
+        GOKind.isBSSLocal() || GOKind.isThreadBSSLocal())
       return cast<MCSectionXCOFF>(SectionForGlobal(GO, GOKind, TM))
           ->getQualNameSymbol();
   }
@@ -2196,24 +2196,31 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
   SmallString<128> Name;
   getNameWithPrefix(Name, GO, TM);
 
+  XCOFF::StorageMappingClass SMC =
+      isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA;
+  if (GO->isThreadLocal())
+    SMC = XCOFF::XMC_UL;
+
   // Externals go into a csect of type ER.
   return getContext().getXCOFFSection(
       Name, SectionKind::getMetadata(),
-      XCOFF::CsectProperties(isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA,
-                             XCOFF::XTY_ER));
+      XCOFF::CsectProperties(SMC, XCOFF::XTY_ER));
 }
 
 MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   // Common symbols go into a csect with matching name which will get mapped
   // into the .bss section.
-  if (Kind.isBSSLocal() || Kind.isCommon()) {
+  // Zero-initialized local TLS symbols go into a csect with matching name which
+  // will get mapped into the .tbss section.
+  if (Kind.isBSSLocal() || GO->hasCommonLinkage() || Kind.isThreadBSSLocal()) {
     SmallString<128> Name;
     getNameWithPrefix(Name, GO, TM);
+    XCOFF::StorageMappingClass SMC = Kind.isBSSLocal() ? XCOFF::XMC_BS
+                                     : Kind.isCommon() ? XCOFF::XMC_RW
+                                                       : XCOFF::XMC_UL;
     return getContext().getXCOFFSection(
-        Name, Kind,
-        XCOFF::CsectProperties(
-            Kind.isBSSLocal() ? XCOFF::XMC_BS : XCOFF::XMC_RW, XCOFF::XTY_CM));
+        Name, Kind, XCOFF::CsectProperties(SMC, XCOFF::XTY_CM));
   }
 
   if (Kind.isMergeableCString()) {
@@ -2270,6 +2277,20 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
     return ReadOnlySection;
   }
 
+  // External/weak TLS data and initialized local TLS data are not eligible
+  // to be put into common csect. If data sections are enabled, thread
+  // data are emitted into separate sections. Otherwise, thread data
+  // are emitted into the .tdata section.
+  if (Kind.isThreadLocal()) {
+    if (TM.getDataSections()) {
+      SmallString<128> Name;
+      getNameWithPrefix(Name, GO, TM);
+      return getContext().getXCOFFSection(
+          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TL, XCOFF::XTY_SD));
+    }
+    return TLSDataSection;
+  }
+
   report_fatal_error("XCOFF other section types not yet implemented.");
 }
 

diff  --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index b4c4c8751f17f..06c1ae6b0717e 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -888,6 +888,11 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
       XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD),
       /* MultiSymbolsAllowed*/ true);
 
+  TLSDataSection = Ctx->getXCOFFSection(
+      ".tdata", SectionKind::getThreadData(),
+      XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_TL, XCOFF::XTY_SD),
+      /* MultiSymbolsAllowed*/ true);
+
   TOCBaseSection = Ctx->getXCOFFSection(
       "TOC", SectionKind::getData(),
       XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_TC0,

diff  --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index 5ef23ed1d894a..8c01f7f0dc498 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -38,6 +38,15 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     return;
   }
 
+  // Initialized TLS data.
+  if (getKind().isThreadData()) {
+    // We only expect XMC_TL here for initialized TLS data.
+    if (getMappingClass() != XCOFF::XMC_TL)
+      report_fatal_error("Unhandled storage-mapping class for .tdata csect.");
+    printCsectDirective(OS);
+    return;
+  }
+
   if (getKind().isData()) {
     switch (getMappingClass()) {
     case XCOFF::XMC_RW:
@@ -57,16 +66,32 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     return;
   }
 
-  if (getKind().isBSSLocal() || getKind().isCommon()) {
+  // Common csect type (uninitialized storage) does not have to print csect
+  // directive for section switching.
+  if (getCSectType() == XCOFF::XTY_CM) {
     assert((getMappingClass() == XCOFF::XMC_RW ||
-            getMappingClass() == XCOFF::XMC_BS) &&
-           "Generated a storage-mapping class for a common/bss csect we don't "
+            getMappingClass() == XCOFF::XMC_BS ||
+            getMappingClass() == XCOFF::XMC_UL) &&
+           "Generated a storage-mapping class for a common/bss/tbss csect we "
+           "don't "
            "understand how to switch to.");
-    assert(getCSectType() == XCOFF::XTY_CM &&
-           "wrong csect type for .bss csect");
-    // Don't have to print a directive for switching to section for commons.
-    // '.comm' and '.lcomm' directives for the variable will create the needed
-    // csect.
+    // Common symbols and local zero-initialized symbols for TLS and Non-TLS are
+    // eligible for .bss/.tbss csect, getKind().isThreadBSS() is used to cover
+    // TLS common and zero-initialized local symbols since linkage type (in the
+    // GlobalVariable) is not accessible in this class.
+    assert((getKind().isBSSLocal() || getKind().isCommon() ||
+            getKind().isThreadBSS()) &&
+           "wrong symbol type for .bss/.tbss csect");
+    // Don't have to print a directive for switching to section for commons and
+    // zero-initialized TLS data. The '.comm' and '.lcomm' directives of the
+    // variable will create the needed csect.
+    return;
+  }
+
+  // Zero-initialized TLS data with weak or external linkage are not eligible to
+  // be put into common csect.
+  if (getKind().isThreadBSS()) {
+    printCsectDirective(OS);
     return;
   }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 84de8ec80dbb0..ddfca2a764d46 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -193,7 +193,6 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
   /// sinit/sterm function names.
   std::string FormatIndicatorAndUniqueModId;
 
-  static void ValidateGV(const GlobalVariable *GV);
   // Record a list of GlobalAlias associated with a GlobalObject.
   // This is used for AIX's extra-label-at-definition aliasing strategy.
   DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
@@ -2051,15 +2050,6 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
 #undef GENVALUECOMMENT
 }
 
-void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) {
-  // Early error checking limiting what is supported.
-  if (GV->isThreadLocal())
-    report_fatal_error("Thread local not yet supported on AIX.");
-
-  if (GV->hasComdat())
-    report_fatal_error("COMDAT not yet supported by AIX.");
-}
-
 static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) {
   return GV->hasAppendingLinkage() &&
          StringSwitch<bool>(GV->getName())
@@ -2085,7 +2075,9 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
 
   assert(!GV->getName().startswith("llvm.") &&
          "Unhandled intrinsic global variable.");
-  ValidateGV(GV);
+
+  if (GV->hasComdat())
+    report_fatal_error("COMDAT not yet supported by AIX.");
 
   MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
 
@@ -2095,7 +2087,8 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   }
 
   SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
-  if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly())
+  if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&
+      !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.
     report_fatal_error("Encountered a global variable kind that is "
                        "not supported yet.");
 
@@ -2107,14 +2100,15 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
 
   const DataLayout &DL = GV->getParent()->getDataLayout();
 
-  // Handle common symbols.
-  if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+  // Handle common and zero-initialized local symbols.
+  if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||
+      GVKind.isThreadBSSLocal()) {
     Align Alignment = GV->getAlign().getValueOr(DL.getPreferredAlign(GV));
     uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
     GVSym->setStorageClass(
         TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
 
-    if (GVKind.isBSSLocal())
+    if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal())
       OutStreamer->emitXCOFFLocalCommonSymbol(
           OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
           GVSym, Alignment.value());

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 992fd8bf89735..9675c012fe0a8 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3117,6 +3117,8 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op,
 
 SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
                                               SelectionDAG &DAG) const {
+  if (Subtarget.isAIXABI())
+    report_fatal_error("TLS is not yet supported on AIX.");
   // FIXME: TLS addresses currently use medium model code sequences,
   // which is the most useful form.  Eventually support for small and
   // large models could be added if users need it, at the cost of

diff  --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp
index 4efac2303da6e..eae85c7475554 100644
--- a/llvm/lib/Target/TargetLoweringObjectFile.cpp
+++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp
@@ -217,8 +217,14 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO,
 
   // Handle thread-local data first.
   if (GVar->isThreadLocal()) {
-    if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS)
+    if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {
+      // Zero-initialized TLS variables with local linkage always get classified
+      // as ThreadBSSLocal.
+      if (GVar->hasLocalLinkage()) {
+        return SectionKind::getThreadBSSLocal();
+      }
       return SectionKind::getThreadBSS();
+    }
     return SectionKind::getThreadData();
   }
 

diff  --git a/llvm/test/CodeGen/PowerPC/aix-tls-checks.ll b/llvm/test/CodeGen/PowerPC/aix-tls-checks.ll
new file mode 100644
index 0000000000000..258dc1e4b8830
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-checks.ll
@@ -0,0 +1,13 @@
+; RUN: not --crash llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec \
+; RUN:   -mtriple powerpc-ibm-aix-xcoff < %s - 2>&1 | FileCheck %s
+; RUN: not --crash llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec \
+; RUN:   -mtriple powerpc64-ibm-aix-xcoff < %s - 2>&1 | FileCheck %s
+
+; CHECK: TLS is not yet supported on AIX
+
+ at tls1 = thread_local global i32 0, align 4
+
+define i32* @getTls1Addr() {
+entry:
+  ret i32* @tls1
+}

diff  --git a/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc32.ll b/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc32.ll
new file mode 100644
index 0000000000000..9a71c93ce84f0
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc32.ll
@@ -0,0 +1,261 @@
+; This file tests 32 bit TLS variable generation.
+
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple \
+; RUN:      powerpc-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple \
+; RUN:      powerpc-ibm-aix-xcoff -data-sections=false < %s | FileCheck %s \
+; RUN:      --check-prefix=NODATASEC
+
+; When data-sections is true (default), we emit data into separate sections.
+; When data-sections is false, we emit data into the .data / .tdata sections.
+
+; Int global variable, TLS/Non-TLS, local/external/weak/common linkage
+; CHECK:           .csect  global_int_external_val_initialized[RW],2
+; CHECK-NEXT:      .globl  global_int_external_val_initialized[RW]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 1
+
+; NODATASEC:       .csect  .data[RW],3
+; NODATASEC-NEXT:  .globl  global_int_external_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:global_int_external_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at global_int_external_val_initialized = global i32 1, align 4
+
+; CHECK-NEXT:      .csect  global_int_external_zero_initialized[RW],2
+; CHECK-NEXT:      .globl  global_int_external_zero_initialized[RW]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 0
+
+; NODATASEC-NEXT:  .globl  global_int_external_zero_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:global_int_external_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at global_int_external_zero_initialized = global i32 0, align 4
+
+; CHECK-NEXT:      .csect  tls_global_int_external_val_initialized[TL],2
+; CHECK-NEXT:      .globl  tls_global_int_external_val_initialized[TL]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 1
+
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .globl  tls_global_int_external_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:tls_global_int_external_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at tls_global_int_external_val_initialized = thread_local global i32 1, align 4
+
+; CHECK-NEXT:      .csect  tls_global_int_external_zero_initialized[TL],2
+; CHECK-NEXT:      .globl  tls_global_int_external_zero_initialized[TL]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 0
+
+; NODATASEC-NEXT:  .globl  tls_global_int_external_zero_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:tls_global_int_external_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at tls_global_int_external_zero_initialized = thread_local global i32 0, align 4
+
+; CHECK-NEXT:      .csect  global_int_local_val_initialized[RW],2
+; CHECK-NEXT:      .lglobl global_int_local_val_initialized[RW]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 2
+
+; NODATASEC-NEXT:  .csect .data[RW],3
+; NODATASEC-NEXT:  .lglobl global_int_local_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:global_int_local_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 2
+ at global_int_local_val_initialized = internal global i32 2, align 4
+
+; CHECK-NEXT:      .csect  tls_global_int_local_val_initialized[TL],2
+; CHECK-NEXT:      .lglobl tls_global_int_local_val_initialized[TL]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 2
+
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .lglobl tls_global_int_local_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:tls_global_int_local_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 2
+ at tls_global_int_local_val_initialized = internal thread_local global i32 2, align 4
+
+; CHECK-NEXT:      .lcomm  global_int_local_zero_initialized,4,global_int_local_zero_initialized[BS],2
+; NODATASEC-NEXT:  .lcomm  global_int_local_zero_initialized,4,global_int_local_zero_initialized[BS],2
+ at global_int_local_zero_initialized = internal global i32 0, align 4
+
+; CHECK-NEXT:      .lcomm  tls_global_int_local_zero_initialized,4,tls_global_int_local_zero_initialized[UL],2
+; NODATASEC-NEXT:  .lcomm  tls_global_int_local_zero_initialized,4,tls_global_int_local_zero_initialized[UL],2
+ at tls_global_int_local_zero_initialized = internal thread_local global i32 0, align 4
+
+; CHECK-NEXT:      .csect  global_int_weak_zero_initialized[RW],2
+; CHECK-NEXT:      .weak   global_int_weak_zero_initialized[RW]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 0
+
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_int_weak_zero_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:global_int_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at global_int_weak_zero_initialized = weak global i32 0, align 4
+
+; CHECK-NEXT:      .csect  tls_global_int_weak_zero_initialized[TL],2
+; CHECK-NEXT:      .weak   tls_global_int_weak_zero_initialized[TL]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 0
+
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_int_weak_zero_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:tls_global_int_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at tls_global_int_weak_zero_initialized = weak thread_local global i32 0, align 4
+
+; CHECK-NEXT:      .comm   global_int_common_zero_initialized[RW],4,2
+; NODATASEC-NEXT:  .comm   global_int_common_zero_initialized[RW],4,2
+ at global_int_common_zero_initialized = common global i32 0, align 4
+
+; CHECK-NEXT:      .comm   tls_global_int_common_zero_initialized[UL],4,2
+; NODATASEC-NEXT:  .comm   tls_global_int_common_zero_initialized[UL],4,2
+ at tls_global_int_common_zero_initialized = common thread_local global i32 0, align 4
+
+; CHECK-NEXT:      .csect  global_int_weak_val_initialized[RW],2
+; CHECK-NEXT:      .weak   global_int_weak_val_initialized[RW]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 1
+
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_int_weak_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:global_int_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at global_int_weak_val_initialized = weak global i32 1, align 4
+
+; CHECK-NEXT:      .csect  tls_global_int_weak_val_initialized[TL],2
+; CHECK-NEXT:      .weak   tls_global_int_weak_val_initialized[TL]
+; CHECK-NEXT:      .align  2
+; CHECK-NEXT:      .vbyte  4, 1
+
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_int_weak_val_initialized
+; NODATASEC-NEXT:  .align  2
+; NODATASEC-NEXT:tls_global_int_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at tls_global_int_weak_val_initialized = weak thread_local global i32 1, align 4
+
+; CHECK-NEXT:      .extern global_int_external_uninitialized[UA]
+; NODATASEC-NEXT:  .extern global_int_external_uninitialized[UA]
+ at global_int_external_uninitialized = external global i32, align 4
+
+; CHECK-NEXT:      .extern tls_global_int_external_uninitialized[UL]
+; NODATASEC-NEXT:  .extern tls_global_int_external_uninitialized[UL]
+ at tls_global_int_external_uninitialized = external thread_local global i32, align 4
+
+
+; double global variable, TLS/Non-TLS, common/external linkage
+
+; CHECK-NEXT:      .comm   global_double_common_zero_initialized[RW],8,3
+; NODATASEC-NEXT:  .comm   global_double_common_zero_initialized[RW],8,3
+ at global_double_common_zero_initialized = common global double 0.000000e+00, align 8
+
+; CHECK-NEXT:      .comm   tls_global_double_common_zero_initialized[UL],8,3
+; NODATASEC-NEXT:  .comm   tls_global_double_common_zero_initialized[UL],8,3
+ at tls_global_double_common_zero_initialized = common thread_local global double 0.000000e+00, align 8
+
+; CHECK-NEXT:      .extern global_double_external_uninitialized[UA]
+; NODATASEC-NEXT:  .extern global_double_external_uninitialized[UA]
+ at global_double_external_uninitialized = external global i64, align 8
+
+; CHECK-NEXT:      .extern tls_global_double_external_uninitialized[UL]
+; NODATASEC-NEXT:  .extern tls_global_double_external_uninitialized[UL]
+ at tls_global_double_external_uninitialized = external thread_local global i64, align 8
+
+
+; Long long global variable, TLS/Non-TLS, local/weak linkage
+
+; CHECK-NEXT:      .csect  global_long_long_internal_val_initialized[RW],3
+; CHECK-NEXT:      .lglobl global_long_long_internal_val_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 1
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .lglobl global_long_long_internal_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_internal_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at global_long_long_internal_val_initialized = internal global i64 1, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_internal_val_initialized[TL],3
+; CHECK-NEXT:      .lglobl tls_global_long_long_internal_val_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 1
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .lglobl tls_global_long_long_internal_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_internal_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at tls_global_long_long_internal_val_initialized = internal thread_local global i64 1, align 8
+
+; CHECK-NEXT:      .lcomm  global_long_long_internal_zero_initialized,8,global_long_long_internal_zero_initialized[BS],3
+; NODATASEC-NEXT:  .lcomm  global_long_long_internal_zero_initialized,8,global_long_long_internal_zero_initialized[BS],3
+ at global_long_long_internal_zero_initialized = internal global i64 0, align 8
+
+; CHECK-NEXT:      .lcomm  tls_global_long_long_internal_zero_initialized,8,tls_global_long_long_internal_zero_initialized[UL],3
+; NODATASEC-NEXT:  .lcomm  tls_global_long_long_internal_zero_initialized,8,tls_global_long_long_internal_zero_initialized[UL],3
+ at tls_global_long_long_internal_zero_initialized = internal thread_local global i64 0, align 8
+
+; CHECK-NEXT:      .csect  global_long_long_weak_val_initialized[RW],3
+; CHECK-NEXT:      .weak   global_long_long_weak_val_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 1
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_long_long_weak_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at global_long_long_weak_val_initialized = weak global i64 1, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_weak_val_initialized[TL],3
+; CHECK-NEXT:      .weak   tls_global_long_long_weak_val_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 1
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_long_long_weak_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 1
+ at tls_global_long_long_weak_val_initialized = weak thread_local global i64 1, align 8
+
+; CHECK-NEXT:      .csect  global_long_long_weak_zero_initialized[RW],3
+; CHECK-NEXT:      .weak   global_long_long_weak_zero_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 0
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_long_long_weak_zero_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at global_long_long_weak_zero_initialized = weak global i64 0, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_weak_zero_initialized[TL],3
+; CHECK-NEXT:      .weak   tls_global_long_long_weak_zero_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  4, 0
+; CHECK-NEXT:      .vbyte  4, 0
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_long_long_weak_zero_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  4, 0
+; NODATASEC-NEXT:  .vbyte  4, 0
+ at tls_global_long_long_weak_zero_initialized = weak thread_local global i64 0, align 8

diff  --git a/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc64.ll b/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc64.ll
new file mode 100644
index 0000000000000..f2cbff7f7380a
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-tls-variables-ppc64.ll
@@ -0,0 +1,86 @@
+; This file tests 64 bit TLS variable generation
+
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple \
+; RUN:      powerpc64-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc  -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple \
+; RUN:      powerpc64-ibm-aix-xcoff -data-sections=false < %s | FileCheck %s \
+; RUN:      --check-prefix=NODATASEC
+
+; When data-sections is true (default), we emit data into separate sections.
+; When data-sections is false, we emit data into the .data / .tdata sections.
+
+; Long long global variable, TLS/Non-TLS, local/weak linkage
+
+; CHECK:           .csect  global_long_long_internal_val_initialized[RW],3
+; CHECK-NEXT:      .lglobl global_long_long_internal_val_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 1
+; NODATASEC:       .csect  .data[RW],3
+; NODATASEC-NEXT:  .lglobl global_long_long_internal_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_internal_val_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 1
+ at global_long_long_internal_val_initialized = internal global i64 1, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_internal_val_initialized[TL],3
+; CHECK-NEXT:      .lglobl tls_global_long_long_internal_val_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 1
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .lglobl tls_global_long_long_internal_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_internal_val_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 1
+ at tls_global_long_long_internal_val_initialized = internal thread_local global i64 1, align 8
+
+; CHECK-NEXT:      .lcomm  global_long_long_internal_zero_initialized,8,global_long_long_internal_zero_initialized[BS],3
+; NODATASEC-NEXT:  .lcomm  global_long_long_internal_zero_initialized,8,global_long_long_internal_zero_initialized[BS],3
+ at global_long_long_internal_zero_initialized = internal global i64 0, align 8
+
+; CHECK-NEXT:      .lcomm  tls_global_long_long_internal_zero_initialized,8,tls_global_long_long_internal_zero_initialized[UL],3
+; NODATASEC-NEXT:  .lcomm  tls_global_long_long_internal_zero_initialized,8,tls_global_long_long_internal_zero_initialized[UL],3
+ at tls_global_long_long_internal_zero_initialized = internal thread_local global i64 0, align 8
+
+; CHECK-NEXT:      .csect  global_long_long_weak_val_initialized[RW],3
+; CHECK-NEXT:      .weak   global_long_long_weak_val_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 1
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_long_long_weak_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 1
+ at global_long_long_weak_val_initialized = weak global i64 1, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_weak_val_initialized[TL],3
+; CHECK-NEXT:      .weak   tls_global_long_long_weak_val_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 1
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_long_long_weak_val_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_weak_val_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 1
+ at tls_global_long_long_weak_val_initialized = weak thread_local global i64 1, align 8
+
+; CHECK-NEXT:      .csect  global_long_long_weak_zero_initialized[RW],3
+; CHECK-NEXT:      .weak   global_long_long_weak_zero_initialized[RW]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 0
+; NODATASEC-NEXT:  .csect  .data[RW],3
+; NODATASEC-NEXT:  .weak   global_long_long_weak_zero_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:global_long_long_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 0
+ at global_long_long_weak_zero_initialized = weak global i64 0, align 8
+
+; CHECK-NEXT:      .csect  tls_global_long_long_weak_zero_initialized[TL],3
+; CHECK-NEXT:      .weak   tls_global_long_long_weak_zero_initialized[TL]
+; CHECK-NEXT:      .align  3
+; CHECK-NEXT:      .vbyte  8, 0
+; NODATASEC-NEXT:  .csect  .tdata[TL],3
+; NODATASEC-NEXT:  .weak   tls_global_long_long_weak_zero_initialized
+; NODATASEC-NEXT:  .align  3
+; NODATASEC-NEXT:tls_global_long_long_weak_zero_initialized:
+; NODATASEC-NEXT:  .vbyte  8, 0
+ at tls_global_long_long_weak_zero_initialized = weak thread_local global i64 0, align 8


        


More information about the llvm-commits mailing list