aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGException.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGException.cpp')
-rw-r--r--clang/lib/CodeGen/CGException.cpp165
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);