[cfe-commits] r118336 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CGDeclCXX.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/CodeGen/ItaniumCXXABI.cpp test/CodeGenCXX/static-data-member.cpp

John McCall rjmccall at apple.com
Sat Nov 6 02:44:32 PDT 2010


Author: rjmccall
Date: Sat Nov  6 04:44:32 2010
New Revision: 118336

URL: http://llvm.org/viewvc/llvm-project?rev=118336&view=rev
Log:
Simplify the logic for emitting guard variables for template static
data members by delaying the emission of the initializer until after
linkage and visibility have been set on the global.  Also, don't
emit a guard unless the variable actually ends up with vague linkage,
and don't use thread-safe statics in any case.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/static-data-member.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sat Nov  6 04:44:32 2010
@@ -468,8 +468,8 @@
   CookieSize = CharUnits::Zero();
 }
 
-void CGCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
-                                   const VarDecl &D,
-                                   llvm::GlobalVariable *GV) {
+void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+                               const VarDecl &D,
+                               llvm::GlobalVariable *GV) {
   ErrorUnsupportedABI(CGF, "static local variable initialization");
 }

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sat Nov  6 04:44:32 2010
@@ -221,11 +221,14 @@
 
   /*************************** Static local guards ****************************/
 
-  /// Emits the initializer and destructor setup for the given static
-  /// local variable, given that it's reachable and couldn't be
-  /// emitted as a constant.
-  virtual void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
-                                   llvm::GlobalVariable *DeclPtr);
+  /// Emits the guarded initializer and destructor setup for the given
+  /// variable, given that it couldn't be emitted as a constant.
+  ///
+  /// The variable may be:
+  ///   - a static local variable
+  ///   - a static data member of a class template instantiation
+  virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+                               llvm::GlobalVariable *DeclPtr);
 
 };
 

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Nov  6 04:44:32 2010
@@ -196,7 +196,7 @@
       // be constant.
       GV->setConstant(false);
 
-      EmitCXXStaticLocalInit(D, GV);
+      EmitCXXGuardedInit(D, GV);
     }
     return GV;
   }

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Sat Nov  6 04:44:32 2010
@@ -140,9 +140,9 @@
   Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
 }
 
-void CodeGenFunction::EmitCXXStaticLocalInit(const VarDecl &D,
-                                             llvm::GlobalVariable *DeclPtr) {
-  CGM.getCXXABI().EmitStaticLocalInit(*this, D, DeclPtr);
+void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
+                                         llvm::GlobalVariable *DeclPtr) {
+  CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
 }
 
 static llvm::Function *
@@ -165,7 +165,8 @@
 }
 
 void
-CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
+CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+                                            llvm::GlobalVariable *Addr) {
   const llvm::FunctionType *FTy
     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                               false);
@@ -174,7 +175,7 @@
   llvm::Function *Fn =
     CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
 
-  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
+  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
 
   if (D->hasAttr<InitPriorityAttr>()) {
     unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
@@ -247,26 +248,20 @@
   AddGlobalDtor(Fn);
 }
 
+/// Emit the code necessary to initialize the given global variable.
 void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
-                                                       const VarDecl *D) {
+                                                       const VarDecl *D,
+                                                 llvm::GlobalVariable *Addr) {
   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
                 SourceLocation());
 
-  llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
-  if (D->isStaticDataMember() &&
-      D->getInstantiatedFromStaticDataMember() && D->getInit()){
-    llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(DeclPtr);
-    assert(GV && "GenerateCXXGlobalVarDeclInitFunc - GV is null");
-    llvm::GlobalValue::LinkageTypes Linkage = 
-      CGM.GetLLVMLinkageVarDefinition(D, GV);
-    if (Linkage == llvm::GlobalVariable::WeakAnyLinkage) {
-      GV->setConstant(false);
-      EmitCXXStaticLocalInit(*D, GV);
-      FinishFunction();
-      return;
-    }
+  // Use guarded initialization if the global variable is weak due to
+  // being a class template's static data member.
+  if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) {
+    EmitCXXGuardedInit(*D, Addr);
+  } else {
+    EmitCXXGlobalVarDeclInit(*D, Addr);
   }
-  EmitCXXGlobalVarDeclInit(*D, DeclPtr);
 
   FinishFunction();
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Nov  6 04:44:32 2010
@@ -1628,7 +1628,12 @@
   void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
                                      llvm::Constant *DeclPtr);
 
-  void EmitCXXStaticLocalInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
+  /// Emit code in this function to perform a guarded variable
+  /// initialization.  Guarded initializations are used when it's not
+  /// possible to prove that an initialization will be done exactly
+  /// once, e.g. with a static local variable or a static data member
+  /// of a class template.
+  void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
 
   /// GenerateCXXGlobalInitFunc - Generates code for initializing global
   /// variables.
@@ -1642,7 +1647,8 @@
                                  const std::vector<std::pair<llvm::WeakVH,
                                    llvm::Constant*> > &DtorsAndObjects);
 
-  void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D);
+  void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D,
+                                        llvm::GlobalVariable *Addr);
 
   void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Nov  6 04:44:32 2010
