aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-11-06 09:44:32 +0000
committerJohn McCall <rjmccall@apple.com>2010-11-06 09:44:32 +0000
commit3030eb82593097502469a8b3fc26112c79c75605 (patch)
tree4bebde66f116b99a8a45232887b9bc3ff7cdba48 /lib/CodeGen
parentbb6afcb7f5f9c2e9121a548726d6d03283cb52bc (diff)
Simplify the logic for emitting guard variables for template static
data members by delaying the emission of the initializer until after linkage and visibility have been set on the global. Also, don't emit a guard unless the variable actually ends up with vague linkage, and don't use thread-safe statics in any case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118336 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGCXX.cpp6
-rw-r--r--lib/CodeGen/CGCXXABI.h13
-rw-r--r--lib/CodeGen/CGDecl.cpp2
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp35
-rw-r--r--lib/CodeGen/CodeGenFunction.h10
-rw-r--r--lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--lib/CodeGen/CodeGenModule.h3
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp26
8 files changed, 53 insertions, 47 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 98ccc76fbf..ce1ae32398 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -468,8 +468,8 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
CookieSize = CharUnits::Zero();
}
-void CGCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
- const VarDecl &D,
- llvm::GlobalVariable *GV) {
+void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
ErrorUnsupportedABI(CGF, "static local variable initialization");
}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index b99216b786..0fca02dac0 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -221,11 +221,14 @@ public:
/*************************** Static local guards ****************************/
- /// Emits the initializer and destructor setup for the given static
- /// local variable, given that it's reachable and couldn't be
- /// emitted as a constant.
- virtual void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
- llvm::GlobalVariable *DeclPtr);
+ /// Emits the guarded initializer and destructor setup for the given
+ /// variable, given that it couldn't be emitted as a constant.
+ ///
+ /// The variable may be:
+ /// - a static local variable
+ /// - a static data member of a class template instantiation
+ virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
};
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 5ac8508375..02da0a533b 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -196,7 +196,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
// be constant.
GV->setConstant(false);
- EmitCXXStaticLocalInit(D, GV);
+ EmitCXXGuardedInit(D, GV);
}
return GV;
}
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 6567ffb07d..17571fccf0 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -140,9 +140,9 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
}
-void CodeGenFunction::EmitCXXStaticLocalInit(const VarDecl &D,
- llvm::GlobalVariable *DeclPtr) {
- CGM.getCXXABI().EmitStaticLocalInit(*this, D, DeclPtr);
+void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr) {
+ CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
}
static llvm::Function *
@@ -165,7 +165,8 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
}
void
-CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
+CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
const llvm::FunctionType *FTy
= llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false);
@@ -174,7 +175,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
llvm::Function *Fn =
CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
- CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
+ CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
if (D->hasAttr<InitPriorityAttr>()) {
unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
@@ -247,26 +248,20 @@ void CodeGenModule::EmitCXXGlobalDtorFunc() {
AddGlobalDtor(Fn);
}
+/// Emit the code necessary to initialize the given global variable.
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
- const VarDecl *D) {
+ const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
SourceLocation());
- llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
- if (D->isStaticDataMember() &&
- D->getInstantiatedFromStaticDataMember() && D->getInit()){
- llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(DeclPtr);
- assert(GV && "GenerateCXXGlobalVarDeclInitFunc - GV is null");
- llvm::GlobalValue::LinkageTypes Linkage =
- CGM.GetLLVMLinkageVarDefinition(D, GV);
- if (Linkage == llvm::GlobalVariable::WeakAnyLinkage) {
- GV->setConstant(false);
- EmitCXXStaticLocalInit(*D, GV);
- FinishFunction();
- return;
- }
+ // Use guarded initialization if the global variable is weak due to
+ // being a class template's static data member.
+ if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) {
+ EmitCXXGuardedInit(*D, Addr);
+ } else {
+ EmitCXXGlobalVarDeclInit(*D, Addr);
}
- EmitCXXGlobalVarDeclInit(*D, DeclPtr);
FinishFunction();
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 09b7168a9e..1898c08719 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1628,7 +1628,12 @@ public:
void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr);
- void EmitCXXStaticLocalInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
+ /// Emit code in this function to perform a guarded variable
+ /// initialization. Guarded initializations are used when it's not
+ /// possible to prove that an initialization will be done exactly
+ /// once, e.g. with a static local variable or a static data member
+ /// of a class template.
+ void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
/// variables.
@@ -1642,7 +1647,8 @@ public:
const std::vector<std::pair<llvm::WeakVH,
llvm::Constant*> > &DtorsAndObjects);
- void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D);
+ void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D,
+ llvm::GlobalVariable *Addr);
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index a2b80bea6c..a3cf69b675 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1102,7 +1102,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
T = D->getType();
if (getLangOptions().CPlusPlus) {
- EmitCXXGlobalVarDeclInitFunc(D);
Init = EmitNullConstant(T);
NonConstInit = true;
} else {
@@ -1184,6 +1183,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
SetCommonAttributes(D, GV);
+ // Emit the initializer function if necessary.
+ if (NonConstInit)
+ EmitCXXGlobalVarDeclInitFunc(D, GV);
+
// Emit global variable debug information.
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(D->getLocation());
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 681ab0a008..3a5677b303 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -590,7 +590,8 @@ private:
/// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals.
void EmitCXXGlobalDtorFunc();
- void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D);
+ void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+ llvm::GlobalVariable *Addr);
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 94c1f60a8b..839e0476d4 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -120,8 +120,8 @@ public:
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
- void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
- llvm::GlobalVariable *DeclPtr);
+ void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -1078,11 +1078,15 @@ namespace {
/// The ARM code here follows the Itanium code closely enough that we
/// just special-case it at particular places.
-void ItaniumCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
- const VarDecl &D,
- llvm::GlobalVariable *GV) {
+void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
CGBuilderTy &Builder = CGF.Builder;
- bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
+
+ // We only need to use thread-safe statics for local variables;
+ // global initialization is always single-threaded.
+ bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics &&
+ D.isLocalVarDecl());
// Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
const llvm::IntegerType *GuardTy
@@ -1093,16 +1097,10 @@ void ItaniumCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
llvm::SmallString<256> GuardVName;
getMangleContext().mangleItaniumGuardVariable(&D, GuardVName);
- // FIXME: we should just absorb linkage and visibility from the
- // variable, but that's not always set up properly just yet.
- llvm::GlobalValue::LinkageTypes Linkage = GV->getLinkage();
- if (D.isStaticDataMember() &&
- D.getInstantiatedFromStaticDataMember())
- Linkage = llvm::GlobalVariable::WeakAnyLinkage;
-
+ // Just absorb linkage and visibility from the variable.
llvm::GlobalVariable *GuardVariable =
new llvm::GlobalVariable(CGM.getModule(), GuardTy,
- false, Linkage,
+ false, GV->getLinkage(),
llvm::ConstantInt::get(GuardTy, 0),
GuardVName.str());
GuardVariable->setVisibility(GV->getVisibility());