aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-07-15 23:40:35 +0000
committerJohn McCall <rjmccall@apple.com>2010-07-15 23:40:35 +0000
commitbf40cb518312dde1c07e44fcae59bc4eec65589c (patch)
tree8586ebdad129f9ce6f455050c230fda0570edb08 /lib/CodeGen
parent15a3d7df1ad667c6c09e34def34d546124c9efac (diff)
When deferring the emission of declarations with initializers in C++, remember
the order they appeared in the translation unit. If they get emitted, put them in their proper order. Fixes rdar://problem/7458115 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108477 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp23
-rw-r--r--lib/CodeGen/CodeGenModule.cpp13
-rw-r--r--lib/CodeGen/CodeGenModule.h6
4 files changed, 39 insertions, 7 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1a62ea9555..8d0d338474 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -183,7 +183,7 @@ llvm::GlobalVariable *
CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV) {
llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
-
+
// If constant emission failed, then this should be a C++ static
// initializer.
if (!Init) {
@@ -198,7 +198,7 @@ CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D,
}
return GV;
}
-
+
// The initializer may differ in type from the global. Rewrite
// the global to match the initializer. (We have to do this
// because some types, like unions, can't be completely represented
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index ec3f38667b..a325742573 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -174,13 +174,26 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
+ DelayedCXXInitPosition.erase(D);
+ }
+ else {
+ llvm::DenseMap<const Decl *, unsigned>::iterator I =
+ DelayedCXXInitPosition.find(D);
+ if (I == DelayedCXXInitPosition.end()) {
+ CXXGlobalInits.push_back(Fn);
+ } else {
+ assert(CXXGlobalInits[I->second] == 0);
+ CXXGlobalInits[I->second] = Fn;
+ DelayedCXXInitPosition.erase(I);
+ }
}
- else
- CXXGlobalInits.push_back(Fn);
}
void
CodeGenModule::EmitCXXGlobalInitFunc() {
+ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
+ CXXGlobalInits.pop_back();
+
if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
return;
@@ -200,8 +213,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
LocalCXXGlobalInits.push_back(Fn);
}
- for (unsigned i = 0; i < CXXGlobalInits.size(); i++)
- LocalCXXGlobalInits.push_back(CXXGlobalInits[i]);
+ LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
&LocalCXXGlobalInits[0],
LocalCXXGlobalInits.size());
@@ -247,7 +259,8 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
SourceLocation());
for (unsigned i = 0; i != NumDecls; ++i)
- Builder.CreateCall(Decls[i]);
+ if (Decls[i])
+ Builder.CreateCall(Decls[i]);
FinishFunction();
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 834f981a52..ed95422300 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -792,6 +792,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
EmitGlobalDefinition(GD);
return;
}
+
+ // If we're deferring emission of a C++ variable with an
+ // initializer, remember the order in which it appeared in the file.
+ if (getLangOptions().CPlusPlus && isa<VarDecl>(Global) &&
+ cast<VarDecl>(Global)->hasInit()) {
+ DelayedCXXInitPosition[Global] = CXXGlobalInits.size();
+ CXXGlobalInits.push_back(0);
+ }
// If the value has already been used, add it directly to the
// DeferredDeclsToEmit list.
@@ -1175,6 +1183,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
ErrorUnsupported(D, "static initializer");
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
}
+ } else {
+ // We don't need an initializer, so remove the entry for the delayed
+ // initializer position (just in case this entry was delayed).
+ if (getLangOptions().CPlusPlus)
+ DelayedCXXInitPosition.erase(D);
}
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 27f15fc018..05d02ec0a0 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -162,6 +162,12 @@ class CodeGenModule : public BlockModule {
/// CXXGlobalInits - Global variables with initializers that need to run
/// before main.
std::vector<llvm::Constant*> CXXGlobalInits;
+
+ /// When a C++ decl with an initializer is deferred, null is
+ /// appended to CXXGlobalInits, and the index of that null is placed
+ /// here so that the initializer will be performed in the correct
+ /// order.
+ llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
/// - Global variables with initializers whose order of initialization
/// is set by init_priority attribute.