diff --git a/llvm/include/llvm/MC/SectionKind.h b/llvm/include/llvm/MC/SectionKind.h --- a/llvm/include/llvm/MC/SectionKind.h +++ b/llvm/include/llvm/MC/SectionKind.h @@ -82,6 +82,9 @@ /// 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 @@ } 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 @@ 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 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2157,8 +2157,8 @@ return cast( getSectionForFunctionDescriptor(cast(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(SectionForGlobal(GO, GOKind, TM)) ->getQualNameSymbol(); } @@ -2196,24 +2196,31 @@ SmallString<128> Name; getNameWithPrefix(Name, GO, TM); + XCOFF::StorageMappingClass SMC = + isa(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(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 @@ 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 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -888,6 +888,11 @@ 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 --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -38,6 +38,15 @@ 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 @@ 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 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -193,7 +193,6 @@ /// 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> @@ -2051,15 +2050,6 @@ #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(GV->getName()) @@ -2085,7 +2075,9 @@ 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(getSymbol(GV)); @@ -2095,7 +2087,8 @@ } 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 @@ 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 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3117,6 +3117,8 @@ 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 --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -217,8 +217,14 @@ // 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 --- /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 + +@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 --- /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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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] +@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] +@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 +@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 +@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] +@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] +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 --- /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 +@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 +@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 +@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 +@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 +@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 +@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 +@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 +@tls_global_long_long_weak_zero_initialized = weak thread_local global i64 0, align 8