diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 35 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 26 |
8 files changed, 53 insertions, 47 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 98ccc76fbf3..ce1ae32398e 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/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/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index b99216b786b..0fca02dac0c 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/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/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5ac8508375f..02da0a533b8 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/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/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 6567ffb07d8..17571fccf08 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 09b7168a9ea..1898c087198 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a2b80bea6c0..a3cf69b675c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 681ab0a008d..3a5677b303b 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/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/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 94c1f60a8b2..839e0476d40 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/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()); |