diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/LowerInvoke.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LowerInvoke.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/LowerInvoke.cpp b/llvm/lib/Transforms/Utils/LowerInvoke.cpp new file mode 100644 index 0000000000000..fe67e191dc62a --- /dev/null +++ b/llvm/lib/Transforms/Utils/LowerInvoke.cpp @@ -0,0 +1,96 @@ +//===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This transformation is designed for use by code generators which do not yet +// support stack unwinding. This pass converts 'invoke' instructions to 'call' +// instructions, so that any exception-handling 'landingpad' blocks become dead +// code (which can be removed by running the '-simplifycfg' pass afterwards). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/LowerInvoke.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils.h" +using namespace llvm; + +#define DEBUG_TYPE "lowerinvoke" + +STATISTIC(NumInvokes, "Number of invokes replaced"); + +namespace { + class LowerInvokeLegacyPass : public FunctionPass { + public: + static char ID; // Pass identification, replacement for typeid + explicit LowerInvokeLegacyPass() : FunctionPass(ID) { + initializeLowerInvokeLegacyPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + }; +} + +char LowerInvokeLegacyPass::ID = 0; +INITIALIZE_PASS(LowerInvokeLegacyPass, "lowerinvoke", + "Lower invoke and unwind, for unwindless code generators", + false, false) + +static bool runImpl(Function &F) { + bool Changed = false; + for (BasicBlock &BB : F) + if (InvokeInst *II = dyn_cast<InvokeInst>(BB.getTerminator())) { + SmallVector<Value *, 16> CallArgs(II->arg_begin(), II->arg_end()); + SmallVector<OperandBundleDef, 1> OpBundles; + II->getOperandBundlesAsDefs(OpBundles); + // Insert a normal call instruction... + CallInst *NewCall = + CallInst::Create(II->getFunctionType(), II->getCalledValue(), + CallArgs, OpBundles, "", II); + NewCall->takeName(II); + NewCall->setCallingConv(II->getCallingConv()); + NewCall->setAttributes(II->getAttributes()); + NewCall->setDebugLoc(II->getDebugLoc()); + II->replaceAllUsesWith(NewCall); + + // Insert an unconditional branch to the normal destination. + BranchInst::Create(II->getNormalDest(), II); + + // Remove any PHI node entries from the exception destination. + II->getUnwindDest()->removePredecessor(&BB); + + // Remove the invoke instruction now. + BB.getInstList().erase(II); + + ++NumInvokes; + Changed = true; + } + return Changed; +} + +bool LowerInvokeLegacyPass::runOnFunction(Function &F) { + return runImpl(F); +} + +namespace llvm { +char &LowerInvokePassID = LowerInvokeLegacyPass::ID; + +// Public Interface To the LowerInvoke pass. +FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); } + +PreservedAnalyses LowerInvokePass::run(Function &F, + FunctionAnalysisManager &AM) { + bool Changed = runImpl(F); + if (!Changed) + return PreservedAnalyses::all(); + + return PreservedAnalyses::none(); +} +} |