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 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 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 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. 850b57cec5SDimitry Andric FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); } 860b57cec5SDimitry Andric 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