aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGException.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-07-31 17:58:45 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-07-31 17:58:45 +0000
commitdbf1045ad75c41e0711e075cf9e0ffd433c55c67 (patch)
treec75cc12748d00898b082c1e1d556af59ec43ab8d /clang/lib/CodeGen/CGException.cpp
parent654e130b6ec76c1a2910b2594cb403ecd2773af8 (diff)
downloadllvm-dbf1045ad75c41e0711e075cf9e0ffd433c55c67.zip
llvm-dbf1045ad75c41e0711e075cf9e0ffd433c55c67.tar.gz
llvm-dbf1045ad75c41e0711e075cf9e0ffd433c55c67.tar.bz2
[MS ABI] Hook clang up to the new EH instructions
The new EH instructions make it possible for LLVM to generate .xdata tables that the MSVC personality routines will be happy about. Because this is experimental, hide it behind a -cc1 flag (-fnew-ms-eh). Differential Revision: http://reviews.llvm.org/D11405 llvm-svn: 243767
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);