[cfe-commits] r113330 - 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/ItaniumCXXABI.cpp lib/CodeGen/Mangle.cpp lib/CodeGen/Mangle.h lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/arm.cpp test/CodeGenCXX/static-init.cpp test/CodeGenCXX/threadsafe-statics-exceptions.cpp

John McCall rjmccall at apple.com
Tue Sep 7 18:44:27 PDT 2010


Author: rjmccall
Date: Tue Sep  7 20:44:27 2010
New Revision: 113330

URL: http://llvm.org/viewvc/llvm-project?rev=113330&view=rev
Log:
Implement ARM static local initialization guards, which are more compact than
Itanium guards and use a slightly different compiled-in API.


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/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/Mangle.cpp
    cfe/trunk/lib/CodeGen/Mangle.h
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/arm.cpp
    cfe/trunk/test/CodeGenCXX/static-init.cpp
    cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Sep  7 20:44:27 2010
@@ -321,7 +321,7 @@
 /// Implementation for CGCXXABI.  Possibly this should be moved into
 /// the incomplete ABI implementations?
 
-CGCXXABI::~CGCXXABI() {}
+void CGCXXABI::_anchor() {}
 
 static void ErrorUnsupportedABI(CodeGenFunction &CGF,
                                 llvm::StringRef S) {
@@ -469,3 +469,9 @@
   AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
   CookieSize = CharUnits::Zero();
 }
+
+void CGCXXABI::EmitStaticLocalInit(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=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Sep  7 20:44:27 2010
@@ -69,9 +69,11 @@
 
   ASTContext &getContext() const { return CGM.getContext(); }
 
+  virtual void _anchor();
+
 public:
 
-  virtual ~CGCXXABI();
+  virtual ~CGCXXABI() {}
 
   /// Gets the mangle context.
   virtual MangleContext &getMangleContext() = 0;
@@ -217,6 +219,14 @@
                                QualType ElementType, llvm::Value *&NumElements,
                                llvm::Value *&AllocPtr, CharUnits &CookieSize);
 
+  /*************************** 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);
+
 };
 
 /// Creates an instance of a C++ ABI class.

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Sep  7 20:44:27 2010
@@ -189,12 +189,12 @@
   if (!Init) {
     if (!getContext().getLangOptions().CPlusPlus)
       CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
-    else {
+    else if (Builder.GetInsertBlock()) {
       // Since we have a static initializer, this global variable can't 
       // be constant.
       GV->setConstant(false);
-      
-      EmitStaticCXXBlockVarDeclInit(D, GV);
+
+      EmitCXXStaticLocalInit(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=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Tue Sep  7 20:44:27 2010
@@ -42,6 +42,8 @@
   }
 }
 
+/// Emit code to cause the destruction of the given variable with
+/// static storage duration.
 static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                             llvm::Constant *DeclPtr) {
   CodeGenModule &CGM = CGF.CGM;
@@ -138,6 +140,11 @@
   Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
 }
 
+void CodeGenFunction::EmitCXXStaticLocalInit(const VarDecl &D,
+                                             llvm::GlobalVariable *DeclPtr) {
+  CGM.getCXXABI().EmitStaticLocalInit(*this, D, DeclPtr);
+}
+
 static llvm::Function *
 CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
                                    const llvm::FunctionType *FTy,
@@ -283,143 +290,6 @@
   FinishFunction();
 }
 
-static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
-  // int __cxa_guard_acquire(__int64_t *guard_object);
-  
-  const llvm::Type *Int64PtrTy = 
-    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
-  
-  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
-  
-  const llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
-                            Args, /*isVarArg=*/false);
-  
-  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
-}
-
-static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
-  // void __cxa_guard_release(__int64_t *guard_object);
-  
-  const llvm::Type *Int64PtrTy = 
-    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
-  
-  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
-  
-  const llvm::FunctionType *FTy =
-  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
-                          Args, /*isVarArg=*/false);
-  
-  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
-}
-
-static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
-  // void __cxa_guard_abort(__int64_t *guard_object);
-  
-  const llvm::Type *Int64PtrTy = 
-    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
-  
-  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
-  
-  const llvm::FunctionType *FTy =
-  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
-                          Args, /*isVarArg=*/false);
-  
-  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
-}
-
-namespace {
-  struct CallGuardAbort : EHScopeStack::Cleanup {
-    llvm::GlobalVariable *Guard;
-    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      // It shouldn't be possible for this to throw, but if it can,
-      // this should allow for the possibility of an invoke.
-      CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard)
-        ->setDoesNotThrow();
-    }
-  };
-}
-
-void
-CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
-                                               llvm::GlobalVariable *GV) {
-  // Bail out early if this initializer isn't reachable.
-  if (!Builder.GetInsertBlock()) return;
-
-  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
-  
-  llvm::SmallString<256> GuardVName;
-  CGM.getCXXABI().getMangleContext().mangleGuardVariable(&D, GuardVName);
-
-  // Create the guard variable.
-  llvm::GlobalVariable *GuardVariable =
-    new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
-                             false, GV->getLinkage(),
-                             llvm::Constant::getNullValue(Int64Ty),
-                             GuardVName.str());
-
-  // Load the first byte of the guard variable.
-  const llvm::Type *PtrTy
-    = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
-  llvm::Value *V = 
-    Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
-
-  llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
-  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
-
-  // Check if the first byte of the guard variable is zero.
-  Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), 
-                       InitCheckBlock, EndBlock);
-
-  EmitBlock(InitCheckBlock);
-
-  // Variables used when coping with thread-safe statics and exceptions.
-  if (ThreadsafeStatics) {    
-    // Call __cxa_guard_acquire.
-    V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
-               
-    llvm::BasicBlock *InitBlock = createBasicBlock("init");
-  
-    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
-                         InitBlock, EndBlock);
-  
-    // Call __cxa_guard_abort along the exceptional edge.
-    if (Exceptions)
-      EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
-    
-    EmitBlock(InitBlock);
-  }
-
-  if (D.getType()->isReferenceType()) {
-    unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
-    QualType T = D.getType();
-    RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
-    EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T);
-  } else
-    EmitDeclInit(*this, D, GV);
-
-  if (ThreadsafeStatics) {
-    // Pop the guard-abort cleanup if we pushed one.
-    if (Exceptions)
-      PopCleanupBlock();
-
-    // Call __cxa_guard_release.  This cannot throw.
-    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);    
-  } else {
-    llvm::Value *One = 
-      llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
-    Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
-  }
-
-  // Register the call to the destructor.
-  if (!D.getType()->isReferenceType())
-    EmitDeclDestroy(*this, D, GV);
-  
-  EmitBlock(EndBlock);
-}
-
 /// GenerateCXXAggrDestructorHelper - Generates a helper function which when
 /// invoked, calls the default destructor on array elements in reverse order of
 /// construction.

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Sep  7 20:44:27 2010
@@ -1565,11 +1565,6 @@
                                      llvm::GlobalVariable *GV);
   
 
