summaryrefslogtreecommitdiff
path: root/lib/CodeGen/ItaniumCXXABI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp42
1 files changed, 31 insertions, 11 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index b5d90ea59a49..f7a8dd66c527 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2272,7 +2272,21 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
ArrayRef<llvm::Function *> CXXThreadLocalInits,
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
llvm::Function *InitFunc = nullptr;
- if (!CXXThreadLocalInits.empty()) {
+
+ // Separate initializers into those with ordered (or partially-ordered)
+ // initialization and those with unordered initialization.
+ llvm::SmallVector<llvm::Function *, 8> OrderedInits;
+ llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
+ for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
+ if (isTemplateInstantiation(
+ CXXThreadLocalInitVars[I]->getTemplateSpecializationKind()))
+ UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
+ CXXThreadLocalInits[I];
+ else
+ OrderedInits.push_back(CXXThreadLocalInits[I]);
+ }
+
+ if (!OrderedInits.empty()) {
// Generate a guarded initialization function.
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
@@ -2289,24 +2303,28 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CharUnits GuardAlign = CharUnits::One();
Guard->setAlignment(GuardAlign.getQuantity());
- CodeGenFunction(CGM)
- .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits,
- Address(Guard, GuardAlign));
+ CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, OrderedInits,
+ Address(Guard, GuardAlign));
// On Darwin platforms, use CXX_FAST_TLS calling convention.
if (CGM.getTarget().getTriple().isOSDarwin()) {
InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
}
}
+
+ // Emit thread wrappers.
for (const VarDecl *VD : CXXThreadLocals) {
llvm::GlobalVariable *Var =
cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD)));
+ llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var);
// Some targets require that all access to thread local variables go through
// the thread wrapper. This means that we cannot attempt to create a thread
// wrapper or a thread helper.
- if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition())
+ if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) {
+ Wrapper->setLinkage(llvm::Function::ExternalLinkage);
continue;
+ }
// Mangle the name for the thread_local initialization function.
SmallString<256> InitFnName;
@@ -2322,18 +2340,21 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
bool InitIsInitFunc = false;
if (VD->hasDefinition()) {
InitIsInitFunc = true;
- if (InitFunc)
+ llvm::Function *InitFuncToUse = InitFunc;
+ if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
+ InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());
+ if (InitFuncToUse)
Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
- InitFunc);
+ InitFuncToUse);
} else {
// Emit a weak global function referring to the initialization function.
// This function will not exist if the TU defining the thread_local
// variable in question does not need any dynamic initialization for
// its thread_local variables.
llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false);
- Init = llvm::Function::Create(
- FnTy, llvm::GlobalVariable::ExternalWeakLinkage, InitFnName.str(),
- &CGM.getModule());
+ Init = llvm::Function::Create(FnTy,
+ llvm::GlobalVariable::ExternalWeakLinkage,
+ InitFnName.str(), &CGM.getModule());
const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
CGM.SetLLVMFunctionAttributes(nullptr, FI, cast<llvm::Function>(Init));
}
@@ -2341,7 +2362,6 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
if (Init)
Init->setVisibility(Var->getVisibility());
- llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var);
llvm::LLVMContext &Context = CGM.getModule().getContext();
llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
CGBuilderTy Builder(CGM, Entry);