15ca98fd9SDimitry Andric //===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This transformation is designed for use by code generators which do not yet
105ca98fd9SDimitry Andric // support stack unwinding. This pass converts 'invoke' instructions to 'call'
115ca98fd9SDimitry Andric // instructions, so that any exception-handling 'landingpad' blocks become dead
125ca98fd9SDimitry Andric // code (which can be removed by running the '-simplifycfg' pass afterwards).
13009b1c42SEd Schouten //
14009b1c42SEd Schouten //===----------------------------------------------------------------------===//
15009b1c42SEd Schouten
16b915e9e0SDimitry Andric #include "llvm/Transforms/Utils/LowerInvoke.h"
1766e41e3cSRoman Divacky #include "llvm/ADT/SmallVector.h"
18009b1c42SEd Schouten #include "llvm/ADT/Statistic.h"
194a16efa3SDimitry Andric #include "llvm/IR/Instructions.h"
20706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
214a16efa3SDimitry Andric #include "llvm/Pass.h"
22eb11fae6SDimitry Andric #include "llvm/Transforms/Utils.h"
23009b1c42SEd Schouten using namespace llvm;
24009b1c42SEd Schouten
25ac9a064cSDimitry Andric #define DEBUG_TYPE "lower-invoke"
26009b1c42SEd Schouten
275ca98fd9SDimitry Andric STATISTIC(NumInvokes, "Number of invokes replaced");
28009b1c42SEd Schouten
29009b1c42SEd Schouten namespace {
30b915e9e0SDimitry Andric class LowerInvokeLegacyPass : public FunctionPass {
31009b1c42SEd Schouten public:
32009b1c42SEd Schouten static char ID; // Pass identification, replacement for typeid
LowerInvokeLegacyPass()33b915e9e0SDimitry Andric explicit LowerInvokeLegacyPass() : FunctionPass(ID) {
34b915e9e0SDimitry Andric initializeLowerInvokeLegacyPassPass(*PassRegistry::getPassRegistry());
35cf099d11SDimitry Andric }
365ca98fd9SDimitry Andric bool runOnFunction(Function &F) override;
37009b1c42SEd Schouten };
38009b1c42SEd Schouten }
39009b1c42SEd Schouten
40b915e9e0SDimitry Andric char LowerInvokeLegacyPass::ID = 0;
41b915e9e0SDimitry Andric INITIALIZE_PASS(LowerInvokeLegacyPass, "lowerinvoke",
42d39c594dSDimitry Andric "Lower invoke and unwind, for unwindless code generators",
43cf099d11SDimitry Andric false, false)
44009b1c42SEd Schouten
runImpl(Function & F)45b915e9e0SDimitry Andric static bool runImpl(Function &F) {
46009b1c42SEd Schouten bool Changed = false;
4701095a5dSDimitry Andric for (BasicBlock &BB : F)
4801095a5dSDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(BB.getTerminator())) {
49b60736ecSDimitry Andric SmallVector<Value *, 16> CallArgs(II->args());
50eb11fae6SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles;
51eb11fae6SDimitry Andric II->getOperandBundlesAsDefs(OpBundles);
52009b1c42SEd Schouten // Insert a normal call instruction...
53b915e9e0SDimitry Andric CallInst *NewCall =
54cfca06d7SDimitry Andric CallInst::Create(II->getFunctionType(), II->getCalledOperand(),
55ac9a064cSDimitry Andric CallArgs, OpBundles, "", II->getIterator());
56009b1c42SEd Schouten NewCall->takeName(II);
57009b1c42SEd Schouten NewCall->setCallingConv(II->getCallingConv());
58009b1c42SEd Schouten NewCall->setAttributes(II->getAttributes());
59cf099d11SDimitry Andric NewCall->setDebugLoc(II->getDebugLoc());
60009b1c42SEd Schouten II->replaceAllUsesWith(NewCall);
61009b1c42SEd Schouten
62009b1c42SEd Schouten // Insert an unconditional branch to the normal destination.
63ac9a064cSDimitry Andric BranchInst::Create(II->getNormalDest(), II->getIterator());
64009b1c42SEd Schouten
65009b1c42SEd Schouten // Remove any PHI node entries from the exception destination.
6601095a5dSDimitry Andric II->getUnwindDest()->removePredecessor(&BB);
67009b1c42SEd Schouten
68009b1c42SEd Schouten // Remove the invoke instruction now.
69e3b55780SDimitry Andric II->eraseFromParent();
70009b1c42SEd Schouten
71b915e9e0SDimitry Andric ++NumInvokes;
72b915e9e0SDimitry Andric Changed = true;
73009b1c42SEd Schouten }
74009b1c42SEd Schouten return Changed;
75009b1c42SEd Schouten }
76b915e9e0SDimitry Andric
runOnFunction(Function & F)77b915e9e0SDimitry Andric bool LowerInvokeLegacyPass::runOnFunction(Function &F) {
78b915e9e0SDimitry Andric return runImpl(F);
79b915e9e0SDimitry Andric }
80b915e9e0SDimitry Andric
81b915e9e0SDimitry Andric namespace llvm {
82b915e9e0SDimitry Andric char &LowerInvokePassID = LowerInvokeLegacyPass::ID;
83b915e9e0SDimitry Andric
84b915e9e0SDimitry Andric // Public Interface To the LowerInvoke pass.
createLowerInvokePass()85b915e9e0SDimitry Andric FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); }
86b915e9e0SDimitry Andric
run(Function & F,FunctionAnalysisManager & AM)87b915e9e0SDimitry Andric PreservedAnalyses LowerInvokePass::run(Function &F,
88b915e9e0SDimitry Andric FunctionAnalysisManager &AM) {
89b915e9e0SDimitry Andric bool Changed = runImpl(F);
90b915e9e0SDimitry Andric if (!Changed)
91b915e9e0SDimitry Andric return PreservedAnalyses::all();
92b915e9e0SDimitry Andric
93b915e9e0SDimitry Andric return PreservedAnalyses::none();
94b915e9e0SDimitry Andric }
95b915e9e0SDimitry Andric }
96