From 86e4445ec3da628f6af0bdc46c16ed6b39173746 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 5 Oct 2003 19:14:42 +0000 Subject: [PATCH] Initial checkin of the LLVM->LLVM transform to support code generators which do not support stack unwinding yet git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8869 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/LowerInvoke.cpp | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lib/Transforms/Utils/LowerInvoke.cpp diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp new file mode 100644 index 00000000000..00d71b21514 --- /dev/null +++ b/lib/Transforms/Utils/LowerInvoke.cpp @@ -0,0 +1,74 @@ +//===- LowerInvoke.cpp - Eliminate Invoke & Unwind instructions -----------===// +// +// This transformation is designed for use by code generators which do not yet +// support stack unwinding. This pass gives them the ability to execute any +// program which does not throw an exception, by turning 'invoke' instructions +// into calls and by turning 'unwind' instructions into calls to abort(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Pass.h" +#include "llvm/iTerminators.h" +#include "llvm/iOther.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Constant.h" +#include "Support/Statistic.h" + +namespace { + Statistic<> NumLowered("lowerinvoke", "Number of invoke & unwinds replaced"); + + class LowerInvoke : public FunctionPass { + Function *AbortFn; + public: + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + }; + + RegisterOpt + X("lowerinvoke", "Lower invoke and unwind, for unwindless code generators"); +} + +FunctionPass *createLowerInvokePass() { return new LowerInvoke(); } + +// doInitialization - Make sure that there is a prototype for abort in the +// current module. +bool LowerInvoke::doInitialization(Module &M) { + AbortFn = M.getOrInsertFunction("abort", Type::VoidTy, 0); + return true; +} + +bool LowerInvoke::runOnFunction(Function &F) { + bool Changed = false; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + if (InvokeInst *II = dyn_cast(I->getTerminator())) { + // Insert a normal call instruction... + std::string Name = II->getName(); II->setName(""); + Value *NewCall = new CallInst(II->getCalledValue(), + std::vector(II->op_begin()+3, + II->op_end()), Name,II); + II->replaceAllUsesWith(NewCall); + + // Insert an unconditional branch to the normal destination + new BranchInst(II->getNormalDest(), II); + + // Remove the invoke instruction now. + I->getInstList().erase(II); + + ++NumLowered; Changed = true; + } else if (UnwindInst *UI = dyn_cast(I->getTerminator())) { + // Insert a call to abort() + new CallInst(AbortFn, std::vector(), "", UI); + + // Insert a return instruction. + new ReturnInst(F.getReturnType() == Type::VoidTy ? 0 : + Constant::getNullValue(F.getReturnType()), UI); + + // Remove the unwind instruction now. + I->getInstList().erase(UI); + + ++NumLowered; Changed = true; + } + return Changed; +}