xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/LowerInvoke.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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