diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 89 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 14 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 15 |
4 files changed, 101 insertions, 18 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 22a103ce35..40c18ca3c2 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" +#include "clang/CodeGen/CodeGenOptions.h" using namespace clang; using namespace CodeGen; @@ -89,8 +90,15 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, "global variable that binds reference to a non-lvalue"); } -void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, - llvm::Constant *DeclPtr) { +void +CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr) { + // Generate a global destructor entry if not using __cxa_atexit. + if (!CGM.getCodeGenOpts().CXAAtExit) { + CGM.AddCXXDtorEntry(DtorFn, DeclPtr); + return; + } + const llvm::Type *Int8PtrTy = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); @@ -123,7 +131,8 @@ void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); } -void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { +void +CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false); @@ -133,18 +142,13 @@ void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, "__cxx_global_var_init", &TheModule); - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), - SourceLocation()); - - llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); - EmitCXXGlobalVarDeclInit(*D, DeclPtr); - - FinishFunction(); + CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); CXXGlobalInits.push_back(Fn); } -void CodeGenModule::EmitCXXGlobalInitFunc() { +void +CodeGenModule::EmitCXXGlobalInitFunc() { if (CXXGlobalInits.empty()) return; @@ -153,20 +157,73 @@ void CodeGenModule::EmitCXXGlobalInitFunc() { false); // Create our global initialization function. - // FIXME: Should this be tweakable by targets? llvm::Function *Fn = llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, - "__cxx_global_initialization", &TheModule); + "_GLOBAL__I_a", &TheModule); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, + &CXXGlobalInits[0], + CXXGlobalInits.size()); + AddGlobalCtor(Fn); +} + +void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn, + llvm::Constant *Object) { + CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object)); +} + +void CodeGenModule::EmitCXXGlobalDtorFunc() { + if (CXXGlobalDtors.empty()) + return; + + const llvm::FunctionType *FTy + = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + false); + + // Create our global destructor function. + llvm::Function *Fn = + llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, + "_GLOBAL__D_a", &TheModule); + + CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); + AddGlobalDtor(Fn); +} +void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, + const VarDecl *D) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), SourceLocation()); - for (unsigned i = 0, e = CXXGlobalInits.size(); i != e; ++i) - Builder.CreateCall(CXXGlobalInits[i]); + llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); + EmitCXXGlobalVarDeclInit(*D, DeclPtr); FinishFunction(); +} - AddGlobalCtor(Fn); +void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, + llvm::Constant **Decls, + unsigned NumDecls) { + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), + SourceLocation()); + + for (unsigned i = 0; i != NumDecls; ++i) + Builder.CreateCall(Decls[i]); + + FinishFunction(); +} + +void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, + const std::vector<std::pair<llvm::Constant*, llvm::Constant*> > + &DtorsAndObjects) { + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), + SourceLocation()); + + // Emit the dtors, in reverse order from construction. + for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) + Builder.CreateCall(DtorsAndObjects[e - i - 1].first, + DtorsAndObjects[e - i - 1].second); + + FinishFunction(); } static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d9b1457811..bd12c4a87c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1225,6 +1225,20 @@ public: void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, llvm::Constant *DeclPtr); + /// GenerateCXXGlobalInitFunc - Generates code for initializing global + /// variables. + void GenerateCXXGlobalInitFunc(llvm::Function *Fn, + llvm::Constant **Decls, + unsigned NumDecls); + + /// GenerateCXXGlobalDtorFunc - Generates code for destroying global + /// variables. + void GenerateCXXGlobalDtorFunc(llvm::Function *Fn, + const std::vector<std::pair<llvm::Constant*, + llvm::Constant*> > &DtorsAndObjects); + + void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D); + void EmitCXXConstructExpr(llvm::Value *Dest, const CXXConstructExpr *E); RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3b04cc125e..b4b5bbdb99 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -81,6 +81,7 @@ void CodeGenModule::createObjCRuntime() { void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); + EmitCXXGlobalDtorFunc(); if (Runtime) if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction()) AddGlobalCtor(ObjCInitFunction); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b93f3c634d..febb856036 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -138,10 +138,14 @@ class CodeGenModule : public BlockModule { llvm::StringMap<llvm::Constant*> CFConstantStringMap; llvm::StringMap<llvm::Constant*> ConstantStringMap; - /// CXXGlobalInits - Variables with global initializers that need to run + /// CXXGlobalInits - Global variables with initializers that need to run /// before main. std::vector<llvm::Constant*> CXXGlobalInits; + /// CXXGlobalDtors - Global destructor functions and arguments that need to + /// run on termination. + std::vector<std::pair<llvm::Constant*,llvm::Constant*> > CXXGlobalDtors; + /// CFConstantStringClassRef - Cached reference to the class for constant /// strings. This value has type int * but is actually an Obj-C class pointer. llvm::Constant *CFConstantStringClassRef; @@ -321,6 +325,10 @@ public: void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); } + /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global + /// destructor function. + void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object); + /// CreateRuntimeFunction - Create a new runtime function with the specified /// type and name. llvm::Constant *CreateRuntimeFunction(const llvm::FunctionType *Ty, @@ -496,9 +504,12 @@ private: /// a C++ destructor Decl. void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); - /// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals. + /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals. void EmitCXXGlobalInitFunc(); + /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals. + void EmitCXXGlobalDtorFunc(); + void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D); // FIXME: Hardcoding priority here is gross. |