summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp31
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp37
-rw-r--r--clang/lib/CodeGen/CGCleanup.h8
-rw-r--r--clang/lib/CodeGen/CGException.cpp74
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h8
-rw-r--r--clang/lib/CodeGen/EHScopeStack.h4
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp4
7 files changed, 63 insertions, 103 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 80f88fb8d15..891f9071bdc 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -15,6 +15,7 @@
#include "CGCall.h"
#include "ABIInfo.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
@@ -3472,11 +3473,21 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList);
- llvm::BasicBlock *InvokeDest = nullptr;
- if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind) ||
- currentFunctionUsesSEHTry())
- InvokeDest = getInvokeDest();
+ bool CannotThrow;
+ if (currentFunctionUsesSEHTry()) {
+ // SEH cares about asynchronous exceptions, everything can "throw."
+ CannotThrow = false;
+ } else if (isCleanupPadScope() &&
+ EHPersonality::get(*this).isMSVCXXPersonality()) {
+ // The MSVC++ personality will implicitly terminate the program if an
+ // exception is thrown. An unwind edge cannot be reached.
+ CannotThrow = true;
+ } else {
+ // Otherwise, nowunind callsites will never throw.
+ CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+ }
+ llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
llvm::CallSite CS;
if (!InvokeDest) {
@@ -3495,14 +3506,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
- // Disable inlining inside SEH __try blocks and cleanup funclets. None of the
- // funclet EH personalities that clang supports have tables that are
- // expressive enough to describe catching an exception inside a cleanup.
- // __CxxFrameHandler3, for example, will terminate the program without
- // catching it.
- // FIXME: Move this decision to the LLVM inliner. Before we can do that, the
- // inliner needs to know if a given call site is part of a cleanuppad.
- if (isSEHTryScope() || isCleanupPadScope())
+ // Disable inlining inside SEH __try blocks.
+ if (isSEHTryScope())
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline);
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 5b6e497673c..245d6a7e4b0 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -246,13 +246,6 @@ void EHScopeStack::pushTerminate() {
InnermostEHScope = stable_begin();
}
-void EHScopeStack::pushPadEnd(llvm::BasicBlock *PadEndBB) {
- char *Buffer = allocate(EHPadEndScope::getSize());
- auto *CES = new (Buffer) EHPadEndScope(InnermostEHScope);
- CES->setCachedEHDispatchBlock(PadEndBB);
- InnermostEHScope = stable_begin();
-}
-
/// Remove any 'null' fixups on the stack. However, we can't pop more
/// fixups than the fixup depth on the innermost normal cleanup, or
/// else fixups that we try to add to that cleanup will end up in the
@@ -909,24 +902,17 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// throwing cleanups. For funclet EH personalities, the cleanupendpad models
// program termination when cleanups throw.
bool PushedTerminate = false;
- SaveAndRestore<bool> RestoreIsCleanupPadScope(IsCleanupPadScope);
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
llvm::CleanupPadInst *CPI = nullptr;
- llvm::BasicBlock *CleanupEndBB = nullptr;
if (!EHPersonality::get(*this).usesFuncletPads()) {
EHStack.pushTerminate();
PushedTerminate = true;
} else {
- CPI = Builder.CreateCleanupPad({});
-
- // Build a cleanupendpad to unwind through. Our insertion point should be
- // in the cleanuppad block.
- CleanupEndBB = createBasicBlock("ehcleanup.end");
- CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction);
- EHStack.pushPadEnd(CleanupEndBB);
-
- // Mark that we're inside a cleanuppad to block inlining.
- // FIXME: Remove this once the inliner knows when it's safe to do so.
- IsCleanupPadScope = true;
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad);
}
// We only actually emit the cleanup code if the cleanup is either
@@ -941,17 +927,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
else
Builder.CreateBr(NextAction);
- // Insert the cleanupendpad block here, if it has any uses.
- if (CleanupEndBB) {
- EHStack.popPadEnd();
- if (CleanupEndBB->hasNUsesOrMore(1)) {
- CurFn->getBasicBlockList().insertAfter(
- Builder.GetInsertBlock()->getIterator(), CleanupEndBB);
- } else {
- delete CleanupEndBB;
- }
- }
-
// Leave the terminate scope.
if (PushedTerminate)
EHStack.popTerminate();
diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h
index 5a0145eb0b8..909f00b0592 100644
--- a/clang/lib/CodeGen/CGCleanup.h
+++ b/clang/lib/CodeGen/CGCleanup.h
@@ -587,14 +587,6 @@ inline void EHScopeStack::popTerminate() {
deallocate(EHTerminateScope::getSize());
}
-inline void EHScopeStack::popPadEnd() {
- assert(!empty() && "popping exception stack when not empty");
-
- EHPadEndScope &scope = cast<EHPadEndScope>(*begin());
- InnermostEHScope = scope.getEnclosingEHScope();
- deallocate(EHPadEndScope::getSize());
-}
-
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
assert(sp.isValid() && "finding invalid savepoint");
assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index eaa76109be1..b5e1dcdc6c9 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -871,58 +871,50 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
return lpad;
}
-static llvm::BasicBlock *emitCatchPadBlock(CodeGenFunction &CGF,
- EHCatchScope &CatchScope) {
+static void emitCatchPadBlock(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;
+ llvm::Value *ParentPad = CGF.CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
+ llvm::BasicBlock *UnwindBB =
+ CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope());
+
+ unsigned NumHandlers = CatchScope.getNumHandlers();
+ llvm::CatchSwitchInst *CatchSwitch =
+ CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
// Test against each of the exception types we claim to catch.
- for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) {
+ for (unsigned I = 0; I < NumHandlers; ++I) {
const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
CatchTypeInfo TypeInfo = Handler.Type;
if (!TypeInfo.RTTI)
TypeInfo.RTTI = 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(CGF, NextBlock).CreateCatchEndPad(
- CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()));
- } else {
- NextBlock = CGF.createBasicBlock("catch.dispatch");
- }
+ CGF.Builder.SetInsertPoint(Handler.Block);
if (EHPersonality::get(CGF).isMSVCXXPersonality()) {
- CGF.Builder.CreateCatchPad(Handler.Block, NextBlock,
- {TypeInfo.RTTI,
- CGF.Builder.getInt32(TypeInfo.Flags),
- llvm::Constant::getNullValue(CGF.VoidPtrTy)});
+ CGF.Builder.CreateCatchPad(
+ CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags),
+ llvm::Constant::getNullValue(CGF.VoidPtrTy)});
} else {
- CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, {TypeInfo.RTTI});
+ CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI});
}
- // Otherwise we need to emit and continue at that block.
- CGF.EmitBlock(NextBlock);
+ CatchSwitch->addHandler(Handler.Block);
}
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.
-/// 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) {
+static void emitCatchDispatchBlock(CodeGenFunction &CGF,
+ EHCatchScope &catchScope) {
if (EHPersonality::get(CGF).usesFuncletPads())
return emitCatchPadBlock(CGF, catchScope);
@@ -934,7 +926,7 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
if (catchScope.getNumHandlers() == 1 &&
catchScope.getHandler(0).isCatchAll()) {
assert(dispatchBlock == catchScope.getHandler(0).Block);
- return nullptr;
+ return;
}
CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
@@ -992,12 +984,11 @@ static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
// If the next handler is a catch-all, we're completely done.
if (nextIsEnd) {
CGF.Builder.restoreIP(savedIP);
- return nullptr;
+ return;
}
// Otherwise we need to emit and continue at that block.
CGF.EmitBlock(nextBlock);
}
- return nullptr;
}
void CodeGenFunction::popCatchScope() {
@@ -1020,7 +1011,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
}
// Emit the structure of the EH dispatch for this catch.
- llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope);
+ emitCatchDispatchBlock(*this, CatchScope);
// Copy the handler blocks off before we pop the EH stack. Emitting
// the handlers might scribble on this memory.
@@ -1043,9 +1034,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
isa<CXXConstructorDecl>(CurCodeDecl);
- if (CatchEndBlockBB)
- EHStack.pushPadEnd(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
@@ -1065,6 +1053,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
RunCleanupsScope CatchScope(*this);
// Initialize the catch variable and set up the cleanups.
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
CGM.getCXXABI().emitBeginCatch(*this, C);
// Emit the PGO counter increment.
@@ -1098,8 +1088,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
EmitBlock(ContBB);
incrementProfileCounter(&S);
- if (CatchEndBlockBB)
- EHStack.popPadEnd();
}
namespace {
@@ -1338,7 +1326,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
TerminateHandler = createBasicBlock("terminate.handler");
Builder.SetInsertPoint(TerminateHandler);
if (EHPersonality::get(*this).usesFuncletPads()) {
- Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn());
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ Builder.CreateTerminatePad(ParentPad, /*UnwindBB=*/nullptr,
+ {CGM.getTerminateFn()});
} else {
llvm::Value *Exn = nullptr;
if (getLangOpts().CPlusPlus)
@@ -1857,18 +1849,16 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
emitCatchDispatchBlock(*this, CatchScope);
// Grab the block before we pop the handler.
- llvm::BasicBlock *ExceptBB = CatchScope.getHandler(0).Block;
+ llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block;
EHStack.popCatch();
- EmitBlockAfterUses(ExceptBB);
+ EmitBlockAfterUses(CatchPadBB);
// __except blocks don't get outlined into funclets, so immediately do a
// catchret.
- llvm::BasicBlock *CatchPadBB = ExceptBB->getSinglePredecessor();
- assert(CatchPadBB && "only ExceptBB pred should be catchpad");
llvm::CatchPadInst *CPI =
cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
- ExceptBB = createBasicBlock("__except");
+ llvm::BasicBlock *ExceptBB = createBasicBlock("__except");
Builder.CreateCatchRet(CPI, ExceptBB);
EmitBlock(ExceptBB);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 714a641ba39..0302b0e6edd 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -279,8 +279,6 @@ public:
/// finally block or filter expression.
bool IsOutlinedSEHHelper;
- bool IsCleanupPadScope = false;
-
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -295,6 +293,8 @@ public:
llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack;
+ llvm::Instruction *CurrentFuncletPad = nullptr;
+
/// Header for data within LifetimeExtendedCleanupStack.
struct LifetimeExtendedCleanupHeader {
/// The size of the following cleanup object.
@@ -375,7 +375,9 @@ public:
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
/// Returns true while emitting a cleanuppad.
- bool isCleanupPadScope() const { return IsCleanupPadScope; }
+ bool isCleanupPadScope() const {
+ return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad);
+ }
/// pushFullExprCleanup - Push a cleanup to be run at the end of the
/// current full-expression. Safe against the possibility that
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index 9840afe6bc5..85cd1543e5b 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -334,10 +334,6 @@ public:
/// Pops a terminate handler off the stack.
void popTerminate();
- void pushPadEnd(llvm::BasicBlock *PadEndBB);
-
- void popPadEnd();
-
// Returns true iff the current scope is either empty or contains only
// lifetime markers, i.e. no real cleanup code
bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 711b08e6a29..f22c5b8b60d 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -893,10 +893,10 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
// In the MS ABI, the runtime handles the copy, and the catch handler is
// responsible for destruction.
VarDecl *CatchParam = S->getExceptionDecl();
- llvm::BasicBlock *CatchPadBB =
- CGF.Builder.GetInsertBlock()->getSinglePredecessor();
+ llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock();
llvm::CatchPadInst *CPI =
cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+ CGF.CurrentFuncletPad = CPI;
// If this is a catch-all or the catch parameter is unnamed, we don't need to
// emit an alloca to the object.
OpenPOWER on IntegriCloud