diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 50a50750e8b..d0b48b0db8d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -314,7 +314,32 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Handle the tbss directive on darwin which is a thread local bss directive // like zerofill. if (GVKind.isThreadBSS() && MAI->hasMachoTBSSDirective()) { - OutStreamer.EmitTBSSSymbol(TheSection, GVSym, Size, 1 << AlignLog); + // Emit the .tbss symbol + MCSymbol *MangSym = + OutContext.GetOrCreateSymbol(GVSym->getName() + Twine("$tlv$init")); + OutStreamer.EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog); + OutStreamer.AddBlankLine(); + + // Emit the variable struct for the runtime. + const MCSection *TLVSect + = getObjFileLowering().getTLSExtraDataSection(); + + OutStreamer.SwitchSection(TLVSect); + // Emit the linkage here. + EmitLinkage(GV->getLinkage(), GVSym); + OutStreamer.EmitLabel(GVSym); + + // Three pointers in size: + // - __tlv_bootstrap - used to make sure support exists + // - spare pointer, used when mapped by the runtime + // - pointer to mangled symbol above with initializer + unsigned PtrSize = TD->getPointerSizeInBits()/8; + OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("__tlv_bootstrap"), + PtrSize, 0); + OutStreamer.EmitIntValue(0, PtrSize, 0); + OutStreamer.EmitSymbolValue(MangSym, PtrSize, 0); + + OutStreamer.AddBlankLine(); return; } diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 83768198585..605e2a817b1 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -627,6 +627,8 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, getContext().getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); + + TLSExtraDataSection = TLSTLVSection; } const MCSection *TargetLoweringObjectFileMachO:: @@ -666,9 +668,13 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, const MCSection *TargetLoweringObjectFileMachO:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + Mangler *Mang, const TargetMachine &TM) const { + + // Handle one kind of thread local... + if (Kind.isThreadBSS()) return TLSBSSSection; + assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + if (Kind.isText()) return GV->isWeakForLinker() ? TextCoalSection : TextSection; diff --git a/test/CodeGen/X86/tls-1.ll b/test/CodeGen/X86/tls-1.ll new file mode 100644 index 00000000000..408e5bb0c60 --- /dev/null +++ b/test/CodeGen/X86/tls-1.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s + +@a = thread_local global i32 0 ; [#uses=0] +@b = thread_local global i32 0 ; [#uses=0] + +; CHECK: .tbss _a$tlv$init, 4, 2 +; CHECK: .section __DATA,__thread_vars,thread_local_variables +; CHECK: .globl _a +; CHECK: _a: +; CHECK: .quad ___tlv_bootstrap +; CHECK: .quad 0 +; CHECK: .quad _a$tlv$init + +; CHECK: .tbss _b$tlv$init, 4, 2 +; CHECK: .globl _b +; CHECK: _b: +; CHECK: .quad ___tlv_bootstrap +; CHECK: .quad 0 +; CHECK: .quad _b$tlv$init