-  /// EmitStaticCXXBlockVarDeclInit - Create the initializer for a C++ runtime
-  /// initialized static block var decl.
-  void EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
-                                     llvm::GlobalVariable *GV);
-
   /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
   /// variable with global storage.
   void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr);
@@ -1579,6 +1574,8 @@
   void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
                                      llvm::Constant *DeclPtr);
 
+  void EmitCXXStaticLocalInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
+
   /// GenerateCXXGlobalInitFunc - Generates code for initializing global
   /// variables.
   void GenerateCXXGlobalInitFunc(llvm::Function *Fn,

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Sep  7 20:44:27 2010
@@ -119,6 +119,9 @@
   void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
                        QualType ElementType, llvm::Value *&NumElements,
                        llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+  void EmitStaticLocalInit(CodeGenFunction &CGF, const VarDecl &D,
+                           llvm::GlobalVariable *DeclPtr);
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
@@ -1021,3 +1024,159 @@
   NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
 }
 
+/*********************** Static local initialization **************************/
+
+static llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM,
+                                         const llvm::PointerType *GuardPtrTy) {
+  // int __cxa_guard_acquire(__guard *guard_object);
+  
+  std::vector<const llvm::Type*> Args(1, GuardPtrTy);  
+  const llvm::FunctionType *FTy =
+    llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
+                            Args, /*isVarArg=*/false);
+  
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
+}
+
+static llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM,
+                                         const llvm::PointerType *GuardPtrTy) {
+  // void __cxa_guard_release(__guard *guard_object);
+  
+  std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+  
+  const llvm::FunctionType *FTy =
+    llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+                            Args, /*isVarArg=*/false);
+  
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
+}
+
+static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
+                                       const llvm::PointerType *GuardPtrTy) {
+  // void __cxa_guard_abort(__guard *guard_object);
+  
+  std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+  
+  const llvm::FunctionType *FTy =
+    llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+                            Args, /*isVarArg=*/false);
+  
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
+}
+
+namespace {
+  struct CallGuardAbort : EHScopeStack::Cleanup {
+    llvm::GlobalVariable *Guard;
+    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+
+    void Emit(CodeGenFunction &CGF, bool IsForEH) {
+      CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard)
+        ->setDoesNotThrow();
+    }
+  };
+}
+
+/// 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) {
+  CGBuilderTy &Builder = CGF.Builder;
+  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
+  
+  // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
+  const llvm::IntegerType *GuardTy
+    = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty());
+  const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
+
+  // Create the guard variable.
+  llvm::SmallString<256> GuardVName;
+  getMangleContext().mangleItaniumGuardVariable(&D, GuardVName);
+  llvm::GlobalVariable *GuardVariable =
+    new llvm::GlobalVariable(CGM.getModule(), GuardTy,
+                             false, GV->getLinkage(),
+                             llvm::ConstantInt::get(GuardTy, 0),
+                             GuardVName.str());
+
+  // Test whether the variable has completed initialization.
+  llvm::Value *IsInitialized;
+
+  // ARM C++ ABI 3.2.3.1:
+  //   To support the potential use of initialization guard variables
+  //   as semaphores that are the target of ARM SWP and LDREX/STREX
+  //   synchronizing instructions we define a static initialization
+  //   guard variable to be a 4-byte aligned, 4- byte word with the
+  //   following inline access protocol.
+  //     #define INITIALIZED 1
+  //     if ((obj_guard & INITIALIZED) != INITIALIZED) {
+  //       if (__cxa_guard_acquire(&obj_guard))
+  //         ...
+  //     }
+  if (IsARM) {
+    llvm::Value *V = Builder.CreateLoad(GuardVariable);
+    V = Builder.CreateAnd(V, Builder.getInt32(1));
+    IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+
+  // Itanium C++ ABI 3.3.2:
+  //   The following is pseudo-code showing how these functions can be used:
+  //     if (obj_guard.first_byte == 0) {
+  //       if ( __cxa_guard_acquire (&obj_guard) ) {
+  //         try {
+  //           ... initialize the object ...;
+  //         } catch (...) {
+  //            __cxa_guard_abort (&obj_guard);
+  //            throw;
+  //         }
+  //         ... queue object destructor with __cxa_atexit() ...;
+  //         __cxa_guard_release (&obj_guard);
+  //       }
+  //     }
+  } else {
+    // Load the first byte of the guard variable.
+    const llvm::Type *PtrTy = Builder.getInt8PtrTy();
+    llvm::Value *V = 
+      Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
+
+    IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+  }
+
+  llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
+  llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+
+  // Check if the first byte of the guard variable is zero.
+  Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+
+  CGF.EmitBlock(InitCheckBlock);
+
+  // Variables used when coping with thread-safe statics and exceptions.
+  if (ThreadsafeStatics) {    
+    // Call __cxa_guard_acquire.
+    llvm::Value *V
+      = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
+               
+    llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+  
+    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
+                         InitBlock, EndBlock);
+  
+    // Call __cxa_guard_abort along the exceptional edge.
+    CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
+    
+    CGF.EmitBlock(InitBlock);
+  }
+
+  // Emit the initializer and add a global destructor if appropriate.
+  CGF.EmitCXXGlobalVarDeclInit(D, GV);
+
+  if (ThreadsafeStatics) {
+    // Pop the guard-abort cleanup if we pushed one.
+    CGF.PopCleanupBlock();
+
+    // Call __cxa_guard_release.  This cannot throw.
+    Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable);
+  } else {
+    Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
+  }
+
+  CGF.EmitBlock(EndBlock);
+}

Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Tue Sep  7 20:44:27 2010
@@ -2451,8 +2451,8 @@
 
 /// mangleGuardVariable - Returns the mangled name for a guard variable
 /// for the passed in VarDecl.