@@ -1102,7 +1102,6 @@
         T = D->getType();
       
       if (getLangOptions().CPlusPlus) {
-        EmitCXXGlobalVarDeclInitFunc(D);
         Init = EmitNullConstant(T);
         NonConstInit = true;
       } else {
@@ -1184,6 +1183,10 @@
 
   SetCommonAttributes(D, GV);
 
+  // Emit the initializer function if necessary.
+  if (NonConstInit)
+    EmitCXXGlobalVarDeclInitFunc(D, GV);
+
   // Emit global variable debug information.
   if (CGDebugInfo *DI = getDebugInfo()) {
     DI->setLocation(D->getLocation());

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Nov  6 04:44:32 2010
@@ -590,7 +590,8 @@
   /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals.
   void EmitCXXGlobalDtorFunc();
 
-  void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D);
+  void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+                                    llvm::GlobalVariable *Addr);
 
   // FIXME: Hardcoding priority here is gross.
   void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sat Nov  6 04:44:32 2010
@@ -120,8 +120,8 @@
                        QualType ElementType, llvm::Value *&NumElements,
                        llvm::Value *&AllocPtr, CharUnits &CookieSize);
 
-  void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
-                           llvm::GlobalVariable *DeclPtr);
+  void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+                       llvm::GlobalVariable *DeclPtr);
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
@@ -1078,11 +1078,15 @@
 
 /// The ARM code here follows the Itanium code closely enough that we
 /// just special-case it at particular places.
-void ItaniumCXXABI::EmitStaticLocalInit(CodeGenFunction &CGF,
-                                        const VarDecl &D,
-                                        llvm::GlobalVariable *GV) {
+void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+                                    const VarDecl &D,
+                                    llvm::GlobalVariable *GV) {
   CGBuilderTy &Builder = CGF.Builder;
-  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
+
+  // We only need to use thread-safe statics for local variables;
+  // global initialization is always single-threaded.
+  bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics &&
+                            D.isLocalVarDecl());
   
   // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
   const llvm::IntegerType *GuardTy
@@ -1093,16 +1097,10 @@
   llvm::SmallString<256> GuardVName;
   getMangleContext().mangleItaniumGuardVariable(&D, GuardVName);
 
-  // FIXME: we should just absorb linkage and visibility from the
-  // variable, but that's not always set up properly just yet.
-  llvm::GlobalValue::LinkageTypes Linkage = GV->getLinkage();
-  if (D.isStaticDataMember() &&
-      D.getInstantiatedFromStaticDataMember())
-    Linkage = llvm::GlobalVariable::WeakAnyLinkage;
-  
+  // Just absorb linkage and visibility from the variable.
   llvm::GlobalVariable *GuardVariable =
     new llvm::GlobalVariable(CGM.getModule(), GuardTy,
-                             false, Linkage,
+                             false, GV->getLinkage(),
                              llvm::ConstantInt::get(GuardTy, 0),
                              GuardVName.str());
   GuardVariable->setVisibility(GV->getVisibility());

Modified: cfe/trunk/test/CodeGenCXX/static-data-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-data-member.cpp?rev=118336&r1=118335&r2=118336&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-data-member.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-data-member.cpp Sat Nov  6 04:44:32 2010
@@ -1,18 +1,66 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
 
-// CHECK: @_ZN1A1aE = constant i32 10
+// CHECK: @_ZN5test11A1aE = constant i32 10, align 4
+// CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4
+// CHECK: @_ZN5test31AIiE1xE = weak global i32 0, align 4
+// CHECK: @_ZGVN5test31AIiE1xE = weak global i64 0
 
 // PR5564.
-struct A {
-  static const int a = 10;
-};
-
-const int A::a;
-
-struct S { 
-  static int i;
-};
+namespace test1 {
+  struct A {
+    static const int a = 10;
+  };
 
-void f() { 
-  int a = S::i;
+  const int A::a;
+
+  struct S { 
+    static int i;
+  };
+
+  void f() { 
+    int a = S::i;
+  }
+}
+
+// Test that we don't use guards for initializing template static data
+// members with internal linkage.
+namespace test2 {
+  int foo();
+
+  namespace {
+    template <class T> struct A {
+      static int x;
+    };
+
+    template <class T> int A<T>::x = foo();
+    template struct A<int>;
+  }
+
+  // CHECK: define internal void @__cxx_global_var_init()
+  // CHECK:      [[TMP:%.*]] = call i32 @_ZN5test23fooEv()
+  // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test212_GLOBAL__N_11AIiE1xE, align 4
+  // CHECK-NEXT: ret void
+}
+
+// Test that we don't use threadsafe statics when initializing
+// template static data members.
+namespace test3 {
+  int foo();
+
+  template <class T> struct A {
+    static int x;
+  };
+
+  template <class T> int A<T>::x = foo();
+  template struct A<int>;
+
+  // CHECK: define internal void @__cxx_global_var_init1()
+  // CHECK:      [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*)
+  // CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0
+  // CHECK-NEXT: br i1 [[UNINITIALIZED]]
+  // CHECK:      [[TMP:%.*]] = call i32 @_ZN5test33fooEv()
+  // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test31AIiE1xE, align 4
+  // CHECK-NEXT: store i64 1, i64* @_ZGVN5test31AIiE1xE
+  // CHECK-NEXT: br label
+  // CHECK:      ret void
 }





More information about the cfe-commits mailing list