aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp89
-rw-r--r--lib/CodeGen/CodeGenFunction.h14
-rw-r--r--lib/CodeGen/CodeGenModule.cpp1
-rw-r--r--lib/CodeGen/CodeGenModule.h15
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.