-void MangleContext::mangleGuardVariable(const VarDecl *D,
-                                        llvm::SmallVectorImpl<char> &Res) {
+void MangleContext::mangleItaniumGuardVariable(const VarDecl *D,
+                                         llvm::SmallVectorImpl<char> &Res) {
   //  <special-name> ::= GV <object name>       # Guard variable for one-time
   //                                            # initialization
   CXXNameMangler Mangler(*this, Res);

Modified: cfe/trunk/lib/CodeGen/Mangle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.h?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.h (original)
+++ cfe/trunk/lib/CodeGen/Mangle.h Tue Sep  7 20:44:27 2010
@@ -119,8 +119,6 @@
   virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
                                   const ThisAdjustment &ThisAdjustment,
                                   llvm::SmallVectorImpl<char> &);
-  virtual void mangleGuardVariable(const VarDecl *D,
-                                   llvm::SmallVectorImpl<char> &);
   virtual void mangleReferenceTemporary(const VarDecl *D,
                                         llvm::SmallVectorImpl<char> &);
   virtual void mangleCXXVTable(const CXXRecordDecl *RD,
@@ -139,6 +137,10 @@
   void mangleBlock(GlobalDecl GD,
                    const BlockDecl *BD, llvm::SmallVectorImpl<char> &);
 
+  // This is pretty lame.
+  void mangleItaniumGuardVariable(const VarDecl *D,
+                                  llvm::SmallVectorImpl<char> &);
+
   void mangleInitDiscriminator() {
     Discriminator = 0;
   }

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Sep  7 20:44:27 2010
@@ -91,8 +91,6 @@
   virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
                                   const ThisAdjustment &ThisAdjustment,
                                   llvm::SmallVectorImpl<char> &);
-  virtual void mangleGuardVariable(const VarDecl *D,
-                                   llvm::SmallVectorImpl<char> &);
   virtual void mangleCXXVTable(const CXXRecordDecl *RD,
                                llvm::SmallVectorImpl<char> &);
   virtual void mangleCXXVTT(const CXXRecordDecl *RD,
@@ -1175,10 +1173,6 @@
                                                 llvm::SmallVectorImpl<char> &) {
   assert(false && "Can't yet mangle destructor thunks!");
 }
-void MicrosoftMangleContext::mangleGuardVariable(const VarDecl *D,
-                                                 llvm::SmallVectorImpl<char> &) {
-  assert(false && "Can't yet mangle guard variables!");
-}
 void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
                                              llvm::SmallVectorImpl<char> &) {
   assert(false && "Can't yet mangle virtual tables!");

Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Tue Sep  7 20:44:27 2010
@@ -1,5 +1,10 @@
 // RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
 
+// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4
+// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0
+// CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 1
+// CHECK: @_ZGVZN5test84testEvE1x = internal global i32 0
+
 typedef typeof(sizeof(int)) size_t;
 
 class foo {
@@ -277,6 +282,76 @@
   }
 }
 
