Add a call to 'write' right before the call to abort() in the unwind path.
[oota-llvm.git] / lib / Transforms / Utils / LowerInvoke.cpp
1 //===- LowerInvoke.cpp - Eliminate Invoke & Unwind instructions -----------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This transformation is designed for use by code generators which do not yet
11 // support stack unwinding.  This pass gives them the ability to execute any
12 // program which does not throw an exception, by turning 'invoke' instructions
13 // into calls and by turning 'unwind' instructions into calls to abort().
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "llvm/Transforms/Scalar.h"
18 #include "llvm/Constants.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Module.h"
21 #include "llvm/Pass.h"
22 #include "llvm/iTerminators.h"
23 #include "llvm/iOther.h"
24 #include "Support/Statistic.h"
25 using namespace llvm;
26
27 namespace {
28   Statistic<> NumLowered("lowerinvoke", "Number of invoke & unwinds replaced");
29
30   class LowerInvoke : public FunctionPass {
31     Value *AbortMessage;
32     unsigned AbortMessageLength;
33     Function *WriteFn;
34     Function *AbortFn;
35   public:
36     bool doInitialization(Module &M);
37     bool runOnFunction(Function &F);
38   };
39
40   RegisterOpt<LowerInvoke>
41   X("lowerinvoke", "Lower invoke and unwind, for unwindless code generators");
42 }
43
44 // Public Interface To the LowerInvoke pass.
45 FunctionPass *llvm::createLowerInvokePass() { return new LowerInvoke(); }
46
47 // doInitialization - Make sure that there is a prototype for abort in the
48 // current module.
49 bool LowerInvoke::doInitialization(Module &M) {
50   Constant *Msg =
51     ConstantArray::get("Exception handler needed, but not available.\n");
52   AbortMessageLength = Msg->getNumOperands()-1;  // don't include \0
53   
54   GlobalVariable *MsgGV =
55     new GlobalVariable(Msg->getType(), true, GlobalValue::InternalLinkage, Msg,
56                        "", &M);
57   std::vector<Constant*> GEPIdx(2, Constant::getNullValue(Type::LongTy));
58   AbortMessage =
59     ConstantExpr::getGetElementPtr(ConstantPointerRef::get(MsgGV), GEPIdx);
60
61   AbortFn = M.getOrInsertFunction("abort", Type::VoidTy, 0);
62   WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::IntTy,
63                                   PointerType::get(Type::SByteTy), Type::IntTy,
64                                   0);
65   return true;
66 }
67
68 bool LowerInvoke::runOnFunction(Function &F) {
69   bool Changed = false;
70   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
71     if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
72       // Insert a normal call instruction...
73       std::string Name = II->getName(); II->setName("");
74       Value *NewCall = new CallInst(II->getCalledValue(),
75                                     std::vector<Value*>(II->op_begin()+3,
76                                                         II->op_end()), Name,II);
77       II->replaceAllUsesWith(NewCall);
78       
79       // Insert an unconditional branch to the normal destination.
80       new BranchInst(II->getNormalDest(), II);
81
82       // Remove any PHI node entries from the exception destination.
83       II->getExceptionalDest()->removePredecessor(BB);
84
85       // Remove the invoke instruction now.
86       BB->getInstList().erase(II);
87
88       ++NumLowered; Changed = true;
89     } else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
90       // Insert a new call to write(2, AbortMessage, AbortMessageLength);
91       std::vector<Value*> Args;
92       Args.push_back(ConstantInt::get(Type::IntTy, 2));
93       Args.push_back(AbortMessage);
94       Args.push_back(ConstantInt::get(Type::IntTy, AbortMessageLength));
95       new CallInst(WriteFn, Args, "", UI);
96
97       // Insert a call to abort()
98       new CallInst(AbortFn, std::vector<Value*>(), "", UI);
99
100       // Insert a return instruction.
101       new ReturnInst(F.getReturnType() == Type::VoidTy ? 0 :
102                             Constant::getNullValue(F.getReturnType()), UI);
103
104       // Remove the unwind instruction now.
105       BB->getInstList().erase(UI);
106
107       ++NumLowered; Changed = true;
108     }
109   return Changed;
110 }