Switch the __cxa_free_exception cleanup to be lazy.

llvm-svn: 108276
This commit is contained in:
John McCall 2010-07-13 21:17:51 +00:00
parent a3f1901531
commit bb0260139a
2 changed files with 32 additions and 19 deletions

View File

@ -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);

View File

@ -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]]