summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorJoseph Tremoulet <jotrem@microsoft.com>2015-09-03 09:09:43 +0000
committerJoseph Tremoulet <jotrem@microsoft.com>2015-09-03 09:09:43 +0000
commit9ce71f76b9497d3b50bc267b2ba9a92de48f13e2 (patch)
tree7323a60f5c30c9b8e7ffde38dfb29d19b0de19c5 /llvm/lib/CodeGen
parent0dcd8bcf2407caa5c6a9705c8b7d0cdda4824dba (diff)
downloadbcm5719-llvm-9ce71f76b9497d3b50bc267b2ba9a92de48f13e2.tar.gz
bcm5719-llvm-9ce71f76b9497d3b50bc267b2ba9a92de48f13e2.zip
[WinEH] Add cleanupendpad instruction
Summary: Add a `cleanupendpad` instruction, used to mark exceptional exits out of cleanups (for languages/targets that can abort a cleanup with another exception). The `cleanupendpad` instruction is similar to the `catchendpad` instruction in that it is an EH pad which is the target of unwind edges in the handler and which itself has an unwind edge to the next EH action. The `cleanupendpad` instruction, similar to `cleanupret` has a `cleanuppad` argument indicating which cleanup it exits. The unwind successors of a `cleanuppad`'s `cleanupendpad`s must agree with each other and with its `cleanupret`s. Update WinEHPrepare (and docs/tests) to accomodate `cleanupendpad`. Reviewers: rnk, andrew.w.kaylor, majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D12433 llvm-svn: 246751
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp4
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h1
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp1
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp36
4 files changed, 33 insertions, 9 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 7c1706f6edc..9aa9755796d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1205,6 +1205,10 @@ void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
report_fatal_error("visitCleanupRet not yet implemented!");
}
+void SelectionDAGBuilder::visitCleanupEndPad(const CleanupEndPadInst &I) {
+ report_fatal_error("visitCleanupEndPad not yet implemented!");
+}
+
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
report_fatal_error("visitTerminatePad not yet implemented!");
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 3b97d469f5e..2331127a966 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -740,6 +740,7 @@ private:
void visitSwitch(const SwitchInst &I);
void visitIndirectBr(const IndirectBrInst &I);
void visitUnreachable(const UnreachableInst &I);
+ void visitCleanupEndPad(const CleanupEndPadInst &I);
void visitCleanupRet(const CleanupReturnInst &I);
void visitCatchEndPad(const CatchEndPadInst &I);
void visitCatchRet(const CatchReturnInst &I);
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index d7a58f9686d..7250fdc9385 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1574,6 +1574,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case Invoke: return 0;
case Resume: return 0;
case Unreachable: return 0;
+ case CleanupEndPad: return 0;
case CleanupRet: return 0;
case CatchEndPad: return 0;
case CatchRet: return 0;
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 8c15b7e4413..c333c074900 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -403,7 +403,7 @@ bool WinEHPrepare::runOnFunction(Function &Fn) {
} else if (First->isEHPad()) {
if (!ForExplicitEH)
EntryBlocks.push_back(&Fn.getEntryBlock());
- if (!isa<CatchEndPadInst>(First))
+ if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First))
EntryBlocks.push_back(&BB);
ForExplicitEH = true;
}
@@ -2965,6 +2965,8 @@ static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
if (isa<CatchPadInst>(TI) || isa<CatchEndPadInst>(TI) ||
isa<TerminatePadInst>(TI))
return BB;
+ if (auto *CEPI = dyn_cast<CleanupEndPadInst>(TI))
+ return CEPI->getCleanupPad()->getParent();
return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
}
@@ -3035,18 +3037,27 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
for (const BasicBlock &BB : *ParentFn) {
if (!BB.isEHPad())
continue;
+ const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+ // Skip cleanupendpads; they are exits, not entries.
+ if (isa<CleanupEndPadInst>(FirstNonPHI))
+ continue;
// Check if the EH Pad has no exceptional successors (i.e. it unwinds to
// caller). Cleanups are a little bit of a special case because their
// control flow cannot be determined by looking at the pad but instead by
// the pad's users.
bool HasNoSuccessors = false;
- const Instruction *FirstNonPHI = BB.getFirstNonPHI();
if (FirstNonPHI->mayThrow()) {
HasNoSuccessors = true;
} else if (auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) {
- HasNoSuccessors =
- CPI->use_empty() ||
- cast<CleanupReturnInst>(CPI->user_back())->unwindsToCaller();
+ if (CPI->use_empty()) {
+ HasNoSuccessors = true;
+ } else {
+ const Instruction *User = CPI->user_back();
+ if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
+ HasNoSuccessors = CRI->unwindsToCaller();
+ else
+ HasNoSuccessors = cast<CleanupEndPadInst>(User)->unwindsToCaller();
+ }
}
if (!HasNoSuccessors)
@@ -3096,7 +3107,8 @@ void WinEHPrepare::colorFunclets(Function &F,
BasicBlock *Color;
std::tie(Visiting, Color) = Worklist.pop_back_val();
Instruction *VisitingHead = Visiting->getFirstNonPHI();
- if (VisitingHead->isEHPad() && !isa<CatchEndPadInst>(VisitingHead)) {
+ if (VisitingHead->isEHPad() && !isa<CatchEndPadInst>(VisitingHead) &&
+ !isa<CleanupEndPadInst>(VisitingHead)) {
// Mark this as a funclet head as a member of itself.
FuncletBlocks[Visiting].insert(Visiting);
// Queue exits with the parent color.
@@ -3132,7 +3144,8 @@ void WinEHPrepare::colorFunclets(Function &F,
FuncletBlocks[Color].insert(Visiting);
TerminatorInst *Terminator = Visiting->getTerminator();
if (isa<CleanupReturnInst>(Terminator) ||
- isa<CatchReturnInst>(Terminator)) {
+ isa<CatchReturnInst>(Terminator) ||
+ isa<CleanupEndPadInst>(Terminator)) {
// These block's successors have already been queued with the parent
// color.
continue;
@@ -3288,11 +3301,16 @@ bool WinEHPrepare::prepareExplicitEH(
bool IsUnreachableCatchret = false;
if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
- // The token consumed by a CleanupPadInst must match the funclet token.
+ // The token consumed by a CleanupReturnInst must match the funclet token.
bool IsUnreachableCleanupret = false;
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
- if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) {
+ // The token consumed by a CleanupEndPadInst must match the funclet token.
+ bool IsUnreachableCleanupendpad = false;
+ if (auto *CEPI = dyn_cast<CleanupEndPadInst>(TI))
+ IsUnreachableCleanupendpad = CEPI->getCleanupPad() != CleanupPad;
+ if (IsUnreachableRet || IsUnreachableCatchret ||
+ IsUnreachableCleanupret || IsUnreachableCleanupendpad) {
new UnreachableInst(BB->getContext(), TI);
TI->eraseFromParent();
}
OpenPOWER on IntegriCloud