diff options
Diffstat (limited to 'lib/CodeGen/CGException.cpp')
-rw-r--r-- | lib/CodeGen/CGException.cpp | 125 |
1 files changed, 68 insertions, 57 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 1f00914ea4..d31cab5194 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -98,6 +98,11 @@ void EHScopeStack::popCleanup() { InnermostEHCleanup = Cleanup.getEnclosingEHCleanup(); StartOfData += Cleanup.getAllocatedSize(); + if (empty()) NextEHDestIndex = FirstEHDestIndex; + + // Destroy the cleanup. + Cleanup.~EHCleanupScope(); + // Check whether we can shrink the branch-fixups stack. if (!BranchFixups.empty()) { // If we no longer have any normal cleanups, all the fixups are @@ -123,6 +128,8 @@ void EHScopeStack::popFilter() { EHFilterScope &Filter = cast<EHFilterScope>(*begin()); StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters()); + if (empty()) NextEHDestIndex = FirstEHDestIndex; + assert(CatchDepth > 0 && "mismatched filter push/pop"); CatchDepth--; } @@ -130,13 +137,16 @@ void EHScopeStack::popFilter() { EHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) { char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers)); CatchDepth++; - return new (Buffer) EHCatchScope(NumHandlers); + EHCatchScope *Scope = new (Buffer) EHCatchScope(NumHandlers); + for (unsigned I = 0; I != NumHandlers; ++I) + Scope->getHandlers()[I].Index = getNextEHDestIndex(); + return Scope; } void EHScopeStack::pushTerminate() { char *Buffer = allocate(EHTerminateScope::getSize()); CatchDepth++; - new (Buffer) EHTerminateScope(); + new (Buffer) EHTerminateScope(getNextEHDestIndex()); } /// Remove any 'null' fixups on the stack. However, we can't pop more @@ -158,20 +168,6 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -void EHScopeStack::resolveBranchFixups(llvm::BasicBlock *Dest) { - assert(Dest && "null block passed to resolveBranchFixups"); - - if (BranchFixups.empty()) return; - assert(hasNormalCleanups() && - "branch fixups exist with no normal cleanups on stack"); - - for (unsigned I = 0, E = BranchFixups.size(); I != E; ++I) - if (BranchFixups[I].Destination == Dest) - BranchFixups[I].Destination = 0; - - popNullFixups(); -} - static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { // void *__cxa_allocate_exception(size_t thrown_size); const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); @@ -756,8 +752,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { EHSelector.push_back(getPersonalityFn(*this, Personality)); // Accumulate all the handlers in scope. - llvm::DenseMap<llvm::Value*, JumpDest> EHHandlers; - JumpDest CatchAll; + llvm::DenseMap<llvm::Value*, UnwindDest> EHHandlers; + UnwindDest CatchAll; bool HasEHCleanup = false; bool HasEHFilter = false; llvm::SmallVector<llvm::Value*, 8> EHFilters; @@ -773,7 +769,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { case EHScope::Filter: { assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); - assert(!CatchAll.Block && "EH filter reached after catch-all"); + assert(!CatchAll.isValid() && "EH filter reached after catch-all"); // Filter scopes get added to the selector in wierd ways. EHFilterScope &Filter = cast<EHFilterScope>(*I); @@ -791,9 +787,10 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { case EHScope::Terminate: // Terminate scopes are basically catch-alls. - assert(!CatchAll.Block); - CatchAll.Block = getTerminateHandler(); - CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I); + assert(!CatchAll.isValid()); + CatchAll = UnwindDest(getTerminateHandler(), + EHStack.getEnclosingEHCleanup(I), + cast<EHTerminateScope>(*I).getDestIndex()); goto done; case EHScope::Catch: @@ -806,30 +803,32 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // Catch-all. We should only have one of these per catch. if (!Handler.Type) { - assert(!CatchAll.Block); - CatchAll.Block = Handler.Block; - CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I); + assert(!CatchAll.isValid()); + CatchAll = UnwindDest(Handler.Block, + EHStack.getEnclosingEHCleanup(I), + Handler.Index); continue; } // Check whether we already have a handler for this type. - JumpDest &Dest = EHHandlers[Handler.Type]; - if (Dest.Block) continue; + UnwindDest &Dest = EHHandlers[Handler.Type]; + if (Dest.isValid()) continue; EHSelector.push_back(Handler.Type); - Dest.Block = Handler.Block; - Dest.ScopeDepth = EHStack.getEnclosingEHCleanup(I); + Dest = UnwindDest(Handler.Block, + EHStack.getEnclosingEHCleanup(I), + Handler.Index); } // Stop if we found a catch-all. - if (CatchAll.Block) break; + if (CatchAll.isValid()) break; } done: unsigned LastToEmitInLoop = EHSelector.size(); // If we have a catch-all, add null to the selector. - if (CatchAll.Block) { + if (CatchAll.isValid()) { EHSelector.push_back(getCatchAllValue(CGF)); // If we have an EH filter, we need to add those handlers in the @@ -878,14 +877,15 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // filter (possibly with a cleanup), a catch-all, or another catch). for (unsigned I = 2; I != LastToEmitInLoop; ++I) { llvm::Value *Type = EHSelector[I]; - JumpDest Dest = EHHandlers[Type]; - assert(Dest.Block && "no handler entry for value in selector?"); + UnwindDest Dest = EHHandlers[Type]; + assert(Dest.isValid() && "no handler entry for value in selector?"); // Figure out where to branch on a match. As a debug code-size // optimization, if the scope depth matches the innermost cleanup, // we branch directly to the catch handler. - llvm::BasicBlock *Match = Dest.Block; - bool MatchNeedsCleanup = Dest.ScopeDepth != EHStack.getInnermostEHCleanup(); + llvm::BasicBlock *Match = Dest.getBlock(); + bool MatchNeedsCleanup = + Dest.getScopeDepth() != EHStack.getInnermostEHCleanup(); if (MatchNeedsCleanup) Match = createBasicBlock("eh.match"); @@ -911,7 +911,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // Emit the final case in the selector. // This might be a catch-all.... - if (CatchAll.Block) { + if (CatchAll.isValid()) { assert(isa<llvm::ConstantPointerNull>(EHSelector.back())); EmitBranchThroughEHCleanup(CatchAll); @@ -930,7 +930,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { } llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont"); - EmitBranchThroughEHCleanup(JumpDest(CleanupContBB, EHStack.stable_end())); + EmitBranchThroughEHCleanup(UnwindDest(CleanupContBB, EHStack.stable_end(), + EHStack.getNextEHDestIndex())); EmitBlock(CleanupContBB); if (HasEHCleanup) @@ -975,26 +976,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // ...or a cleanup. } else { - // We emit a jump to a notional label at the outermost unwind state. - llvm::BasicBlock *Unwind = createBasicBlock("eh.resume"); - JumpDest Dest(Unwind, EHStack.stable_end()); - EmitBranchThroughEHCleanup(Dest); - - // The unwind block. We have to reload the exception here because - // we might have unwound through arbitrary blocks, so the landing - // pad might not dominate. - EmitBlock(Unwind); - - // This can always be a call because we necessarily didn't find - // anything on the EH stack which needs our help. - llvm::Constant *RethrowFn; - if (const char *RethrowName = Personality.getCatchallRethrowFnName()) - RethrowFn = getCatchallRethrowFn(CGF, RethrowName); - else - RethrowFn = getUnwindResumeOrRethrowFn(); - Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot())) - ->setDoesNotReturn(); - Builder.CreateUnreachable(); + EmitBranchThroughEHCleanup(getRethrowDest()); } // Restore the old IR generation state. @@ -1537,6 +1519,35 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { return TerminateHandler; } +CodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() { + if (RethrowBlock.isValid()) return RethrowBlock; + + CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); + + // We emit a jump to a notional label at the outermost unwind state. + llvm::BasicBlock *Unwind = createBasicBlock("eh.resume"); + Builder.SetInsertPoint(Unwind); + + const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions()); + + // This can always be a call because we necessarily didn't find + // anything on the EH stack which needs our help. + llvm::Constant *RethrowFn; + if (const char *RethrowName = Personality.getCatchallRethrowFnName()) + RethrowFn = getCatchallRethrowFn(*this, RethrowName); + else + RethrowFn = getUnwindResumeOrRethrowFn(); + + Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot())) + ->setDoesNotReturn(); + Builder.CreateUnreachable(); + + Builder.restoreIP(SavedIP); + + RethrowBlock = UnwindDest(Unwind, EHStack.stable_end(), 0); + return RethrowBlock; +} + EHScopeStack::Cleanup::~Cleanup() { llvm_unreachable("Cleanup is indestructable"); } |