aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-08-08 23:24:23 +0000
committerAnders Carlsson <andersca@mac.com>2009-08-08 23:24:23 +0000
commit89ed31d3f9eeb8ec77c284a5cf404a74bf5e7acf (patch)
tree3db862303fd3fa7d864623de06bfe4d4cd635143
parent3b2e16b3d25f6b311dba2871e2a566c96238c3d2 (diff)
Add support for global initializers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78515 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCXX.cpp35
-rw-r--r--lib/CodeGen/CGCall.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h6
-rw-r--r--lib/CodeGen/CodeGenModule.cpp13
-rw-r--r--lib/CodeGen/CodeGenModule.h7
-rw-r--r--test/CodeGenCXX/global-init.cpp10
7 files changed, 71 insertions, 4 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index bed6785ef1..bcae8298e6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -91,6 +91,41 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
}
}
+void
+CodeGenModule::EmitCXXGlobalInitFunc() {
+ if (CXXGlobalInits.empty())
+ return;
+
+ const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::VoidTy,
+ 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);
+
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
+ CXXGlobalInits.data(),
+ CXXGlobalInits.size());
+ AddGlobalCtor(Fn);
+}
+
+void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
+ const VarDecl **Decls,
+ unsigned NumDecls) {
+ StartFunction(0, getContext().VoidTy, Fn, FunctionArgList(),
+ SourceLocation());
+
+ for (unsigned i = 0; i != NumDecls; ++i) {
+ const VarDecl *D = Decls[i];
+
+ llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
+ EmitCXXGlobalVarDeclInit(*D, DeclPtr);
+ }
+ FinishFunction();
+}
+
void
CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
llvm::GlobalVariable *GV) {
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 31ed8a6390..12d4d9ca25 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -509,7 +509,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// initialize the return value. TODO: it might be nice to have
// a more general mechanism for this that didn't require synthesized
// return statements.
- if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
+ if (const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
if (FD->hasImplicitReturnZero()) {
QualType RetTy = FD->getResultType().getUnqualifiedType();
const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index eae6161e8e..0b012592e4 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -173,7 +173,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
// FIXME: The cast here is a huge hack.
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(StartLoc);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
DI->EmitFunctionStart(CGM.getMangledName(FD), RetTy, CurFn, Builder);
} else {
// Just use LLVM function name.
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index da88b53352..d18217fcc9 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -901,6 +901,12 @@ public:
void EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor,
llvm::Constant *DeclPtr);
+ /// GenerateCXXGlobalInitFunc - Generates code for initializing global
+ /// variables.
+ void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
+ const VarDecl **Decls,
+ unsigned NumDecls);
+
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 503bcda8e7..df9b341ac9 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -62,6 +62,9 @@ CodeGenModule::~CodeGenModule() {
}
void CodeGenModule::Release() {
+ // We need to call this first because it can add deferred declarations.
+ EmitCXXGlobalInitFunc();
+
EmitDeferred();
if (Runtime)
if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
@@ -854,10 +857,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
Init = EmitNullConstant(D->getType());
} else {
Init = EmitConstantExpr(D->getInit(), D->getType());
+
if (!Init) {
- ErrorUnsupported(D, "static initializer");
QualType T = D->getInit()->getType();
- Init = llvm::UndefValue::get(getTypes().ConvertType(T));
+ if (getLangOptions().CPlusPlus) {
+ CXXGlobalInits.push_back(D);
+ Init = EmitNullConstant(T);
+ } else {
+ ErrorUnsupported(D, "static initializer");
+ Init = llvm::UndefValue::get(getTypes().ConvertType(T));
+ }
}
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 3aa015a99f..923b6d204c 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -173,6 +173,10 @@ class CodeGenModule : public BlockModule {
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
llvm::StringMap<llvm::Constant*> ConstantStringMap;
+ /// CXXGlobalInits - Variables with global initializers that need to run
+ /// before main.
+ std::vector<const VarDecl*> CXXGlobalInits;
+
/// 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;
@@ -444,6 +448,9 @@ private:
/// a C++ destructor Decl.
void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
+ /// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals.
+ void EmitCXXGlobalInitFunc();
+
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
new file mode 100644
index 0000000000..ecca8ff1d6
--- /dev/null
+++ b/test/CodeGenCXX/global-init.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -triple=x86_64-apple-darwin9 -emit-llvm %s -o %t &&
+// RUN: grep "call void @_ZN1AC1Ev" %t | count 1 &&
+// RUN: grep "call i32 @__cxa_atexit(void (i8\*)\* bitcast (void (%.truct.A\*)\* @_ZN1AD1Ev to void (i8\*)\*), i8\* getelementptr (%.truct.A\* @a, i32 0, i32 0), i8\* bitcast (i8\*\* @__dso_handle to i8\*))" %t | count 1
+
+struct A {
+ A();
+ ~A();
+};
+
+A a;