[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