forked from OSchip/llvm-project
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:
parent
f99a631e4e
commit
906da4bb52
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue