[cfe-commits] r108477 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp lib/CodeGen/CGDeclCXX.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/global-init.cpp
John McCall
rjmccall at apple.com
Thu Jul 15 16:40:35 PDT 2010
Author: rjmccall
Date: Thu Jul 15 18:40:35 2010
New Revision: 108477
URL: http://llvm.org/viewvc/llvm-project?rev=108477&view=rev
Log:
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
Modified:
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/test/CodeGenCXX/global-init.cpp
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=108477&r1=108476&r2=108477&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Jul 15 18:40:35 2010
@@ -183,7 +183,7 @@
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 @@
}
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
Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=108477&r1=108476&r2=108477&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Jul 15 18:40:35 2010
@@ -174,13 +174,26 @@
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 @@
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 @@
SourceLocation());
for (unsigned i = 0; i != NumDecls; ++i)
- Builder.CreateCall(Decls[i]);
+ if (Decls[i])
+ Builder.CreateCall(Decls[i]);
FinishFunction();
}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=108477&r1=108476&r2=108477&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Jul 15 18:40:35 2010
@@ -792,6 +792,14 @@
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 @@
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);
}
}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=108477&r1=108476&r2=108477&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Jul 15 18:40:35 2010
@@ -162,6 +162,12 @@
/// 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.
Modified: cfe/trunk/test/CodeGenCXX/global-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-init.cpp?rev=108477&r1=108476&r2=108477&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/global-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/global-init.cpp Thu Jul 15 18:40:35 2010
@@ -29,7 +29,29 @@
// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
D d;
+// <rdar://problem/7458115>
+namespace test1 {
+ int f();
+ const int x = f(); // This has side-effects and gets emitted immediately.
+ const int y = x - 1; // This gets deferred.
+ const int z = ~y; // This also gets deferred, but gets "undeferred" before y.
+ int test() { return z; }
+// CHECK: define i32 @_ZN5test14testEv() {
+// CHECK: define internal void [[TEST1_Z_INIT:@.*]]()
+// CHECK: load i32* @_ZN5test1L1yE
+// CHECK-NEXT: xor
+// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1zE
+// CHECK: define internal void [[TEST1_Y_INIT:@.*]]()
+// CHECK: load i32* @_ZN5test1L1xE
+// CHECK-NEXT: sub
+// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1yE
+
+// Later on, we check that y is initialized before z.
+}
+
// CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+// CHECK: call void [[TEST1_Y_INIT]]
+// CHECK: call void [[TEST1_Z_INIT]]
// rdar://problem/8090834: this should be nounwind
// CHECK-NOEXC: define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
More information about the cfe-commits
mailing list