10b57cec5SDimitry Andric //===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This transformation is designed for use by code generators which do not yet
100b57cec5SDimitry Andric // support stack unwinding. This pass converts 'invoke' instructions to 'call'
110b57cec5SDimitry Andric // instructions, so that any exception-handling 'landingpad' blocks become dead
120b57cec5SDimitry Andric // code (which can be removed by running the '-simplifycfg' pass afterwards).
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LowerInvoke.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
190b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
20480093f4SDimitry Andric #include "llvm/InitializePasses.h"
210b57cec5SDimitry Andric #include "llvm/Pass.h"
220b57cec5SDimitry Andric #include "llvm/Transforms/Utils.h"
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric
25*0fca6ea1SDimitry Andric #define DEBUG_TYPE "lower-invoke"
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric STATISTIC(NumInvokes, "Number of invokes replaced");
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric class LowerInvokeLegacyPass : public FunctionPass {
310b57cec5SDimitry Andric public:
320b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
LowerInvokeLegacyPass()330b57cec5SDimitry Andric explicit LowerInvokeLegacyPass() : FunctionPass(ID) {
340b57cec5SDimitry Andric initializeLowerInvokeLegacyPassPass(*PassRegistry::getPassRegistry());
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric bool runOnFunction(Function &F) override;
370b57cec5SDimitry Andric };
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric char LowerInvokeLegacyPass::ID = 0;
410b57cec5SDimitry Andric INITIALIZE_PASS(LowerInvokeLegacyPass, "lowerinvoke",
420b57cec5SDimitry Andric "Lower invoke and unwind, for unwindless code generators",
430b57cec5SDimitry Andric false, false)
440b57cec5SDimitry Andric
runImpl(Function & F)450b57cec5SDimitry Andric static bool runImpl(Function &F) {
460b57cec5SDimitry Andric bool Changed = false;
470b57cec5SDimitry Andric for (BasicBlock &BB : F)
480b57cec5SDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(BB.getTerminator())) {
49e8d8bef9SDimitry Andric SmallVector<Value *, 16> CallArgs(II->args());
500b57cec5SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles;
510b57cec5SDimitry Andric II->getOperandBundlesAsDefs(OpBundles);
520b57cec5SDimitry Andric // Insert a normal call instruction...
530b57cec5SDimitry Andric CallInst *NewCall =
545ffd83dbSDimitry Andric CallInst::Create(II->getFunctionType(), II->getCalledOperand(),
55*0fca6ea1SDimitry Andric CallArgs, OpBundles, "", II->getIterator());
560b57cec5SDimitry Andric NewCall->takeName(II);
570b57cec5SDimitry Andric NewCall->setCallingConv(II->getCallingConv());
580b57cec5SDimitry Andric NewCall->setAttributes(II->getAttributes());
590b57cec5SDimitry Andric NewCall->setDebugLoc(II->getDebugLoc());
600b57cec5SDimitry Andric II->replaceAllUsesWith(NewCall);
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric // Insert an unconditional branch to the normal destination.
63*0fca6ea1SDimitry Andric BranchInst::Create(II->getNormalDest(), II->getIterator());
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric // Remove any PHI node entries from the exception destination.
660b57cec5SDimitry Andric II->getUnwindDest()->removePredecessor(&BB);
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric // Remove the invoke instruction now.
69bdd1243dSDimitry Andric II->eraseFromParent();
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric ++NumInvokes;
720b57cec5SDimitry Andric Changed = true;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric return Changed;
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
runOnFunction(Function & F)770b57cec5SDimitry Andric bool LowerInvokeLegacyPass::runOnFunction(Function &F) {
780b57cec5SDimitry Andric return runImpl(F);
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric namespace llvm {
820b57cec5SDimitry Andric char &LowerInvokePassID = LowerInvokeLegacyPass::ID;
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric // Public Interface To the LowerInvoke pass.
createLowerInvokePass()850b57cec5SDimitry Andric FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); }
860b57cec5SDimitry Andric
run(Function & F,FunctionAnalysisManager & AM)870b57cec5SDimitry Andric PreservedAnalyses LowerInvokePass::run(Function &F,
880b57cec5SDimitry Andric FunctionAnalysisManager &AM) {
890b57cec5SDimitry Andric bool Changed = runImpl(F);
900b57cec5SDimitry Andric if (!Changed)
910b57cec5SDimitry Andric return PreservedAnalyses::all();
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric return PreservedAnalyses::none();
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric }
96