[cfe-commits] r103892 - in /cfe/trunk: lib/CodeGen/CGDeclCXX.cpp lib/CodeGen/CGException.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/threadsafe-statics-exceptions.cpp

Douglas Gregor dgregor at apple.com
Sat May 15 18:24:13 PDT 2010


Author: dgregor
Date: Sat May 15 20:24:12 2010
New Revision: 103892

URL: http://llvm.org/viewvc/llvm-project?rev=103892&view=rev
Log:
When initializing thread-safe statics, put the call to
__cxa_guard_abort along the exceptional edge into (in effect) a nested
"try" that rethrows after aborting. Fixes PR7144 and the remaining
Boost.ProgramOptions failures, along with the regressions that r103880
caused.

The crucial difference between this and r103880 is that we now follow
LLVM's little dance with the llvm.eh.exception and llvm.eh.selector
calls, then use _Unwind_Resume_or_Rethrow to rethrow.

Added:
    cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
      - copied, changed from r103889, cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/lib/CodeGen/CGException.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=103892&r1=103891&r2=103892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Sat May 15 20:24:12 2010
@@ -13,6 +13,8 @@
 
 #include "CodeGenFunction.h"
 #include "clang/CodeGen/CodeGenOptions.h"
+#include "llvm/Intrinsics.h"
+
 using namespace clang;
 using namespace CodeGen;
 
@@ -321,7 +323,10 @@
 
   EmitBlock(InitCheckBlock);
 
-  if (ThreadsafeStatics) {
+  // Variables used when coping with thread-safe statics and exceptions.
+  llvm::BasicBlock *SavedLandingPad = 0;
+  llvm::BasicBlock *LandingPad = 0;
+  if (ThreadsafeStatics) {    
     // Call __cxa_guard_acquire.
     V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
                
@@ -330,14 +335,13 @@
     Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
                          InitBlock, EndBlock);
   
-    EmitBlock(InitBlock);
-
     if (Exceptions) {
-      EHCleanupBlock Cleanup(*this);
-    
-      // Call __cxa_guard_abort.
-      Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
+      SavedLandingPad = getInvokeDest();
+      LandingPad = createBasicBlock("guard.lpad");
+      setInvokeDest(LandingPad);
     }
+    
+    EmitBlock(InitBlock);
   }
 
   if (D.getType()->isReferenceType()) {
@@ -353,7 +357,7 @@
 
   if (ThreadsafeStatics) {
     // Call __cxa_guard_release.
-    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
+    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);    
   } else {
     llvm::Value *One = 
       llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
@@ -364,5 +368,57 @@
   if (!D.getType()->isReferenceType())
     EmitDeclDestroy(*this, D, GV);
   
+  if (ThreadsafeStatics && Exceptions) {
+    // If an exception is thrown during initialization, call __cxa_guard_abort
+    // along the exceptional edge.
+    EmitBranch(EndBlock);
+    
+    // Construct the landing pad.
+    EmitBlock(LandingPad);
+        
+    // Personality function and LLVM intrinsics.
+    llvm::Constant *Personality =
+      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
+                                                        (VMContext),
+                                                        true),
+                                "__gxx_personality_v0");
+    Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
+    llvm::Value *llvm_eh_exception =
+      CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
+    llvm::Value *llvm_eh_selector =
+      CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
+    
+    // Exception object
+    llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
+    llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
+
+    // Call the selector function.
+    const llvm::PointerType *PtrToInt8Ty 
+      = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
+    llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
+    llvm::Value* SelectorArgs[3] = { Exc, Personality, Null };
+    Builder.CreateCall(llvm_eh_selector, SelectorArgs, SelectorArgs + 3,
+                           "selector");
+    Builder.CreateStore(Exc, RethrowPtr);
+                                
+    // Call __cxa_guard_abort along the exceptional edge.
+    Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
+
+    setInvokeDest(SavedLandingPad);
+
+    // Rethrow the current exception.
+    if (getInvokeDest()) {
+      llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
+      Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont,
+                           getInvokeDest(),
+                           Builder.CreateLoad(RethrowPtr));
+      EmitBlock(Cont);
+    } else
+      Builder.CreateCall(getUnwindResumeOrRethrowFn(),
+                         Builder.CreateLoad(RethrowPtr));
+    
+    Builder.CreateUnreachable();    
+  }    
+  
   EmitBlock(EndBlock);
 }

Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=103892&r1=103891&r2=103892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Sat May 15 20:24:12 2010
@@ -100,17 +100,17 @@
   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
 }
 
-static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) {
-  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
   std::vector<const llvm::Type*> Args(1, Int8PtrTy);
 
   const llvm::FunctionType *FTy =
-    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args,
+    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args,
                             false);
 
-  if (CGF.CGM.getLangOptions().SjLjExceptions)
-    return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
-  return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
+  if (CGM.getLangOptions().SjLjExceptions)
+    return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
+  return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
 }
 
 static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
@@ -397,7 +397,7 @@
 
   if (Proto->getNumExceptions()) {
     EmitBlock(Unwind);
-    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
+    Builder.CreateCall(getUnwindResumeOrRethrowFn(),
                        Builder.CreateLoad(RethrowPtr));
     Builder.CreateUnreachable();
   }
@@ -631,12 +631,12 @@
   // here.
   if (getInvokeDest()) {
     llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
-    Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont,
+    Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont,
                          getInvokeDest(),
                          Builder.CreateLoad(RethrowPtr));
     EmitBlock(Cont);
   } else
-    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
+    Builder.CreateCall(getUnwindResumeOrRethrowFn(),
                        Builder.CreateLoad(RethrowPtr));
 
   Builder.CreateUnreachable();
@@ -687,11 +687,11 @@
   // Rethrow the exception.
   if (CGF.getInvokeDest()) {
     llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
-    CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont,
+    CGF.Builder.CreateInvoke(CGF.getUnwindResumeOrRethrowFn(), Cont,
                              CGF.getInvokeDest(), Exc);
     CGF.EmitBlock(Cont);
   } else
-    CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc);
+    CGF.Builder.CreateCall(CGF.getUnwindResumeOrRethrowFn(), Exc);
   CGF.Builder.CreateUnreachable();
 
   // Resume inserting where we started, but put the new cleanup

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=103892&r1=103891&r2=103892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat May 15 20:24:12 2010
@@ -929,6 +929,7 @@
   void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
   void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
 
+  llvm::Constant *getUnwindResumeOrRethrowFn();
   struct CXXTryStmtInfo {
     llvm::BasicBlock *SavedLandingPad;
     llvm::BasicBlock *HandlerBlock;

Copied: cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp (from r103889, cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp?p2=cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp&p1=cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp&r1=103889&r2=103892&rev=103892&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/threadsafe-statics-exceptions.cpp Sat May 15 20:24:12 2010
@@ -15,8 +15,10 @@
   // CHECK: call i32 @__cxa_atexit
   // CHECK: br
   static X x;
+  // CHECK: call i8* @llvm.eh.exception()
+  // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector
   // CHECK: call void @__cxa_guard_abort(i64* @_ZGVZ1fvE1x)
-  // CHECK: call void @__cxa_rethrow() noreturn
+  // CHECK: call void @_Unwind_Resume_or_Rethrow
   // CHECK: unreachable
 
   // CHECK: call i8* @__cxa_allocate_exception





More information about the cfe-commits mailing list