diff options
Diffstat (limited to 'clang/lib/CodeGen/CGException.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 165 |
1 files changed, 146 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index d0e86ae..16dc7d1 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -559,6 +559,10 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { llvm::BasicBlock * CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) { + if (CGM.getCodeGenOpts().NewMSEH && + EHPersonality::get(*this).isMSVCPersonality()) + return getMSVCDispatchBlock(si); + // The dispatch block for the end of the scope chain is a block that // just resumes unwinding. if (si == EHStack.stable_end()) @@ -595,12 +599,58 @@ CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) { case EHScope::Terminate: dispatchBlock = getTerminateHandler(); break; + + case EHScope::CatchEnd: + llvm_unreachable("CatchEnd unnecessary for Itanium!"); } scope.setCachedEHDispatchBlock(dispatchBlock); } return dispatchBlock; } +llvm::BasicBlock * +CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) { + // Returning nullptr indicates that the previous dispatch block should unwind + // to caller. + if (SI == EHStack.stable_end()) + return nullptr; + + // Otherwise, we should look at the actual scope. + EHScope &EHS = *EHStack.find(SI); + + llvm::BasicBlock *DispatchBlock = EHS.getCachedEHDispatchBlock(); + if (DispatchBlock) + return DispatchBlock; + + if (EHS.getKind() == EHScope::Terminate) + DispatchBlock = getTerminateHandler(); + else + DispatchBlock = createBasicBlock(); + CGBuilderTy Builder(DispatchBlock); + + switch (EHS.getKind()) { + case EHScope::Catch: + DispatchBlock->setName("catch.dispatch"); + break; + + case EHScope::Cleanup: + DispatchBlock->setName("ehcleanup"); + break; + + case EHScope::Filter: + llvm_unreachable("exception specifications not handled yet!"); + + case EHScope::Terminate: + DispatchBlock->setName("terminate"); + break; + + case EHScope::CatchEnd: + llvm_unreachable("CatchEnd dispatch block missing!"); + } + EHS.setCachedEHDispatchBlock(DispatchBlock); + return DispatchBlock; +} + /// Check whether this is a non-EH scope, i.e. a scope which doesn't /// affect exception handling. Currently, the only non-EH scopes are /// normal-only cleanup scopes. @@ -611,6 +661,7 @@ static bool isNonEHScope(const EHScope &S) { case EHScope::Filter: case EHScope::Catch: case EHScope::Terminate: + case EHScope::CatchEnd: return false; } @@ -636,8 +687,19 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); if (LP) return LP; - // Build the landing pad for this scope. - LP = EmitLandingPad(); + const EHPersonality &Personality = EHPersonality::get(*this); + + if (!CurFn->hasPersonalityFn()) + CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality)); + + if (CGM.getCodeGenOpts().NewMSEH && Personality.isMSVCPersonality()) { + // We don't need separate landing pads in the MSVC model. + LP = getEHDispatchBlock(EHStack.getInnermostEHScope()); + } else { + // Build the landing pad for this scope. + LP = EmitLandingPad(); + } + assert(LP); // Cache the landing pad on the innermost scope. If this is a @@ -658,6 +720,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { case EHScope::Terminate: return getTerminateLandingPad(); + case EHScope::CatchEnd: + llvm_unreachable("CatchEnd unnecessary for Itanium!"); + case EHScope::Catch: case EHScope::Cleanup: case EHScope::Filter: @@ -669,11 +734,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation); - const EHPersonality &personality = EHPersonality::get(*this); - - if (!CurFn->hasPersonalityFn()) - CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, personality)); - // Create and configure the landing pad. llvm::BasicBlock *lpad = createBasicBlock("lpad"); EmitBlock(lpad); @@ -728,6 +788,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { case EHScope::Catch: break; + + case EHScope::CatchEnd: + llvm_unreachable("CatchEnd unnecessary for Itanium!"); } EHCatchScope &catchScope = cast<EHCatchScope>(*I); @@ -792,10 +855,63 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { return lpad; } +static llvm::BasicBlock *emitMSVCCatchDispatchBlock(CodeGenFunction &CGF, + EHCatchScope &CatchScope) { + llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); + assert(DispatchBlock); + + CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP(); + CGF.EmitBlockAfterUses(DispatchBlock); + + // Figure out the next block. + llvm::BasicBlock *NextBlock = nullptr; + + // Test against each of the exception types we claim to catch. + for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) { + const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); + + llvm::Value *TypeValue = Handler.Type; + assert(TypeValue != nullptr || Handler.isCatchAll()); + if (!TypeValue) + TypeValue = llvm::Constant::getNullValue(CGF.VoidPtrTy); + + // If this is the last handler, we're at the end, and the next + // block is the block for the enclosing EH scope. + if (I + 1 == E) { + NextBlock = CGF.createBasicBlock("catchendblock"); + CGBuilderTy(NextBlock).CreateCatchEndPad( + CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope())); + } else { + NextBlock = CGF.createBasicBlock("catch.dispatch"); + } + + if (EHPersonality::get(CGF).isMSVCXXPersonality()) { + CGF.Builder.CreateCatchPad( + CGF.VoidTy, Handler.Block, NextBlock, + {TypeValue, llvm::Constant::getNullValue(CGF.VoidPtrTy)}); + } else { + CGF.Builder.CreateCatchPad(CGF.VoidTy, Handler.Block, NextBlock, + {TypeValue}); + } + + // Otherwise we need to emit and continue at that block. + CGF.EmitBlock(NextBlock); + } + CGF.Builder.restoreIP(SavedIP); + + return NextBlock; +} + /// Emit the structure of the dispatch block for the given catch scope. /// It is an invariant that the dispatch block already exists. -static void emitCatchDispatchBlock(CodeGenFunction &CGF, - EHCatchScope &catchScope) { +/// If the catchblock instructions are used for EH dispatch, then the basic +/// block holding the final catchendblock instruction is returned. +static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF, + EHCatchScope &catchScope) { + if (CGF.CGM.getCodeGenOpts().NewMSEH && + EHPersonality::get(CGF).isMSVCPersonality()) + return emitMSVCCatchDispatchBlock(CGF, catchScope); + llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock(); assert(dispatchBlock); @@ -804,7 +920,7 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF, if (catchScope.getNumHandlers() == 1 && catchScope.getHandler(0).isCatchAll()) { assert(dispatchBlock == catchScope.getHandler(0).Block); - return; + return nullptr; } CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); @@ -860,11 +976,12 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF, // If the next handler is a catch-all, we're completely done. if (nextIsEnd) { CGF.Builder.restoreIP(savedIP); - return; + return nullptr; } // Otherwise we need to emit and continue at that block. CGF.EmitBlock(nextBlock); } + return nullptr; } void CodeGenFunction::popCatchScope() { @@ -887,7 +1004,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { } // Emit the structure of the EH dispatch for this catch. - emitCatchDispatchBlock(*this, CatchScope); + llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope); // Copy the handler blocks off before we pop the EH stack. Emitting // the handlers might scribble on this memory. @@ -911,6 +1028,9 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || isa<CXXConstructorDecl>(CurCodeDecl); + if (CatchEndBlockBB) + EHStack.pushCatchEnd(CatchEndBlockBB); + // Perversely, we emit the handlers backwards precisely because we // want them to appear in source order. In all of these cases, the // catch block will have exactly one predecessor, which will be a @@ -963,6 +1083,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { EmitBlock(ContBB); incrementProfileCounter(&S); + if (CatchEndBlockBB) + EHStack.popCatchEnd(); } namespace { @@ -1200,13 +1322,18 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { // end of the function by FinishFunction. TerminateHandler = createBasicBlock("terminate.handler"); Builder.SetInsertPoint(TerminateHandler); - llvm::Value *Exn = 0; - if (getLangOpts().CPlusPlus) - Exn = getExceptionFromSlot(); - llvm::CallInst *terminateCall = - CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); - terminateCall->setDoesNotReturn(); - Builder.CreateUnreachable(); + if (CGM.getCodeGenOpts().NewMSEH && + EHPersonality::get(*this).isMSVCPersonality()) { + Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn()); + } else { + llvm::Value *Exn = 0; + if (getLangOpts().CPlusPlus) + Exn = getExceptionFromSlot(); + llvm::CallInst *terminateCall = + CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); + terminateCall->setDoesNotReturn(); + Builder.CreateUnreachable(); + } // Restore the saved insertion state. Builder.restoreIP(SavedIP); |