[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