diff options
author | John McCall <rjmccall@apple.com> | 2010-07-13 21:17:51 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-07-13 21:17:51 +0000 |
commit | 09faeabf39a6fab2e2beb6bf03da970c17d2049a (patch) | |
tree | ea860d2d4169efb4291ee7c37ac90ab2be7b7480 | |
parent | 55a17c057c5293e517609a91438342737ef51545 (diff) |
Switch the __cxa_free_exception cleanup to be lazy.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108276 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGException.cpp | 48 | ||||
-rw-r--r-- | test/CodeGenCXX/eh.cpp | 3 |
2 files changed, 32 insertions, 19 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index b10e5ae6f6..d3949baf3a 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -400,6 +400,33 @@ static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) { return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); } +namespace { + /// A cleanup to free the exception object if its initialization + /// throws. + struct FreeExceptionCleanup : EHScopeStack::LazyCleanup { + FreeExceptionCleanup(llvm::Value *ShouldFreeVar, + llvm::Value *ExnLocVar) + : ShouldFreeVar(ShouldFreeVar), ExnLocVar(ExnLocVar) {} + + llvm::Value *ShouldFreeVar; + llvm::Value *ExnLocVar; + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj"); + llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done"); + + llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar, + "should-free-exnobj"); + CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB); + CGF.EmitBlock(FreeBB); + llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj"); + CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal) + ->setDoesNotThrow(); + CGF.EmitBlock(DoneBB); + } + }; +} + // Emits an exception expression into the given location. This // differs from EmitAnyExprToMem only in that, if a final copy-ctor // call is required, an exception within that copy ctor causes @@ -424,22 +451,11 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E, // Make sure the exception object is cleaned up if there's an // exception during initialization. - // FIXME: StmtExprs probably force this to include a non-EH - // handler. - { - CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup); - llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj"); - llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done"); - - llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar, - "should-free-exnobj"); - CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB); - CGF.EmitBlock(FreeBB); - llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj"); - CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal) - ->setDoesNotThrow(); - CGF.EmitBlock(DoneBB); - } + // FIXME: stmt expressions might require this to be a normal + // cleanup, too. + CGF.EHStack.pushLazyCleanup<FreeExceptionCleanup>(EHCleanup, + ShouldFreeVar, + ExnLocVar); EHScopeStack::stable_iterator Cleanup = CGF.EHStack.stable_begin(); CGF.Builder.CreateStore(ExnLoc, ExnLocVar); diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index d03dc91715..f8d7ef69e0 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -136,9 +136,6 @@ namespace test7 { // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXNALLOC]], i8* bitcast (i8** @_ZTIi to i8*), i8* null throw 1; } -// This cleanup ends up here for no good reason. It's actually unused. -// CHECK: load i8** [[EXNALLOCVAR]] -// CHECK-NEXT: call void @__cxa_free_exception( // CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] |