From 09af67aba54e6d2a05e3071c0c7ba43bde678df9 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Sun, 27 Sep 2015 01:47:46 +0000 Subject: [EH] Create removeUnwindEdge utility Summary: Factor the code that rewrites invokes to calls and rewrites WinEH terminators to their "unwind to caller" equivalents into a helper in Utils/Local, and use it in the three places I'm aware of that need to do this. Reviewers: andrew.w.kaylor, majnemer, rnk Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D13152 llvm-svn: 248677 --- llvm/lib/Transforms/Utils/Local.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'llvm/lib/Transforms/Utils/Local.cpp') diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 235973c4fbc..fec7176e9a2 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1258,6 +1258,43 @@ static bool markAliveBlocks(Function &F, return Changed; } +void llvm::removeUnwindEdge(BasicBlock *BB) { + TerminatorInst *TI = BB->getTerminator(); + + if (auto *II = dyn_cast(TI)) { + changeToCall(II); + return; + } + + TerminatorInst *NewTI; + BasicBlock *UnwindDest; + + if (auto *CRI = dyn_cast(TI)) { + NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI); + UnwindDest = CRI->getUnwindDest(); + } else if (auto *CEP = dyn_cast(TI)) { + NewTI = CleanupEndPadInst::Create(CEP->getCleanupPad(), nullptr, CEP); + UnwindDest = CEP->getUnwindDest(); + } else if (auto *CEP = dyn_cast(TI)) { + NewTI = CatchEndPadInst::Create(CEP->getContext(), nullptr, CEP); + UnwindDest = CEP->getUnwindDest(); + } else if (auto *TPI = dyn_cast(TI)) { + SmallVector TerminatePadArgs; + for (Value *Operand : TPI->arg_operands()) + TerminatePadArgs.push_back(Operand); + NewTI = TerminatePadInst::Create(TPI->getContext(), nullptr, + TerminatePadArgs, TPI); + UnwindDest = TPI->getUnwindDest(); + } else { + llvm_unreachable("Could not find unwind successor"); + } + + NewTI->takeName(TI); + NewTI->setDebugLoc(TI->getDebugLoc()); + UnwindDest->removePredecessor(BB); + TI->eraseFromParent(); +} + /// removeUnreachableBlocksFromFn - Remove blocks that are not reachable, even /// if they are in a dead cycle. Return true if a change was made, false /// otherwise. -- cgit v1.2.3