+namespace test7 {
+  int foo();
+
+  // Static and guard tested at top of file
+
+  // CHECK: define void @_ZN5test74testEv()
+  void test() {
+    // CHECK:      [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x
+    // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
+    // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+    // CHECK-NEXT: br i1 [[T2]]
+    //   -> fallthrough, end
+    // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x)
+    // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
+    // CHECK-NEXT: br i1 [[T4]]
+    //   -> fallthrough, end
+    // CHECK:      [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv()
+    // CHECK:      store i32 [[INIT]], i32* @_ZZN5test74testEvE1x, align 4
+    // CHECK-NEXT: call void @__cxa_guard_release(i32* @_ZGVZN5test74testEvE1x)
+    // CHECK-NEXT: br label
+    //   -> end
+    // end:
+    // CHECK:      ret void
+    static int x = foo();
+
+    // CHECK:      call i8* @llvm.eh.exception()
+    // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x)
+    // CHECK:      call void @_Unwind_Resume_or_Rethrow
+  }
+}
+
+namespace test8 {
+  struct A {
+    A();
+    ~A();
+  };
+
+  // Static and guard tested at top of file
+
+  // CHECK: define void @_ZN5test84testEv()
+  void test() {
+    // CHECK:      [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x
+    // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
+    // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+    // CHECK-NEXT: br i1 [[T2]]
+    //   -> fallthrough, end
+    // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x)
+    // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
+    // CHECK-NEXT: br i1 [[T4]]
+    //   -> fallthrough, end
+    // CHECK:      [[INIT:%.*]] = invoke [[TEST8A]]* @_ZN5test81AC1Ev([[TEST8A]]* @_ZZN5test84testEvE1x)
+
+    // FIXME: Here we register a global destructor that
+    // unconditionally calls the destructor.  That's what we've always
+    // done for -fno-use-cxa-atexit here, but that's really not
+    // semantically correct at all.
+
+    // CHECK:      call void @__cxa_guard_release(i32* @_ZGVZN5test84testEvE1x)
+    // CHECK-NEXT: br label
+    //   -> end
+    // end:
+    // CHECK:      ret void
+    static A x;
+
+    // CHECK:      call i8* @llvm.eh.exception()
+    // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x)
+    // CHECK:      call void @_Unwind_Resume_or_Rethrow
+  }
+}
+
   // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
   // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
   // CHECK:   ret [[C]]* undef

Modified: cfe/trunk/test/CodeGenCXX/static-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-init.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-init.cpp Tue Sep  7 20:44:27 2010
@@ -14,8 +14,8 @@
 void f() {
   // CHECK: call i32 @__cxa_guard_acquire
   // CHECK: call void @_ZN1AC1Ev
-  // CHECK: call void @__cxa_guard_release
   // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
+  // CHECK: call void @__cxa_guard_release
   static A a;
 }
 

Modified: cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp?rev=113330&r1=113329&r2=113330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp Tue Sep  7 20:44:27 2010
@@ -11,8 +11,8 @@
 void f() {
   // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ1fvE1x)
   // CHECK: invoke void @_ZN1XC1Ev
-  // CHECK: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x)
-  // CHECK-NEXT: call i32 @__cxa_atexit
+  // CHECK: call i32 @__cxa_atexit
+  // CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x)
   // CHECK: br
   static X x;
 





More information about the cfe-commits mailing list