Switch finally cleanups over to being lazy cleanups. We get basically nothing

from the laziness features here except better block ordering, but it removes yet
another CleanupBlock use.

llvm-svn: 108990
This commit is contained in:
John McCall 2010-07-21 05:47:49 +00:00
parent f99a631e4e
commit 906da4bb52
2 changed files with 70 additions and 46 deletions

View File

@ -1357,6 +1357,65 @@ namespace {
CGF.EmitBlock(CleanupContBB);
}
};
struct PerformFinally : EHScopeStack::LazyCleanup {
const Stmt *Body;
llvm::Value *ForEHVar;
llvm::Value *EndCatchFn;
llvm::Value *RethrowFn;
llvm::Value *SavedExnVar;
PerformFinally(const Stmt *Body, llvm::Value *ForEHVar,
llvm::Value *EndCatchFn,
llvm::Value *RethrowFn, llvm::Value *SavedExnVar)
: Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn),
RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
// Enter a cleanup to call the end-catch function if one was provided.
if (EndCatchFn)
CGF.EHStack.pushLazyCleanup<CallEndCatchForFinally>(NormalAndEHCleanup,
ForEHVar, EndCatchFn);
// Emit the finally block.
CGF.EmitStmt(Body);
// If the end of the finally is reachable, check whether this was
// for EH. If so, rethrow.
if (CGF.HaveInsertPoint()) {
llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow");
llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");
llvm::Value *ShouldRethrow =
CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
CGF.EmitBlock(RethrowBB);
if (SavedExnVar) {
llvm::Value *Args[] = { CGF.Builder.CreateLoad(SavedExnVar) };
CGF.EmitCallOrInvoke(RethrowFn, Args, Args+1);
} else {
CGF.EmitCallOrInvoke(RethrowFn, 0, 0);
}
CGF.Builder.CreateUnreachable();
CGF.EmitBlock(ContBB);
}
// Leave the end-catch cleanup. As an optimization, pretend that
// the fallthrough path was inaccessible; we've dynamically proven
// that we're not in the EH case along that path.
if (EndCatchFn) {
CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
CGF.PopCleanupBlock();
CGF.Builder.restoreIP(SavedIP);
}
// Now make sure we actually have an insertion point or the
// cleanup gods will hate us.
CGF.EnsureInsertPoint();
}
};
}
/// Enters a finally block for an implementation using zero-cost
@ -1410,52 +1469,9 @@ CodeGenFunction::EnterFinallyBlock(const Stmt *Body,
InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext()));
// Enter a normal cleanup which will perform the @finally block.
{
CodeGenFunction::CleanupBlock Cleanup(*this, NormalCleanup);
// Enter a cleanup to call the end-catch function if one was provided.
if (EndCatchFn)
EHStack.pushLazyCleanup<CallEndCatchForFinally>(NormalAndEHCleanup,
ForEHVar, EndCatchFn);
// Emit the finally block.
EmitStmt(Body);
// If the end of the finally is reachable, check whether this was
// for EH. If so, rethrow.
if (HaveInsertPoint()) {
llvm::BasicBlock *RethrowBB = createBasicBlock("finally.rethrow");
llvm::BasicBlock *ContBB = createBasicBlock("finally.cont");
llvm::Value *ShouldRethrow =
Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
EmitBlock(RethrowBB);
if (SavedExnVar) {
llvm::Value *Args[] = { Builder.CreateLoad(SavedExnVar) };
EmitCallOrInvoke(RethrowFn, Args, Args+1);
} else {
EmitCallOrInvoke(RethrowFn, 0, 0);
}
Builder.CreateUnreachable();
EmitBlock(ContBB);
}
// Leave the end-catch cleanup. As an optimization, pretend that
// the fallthrough path was inaccessible; we've dynamically proven
// that we're not in the EH case along that path.
if (EndCatchFn) {
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
PopCleanupBlock();
Builder.restoreIP(SavedIP);
}
// Now make sure we actually have an insertion point or the
// cleanup gods will hate us.
EnsureInsertPoint();
}
EHStack.pushLazyCleanup<PerformFinally>(NormalCleanup, Body,
ForEHVar, EndCatchFn,
RethrowFn, SavedExnVar);
// Enter a catch-all scope.
llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall");

View File

@ -255,6 +255,14 @@ public:
(void) Obj;
}
/// Push a lazily-created cleanup on the stack.
template <class T, class A0, class A1, class A2, class A3, class A4>
void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
void *Buffer = pushLazyCleanup(Kind, sizeof(T));
LazyCleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
(void) Obj;
}
/// Push a cleanup on the stack.
void pushCleanup(llvm::BasicBlock *NormalEntry,
llvm::BasicBlock *NormalExit,