191bc56edSDimitry Andric //===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This transformation is designed for use by code generators which do not yet
1191bc56edSDimitry Andric // support stack unwinding.  This pass converts 'invoke' instructions to 'call'
1291bc56edSDimitry Andric // instructions, so that any exception-handling 'landingpad' blocks become dead
1391bc56edSDimitry Andric // code (which can be removed by running the '-simplifycfg' pass afterwards).
14f22ef01cSRoman Divacky //
15f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
16f22ef01cSRoman Divacky 
17d88c1a5aSDimitry Andric #include "llvm/Transforms/Utils/LowerInvoke.h"
18ffd1746dSEd Schouten #include "llvm/ADT/SmallVector.h"
19f22ef01cSRoman Divacky #include "llvm/ADT/Statistic.h"
20139f7f9bSDimitry Andric #include "llvm/IR/Instructions.h"
21139f7f9bSDimitry Andric #include "llvm/IR/LLVMContext.h"
22139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
23139f7f9bSDimitry Andric #include "llvm/Pass.h"
24*4ba319b5SDimitry Andric #include "llvm/Transforms/Utils.h"
25f22ef01cSRoman Divacky using namespace llvm;
26f22ef01cSRoman Divacky 
2791bc56edSDimitry Andric #define DEBUG_TYPE "lowerinvoke"
28f22ef01cSRoman Divacky 
2991bc56edSDimitry Andric STATISTIC(NumInvokes, "Number of invokes replaced");
30f22ef01cSRoman Divacky 
31f22ef01cSRoman Divacky namespace {
32d88c1a5aSDimitry Andric   class LowerInvokeLegacyPass : public FunctionPass {
33f22ef01cSRoman Divacky   public:
34f22ef01cSRoman Divacky     static char ID; // Pass identification, replacement for typeid
LowerInvokeLegacyPass()35d88c1a5aSDimitry Andric     explicit LowerInvokeLegacyPass() : FunctionPass(ID) {
36d88c1a5aSDimitry Andric       initializeLowerInvokeLegacyPassPass(*PassRegistry::getPassRegistry());
372754fe60SDimitry Andric     }
3891bc56edSDimitry Andric     bool runOnFunction(Function &F) override;
39f22ef01cSRoman Divacky   };
40f22ef01cSRoman Divacky }
41f22ef01cSRoman Divacky 
42d88c1a5aSDimitry Andric char LowerInvokeLegacyPass::ID = 0;
43d88c1a5aSDimitry Andric INITIALIZE_PASS(LowerInvokeLegacyPass, "lowerinvoke",
44e580952dSDimitry Andric                 "Lower invoke and unwind, for unwindless code generators",
452754fe60SDimitry Andric                 false, false)
46f22ef01cSRoman Divacky 
runImpl(Function & F)47d88c1a5aSDimitry Andric static bool runImpl(Function &F) {
48f22ef01cSRoman Divacky   bool Changed = false;
493ca95b02SDimitry Andric   for (BasicBlock &BB : F)
503ca95b02SDimitry Andric     if (InvokeInst *II = dyn_cast<InvokeInst>(BB.getTerminator())) {
51*4ba319b5SDimitry Andric       SmallVector<Value *, 16> CallArgs(II->arg_begin(), II->arg_end());
52*4ba319b5SDimitry Andric       SmallVector<OperandBundleDef, 1> OpBundles;
53*4ba319b5SDimitry Andric       II->getOperandBundlesAsDefs(OpBundles);
54f22ef01cSRoman Divacky       // Insert a normal call instruction...
55d88c1a5aSDimitry Andric       CallInst *NewCall =
56*4ba319b5SDimitry Andric           CallInst::Create(II->getCalledValue(), CallArgs, OpBundles, "", II);
57f22ef01cSRoman Divacky       NewCall->takeName(II);
58f22ef01cSRoman Divacky       NewCall->setCallingConv(II->getCallingConv());
59f22ef01cSRoman Divacky       NewCall->setAttributes(II->getAttributes());
602754fe60SDimitry Andric       NewCall->setDebugLoc(II->getDebugLoc());
61f22ef01cSRoman Divacky       II->replaceAllUsesWith(NewCall);
62f22ef01cSRoman Divacky 
63f22ef01cSRoman Divacky       // Insert an unconditional branch to the normal destination.
64f22ef01cSRoman Divacky       BranchInst::Create(II->getNormalDest(), II);
65f22ef01cSRoman Divacky 
66f22ef01cSRoman Divacky       // Remove any PHI node entries from the exception destination.
673ca95b02SDimitry Andric       II->getUnwindDest()->removePredecessor(&BB);
68f22ef01cSRoman Divacky 
69f22ef01cSRoman Divacky       // Remove the invoke instruction now.
703ca95b02SDimitry Andric       BB.getInstList().erase(II);
71f22ef01cSRoman Divacky 
72d88c1a5aSDimitry Andric       ++NumInvokes;
73d88c1a5aSDimitry Andric       Changed = true;
74f22ef01cSRoman Divacky     }
75f22ef01cSRoman Divacky   return Changed;
76f22ef01cSRoman Divacky }
77d88c1a5aSDimitry Andric 
runOnFunction(Function & F)78d88c1a5aSDimitry Andric bool LowerInvokeLegacyPass::runOnFunction(Function &F) {
79d88c1a5aSDimitry Andric   return runImpl(F);
80d88c1a5aSDimitry Andric }
81d88c1a5aSDimitry Andric 
82d88c1a5aSDimitry Andric namespace llvm {
83d88c1a5aSDimitry Andric char &LowerInvokePassID = LowerInvokeLegacyPass::ID;
84d88c1a5aSDimitry Andric 
85d88c1a5aSDimitry Andric // Public Interface To the LowerInvoke pass.
createLowerInvokePass()86d88c1a5aSDimitry Andric FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); }
87d88c1a5aSDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)88d88c1a5aSDimitry Andric PreservedAnalyses LowerInvokePass::run(Function &F,
89d88c1a5aSDimitry Andric                                        FunctionAnalysisManager &AM) {
90d88c1a5aSDimitry Andric   bool Changed = runImpl(F);
91d88c1a5aSDimitry Andric   if (!Changed)
92d88c1a5aSDimitry Andric     return PreservedAnalyses::all();
93d88c1a5aSDimitry Andric 
94d88c1a5aSDimitry Andric   return PreservedAnalyses::none();
95d88c1a5aSDimitry Andric }
96d88c1a5aSDimitry Andric }
97