X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTransforms%2FUtils%2FLowerInvoke.cpp;h=9ec84d730e46d8ed4ae95def24852a40078ee8ce;hp=1f6b1a2a684663fd38df2b42403736ec78347704;hb=0b8c9a80f20772c3793201ab5b251d3520b9cea3;hpb=46445389d36d3b8f92b13810e385bcc75642dba1 diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp index 1f6b1a2a684..9ec84d730e4 100644 --- a/lib/Transforms/Utils/LowerInvoke.cpp +++ b/lib/Transforms/Utils/LowerInvoke.cpp @@ -36,198 +36,150 @@ #define DEBUG_TYPE "lowerinvoke" #include "llvm/Transforms/Scalar.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include #include using namespace llvm; STATISTIC(NumInvokes, "Number of invokes replaced"); -STATISTIC(NumUnwinds, "Number of unwinds replaced"); STATISTIC(NumSpilled, "Number of registers live across unwind edges"); static cl::opt ExpensiveEHSupport("enable-correct-eh-support", cl::desc("Make the -lowerinvoke pass insert expensive, but correct, EH code")); namespace { - class VISIBILITY_HIDDEN LowerInvoke : public FunctionPass { + class LowerInvoke : public FunctionPass { // Used for both models. - Constant *WriteFn; Constant *AbortFn; - Value *AbortMessage; - unsigned AbortMessageLength; // Used for expensive EH support. - const Type *JBLinkTy; + StructType *JBLinkTy; GlobalVariable *JBListHead; - Constant *SetJmpFn, *LongJmpFn; + Constant *SetJmpFn, *LongJmpFn, *StackSaveFn, *StackRestoreFn; + bool useExpensiveEHSupport; // We peek in TLI to grab the target's jmp_buf size and alignment const TargetLowering *TLI; public: static char ID; // Pass identification, replacement for typeid - explicit LowerInvoke(const TargetLowering *tli = NULL) - : FunctionPass(&ID), TLI(tli) { } + explicit LowerInvoke(const TargetLowering *tli = NULL, + bool useExpensiveEHSupport = ExpensiveEHSupport) + : FunctionPass(ID), useExpensiveEHSupport(useExpensiveEHSupport), + TLI(tli) { + initializeLowerInvokePass(*PassRegistry::getPassRegistry()); + } bool doInitialization(Module &M); bool runOnFunction(Function &F); virtual void getAnalysisUsage(AnalysisUsage &AU) const { // This is a cluster of orthogonal Transforms - AU.addPreservedID(PromoteMemoryToRegisterID); + AU.addPreserved("mem2reg"); AU.addPreservedID(LowerSwitchID); - AU.addPreservedID(LowerAllocationsID); } private: - void createAbortMessage(Module *M); - void writeAbortMessage(Instruction *IB); bool insertCheapEHSupport(Function &F); - void splitLiveRangesLiveAcrossInvokes(std::vector &Invokes); + void splitLiveRangesLiveAcrossInvokes(SmallVectorImpl&Invokes); void rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, - AllocaInst *InvokeNum, SwitchInst *CatchSwitch); + AllocaInst *InvokeNum, AllocaInst *StackPtr, + SwitchInst *CatchSwitch); bool insertExpensiveEHSupport(Function &F); }; } char LowerInvoke::ID = 0; -static RegisterPass -X("lowerinvoke", "Lower invoke and unwind, for unwindless code generators"); +INITIALIZE_PASS(LowerInvoke, "lowerinvoke", + "Lower invoke and unwind, for unwindless code generators", + false, false) -const PassInfo *const llvm::LowerInvokePassID = &X; +char &llvm::LowerInvokePassID = LowerInvoke::ID; // Public Interface To the LowerInvoke pass. FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI) { - return new LowerInvoke(TLI); + return new LowerInvoke(TLI, ExpensiveEHSupport); +} +FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI, + bool useExpensiveEHSupport) { + return new LowerInvoke(TLI, useExpensiveEHSupport); } // doInitialization - Make sure that there is a prototype for abort in the // current module. bool LowerInvoke::doInitialization(Module &M) { - const Type *VoidPtrTy = PointerType::getUnqual(Type::Int8Ty); - AbortMessage = 0; - if (ExpensiveEHSupport) { + Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); + if (useExpensiveEHSupport) { // Insert a type for the linked list of jump buffers. unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0; JBSize = JBSize ? JBSize : 200; - const Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize); - - { // The type is recursive, so use a type holder. - std::vector Elements; - Elements.push_back(JmpBufTy); - OpaqueType *OT = OpaqueType::get(); - Elements.push_back(PointerType::getUnqual(OT)); - PATypeHolder JBLType(StructType::get(Elements)); - OT->refineAbstractTypeTo(JBLType.get()); // Complete the cycle. - JBLinkTy = JBLType.get(); - M.addTypeName("llvm.sjljeh.jmpbufty", JBLinkTy); - } + Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize); + + JBLinkTy = StructType::create(M.getContext(), "llvm.sjljeh.jmpbufty"); + Type *Elts[] = { JmpBufTy, PointerType::getUnqual(JBLinkTy) }; + JBLinkTy->setBody(Elts); - const Type *PtrJBList = PointerType::getUnqual(JBLinkTy); + Type *PtrJBList = PointerType::getUnqual(JBLinkTy); // Now that we've done that, insert the jmpbuf list head global, unless it // already exists. if (!(JBListHead = M.getGlobalVariable("llvm.sjljeh.jblist", PtrJBList))) { - JBListHead = new GlobalVariable(PtrJBList, false, + JBListHead = new GlobalVariable(M, PtrJBList, false, GlobalValue::LinkOnceAnyLinkage, Constant::getNullValue(PtrJBList), - "llvm.sjljeh.jblist", &M); + "llvm.sjljeh.jblist"); } -// VisualStudio defines setjmp as _setjmp via #include / , -// so it looks like Intrinsic::_setjmp -#if defined(_MSC_VER) && defined(setjmp) -#define setjmp_undefined_for_visual_studio -#undef setjmp +// VisualStudio defines setjmp as _setjmp +#if defined(_MSC_VER) && defined(setjmp) && \ + !defined(setjmp_undefined_for_msvc) +# pragma push_macro("setjmp") +# undef setjmp +# define setjmp_undefined_for_msvc #endif SetJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::setjmp); -#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio) -// let's return it to _setjmp state in case anyone ever needs it after this -// point under VisualStudio -#define setjmp _setjmp +#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc) + // let's return it to _setjmp state +# pragma pop_macro("setjmp") +# undef setjmp_undefined_for_msvc #endif LongJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::longjmp); + StackSaveFn = Intrinsic::getDeclaration(&M, Intrinsic::stacksave); + StackRestoreFn = Intrinsic::getDeclaration(&M, Intrinsic::stackrestore); } // We need the 'write' and 'abort' functions for both models. - AbortFn = M.getOrInsertFunction("abort", Type::VoidTy, (Type *)0); -#if 0 // "write" is Unix-specific.. code is going away soon anyway. - WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::Int32Ty, - VoidPtrTy, Type::Int32Ty, (Type *)0); -#else - WriteFn = 0; -#endif + AbortFn = M.getOrInsertFunction("abort", Type::getVoidTy(M.getContext()), + (Type *)0); return true; } -void LowerInvoke::createAbortMessage(Module *M) { - if (ExpensiveEHSupport) { - // The abort message for expensive EH support tells the user that the - // program 'unwound' without an 'invoke' instruction. - Constant *Msg = - ConstantArray::get("ERROR: Exception thrown, but not caught!\n"); - AbortMessageLength = Msg->getNumOperands()-1; // don't include \0 - - GlobalVariable *MsgGV = new GlobalVariable(Msg->getType(), true, - GlobalValue::InternalLinkage, - Msg, "abortmsg", M); - std::vector GEPIdx(2, Constant::getNullValue(Type::Int32Ty)); - AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2); - } else { - // The abort message for cheap EH support tells the user that EH is not - // enabled. - Constant *Msg = - ConstantArray::get("Exception handler needed, but not enabled. Recompile" - " program with -enable-correct-eh-support.\n"); - AbortMessageLength = Msg->getNumOperands()-1; // don't include \0 - - GlobalVariable *MsgGV = new GlobalVariable(Msg->getType(), true, - GlobalValue::InternalLinkage, - Msg, "abortmsg", M); - std::vector GEPIdx(2, Constant::getNullValue(Type::Int32Ty)); - AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2); - } -} - - -void LowerInvoke::writeAbortMessage(Instruction *IB) { -#if 0 - if (AbortMessage == 0) - createAbortMessage(IB->getParent()->getParent()->getParent()); - - // These are the arguments we WANT... - Value* Args[3]; - Args[0] = ConstantInt::get(Type::Int32Ty, 2); - Args[1] = AbortMessage; - Args[2] = ConstantInt::get(Type::Int32Ty, AbortMessageLength); - (new CallInst(WriteFn, Args, 3, "", IB))->setTailCall(); -#endif -} - bool LowerInvoke::insertCheapEHSupport(Function &F) { bool Changed = false; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (InvokeInst *II = dyn_cast(BB->getTerminator())) { - std::vector CallArgs(II->op_begin()+3, II->op_end()); + SmallVector CallArgs(II->op_begin(), II->op_end() - 3); // Insert a normal call instruction... CallInst *NewCall = CallInst::Create(II->getCalledValue(), - CallArgs.begin(), CallArgs.end(), "",II); + CallArgs, "", 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. @@ -240,22 +192,6 @@ bool LowerInvoke::insertCheapEHSupport(Function &F) { BB->getInstList().erase(II); ++NumInvokes; Changed = true; - } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { - // Insert a new call to write(2, AbortMessage, AbortMessageLength); - writeAbortMessage(UI); - - // Insert a call to abort() - CallInst::Create(AbortFn, "", UI)->setTailCall(); - - // Insert a return instruction. This really should be a "barrier", as it - // is unreachable. - ReturnInst::Create(F.getReturnType() == Type::VoidTy ? 0 : - Constant::getNullValue(F.getReturnType()), UI); - - // Remove the unwind instruction now. - BB->getInstList().erase(UI); - - ++NumUnwinds; Changed = true; } return Changed; } @@ -264,8 +200,10 @@ bool LowerInvoke::insertCheapEHSupport(Function &F) { /// specified invoke instruction with a call. void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, AllocaInst *InvokeNum, + AllocaInst *StackPtr, SwitchInst *CatchSwitch) { - ConstantInt *InvokeNoC = ConstantInt::get(Type::Int32Ty, InvokeNo); + ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo); // If the unwind edge has phi nodes, split the edge. if (isa(II->getUnwindDest()->begin())) { @@ -281,22 +219,33 @@ void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, // Insert a store of the invoke num before the invoke and store zero into the // location afterward. new StoreInst(InvokeNoC, InvokeNum, true, II); // volatile + + // Insert a store of the stack ptr before the invoke, so we can restore it + // later in the exception case. + CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II); + new StoreInst(StackSaveRet, StackPtr, true, II); // volatile - BasicBlock::iterator NI = II->getNormalDest()->getFirstNonPHI(); + BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt(); // nonvolatile. - new StoreInst(Constant::getNullValue(Type::Int32Ty), InvokeNum, false, NI); - + new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), + InvokeNum, false, NI); + + Instruction* StackPtrLoad = + new LoadInst(StackPtr, "stackptr.restore", true, + II->getUnwindDest()->getFirstInsertionPt()); + CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad); + // Add a switch case to our unwind block. CatchSwitch->addCase(InvokeNoC, II->getUnwindDest()); // Insert a normal call instruction. - std::vector CallArgs(II->op_begin()+3, II->op_end()); + SmallVector CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), - CallArgs.begin(), CallArgs.end(), "", - II); + CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); + NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); // Replace the invoke with an uncond branch. @@ -319,7 +268,7 @@ static void MarkBlocksLiveIn(BasicBlock *BB, std::set &LiveBBs) { // across the unwind edge. This process also splits all critical edges // coming out of invoke's. void LowerInvoke:: -splitLiveRangesLiveAcrossInvokes(std::vector &Invokes) { +splitLiveRangesLiveAcrossInvokes(SmallVectorImpl &Invokes) { // First step, split all critical edges from invoke instructions. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { InvokeInst *II = Invokes[i]; @@ -341,16 +290,33 @@ splitLiveRangesLiveAcrossInvokes(std::vector &Invokes) { ++AfterAllocaInsertPt; for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { - // This is always a no-op cast because we're casting AI to AI->getType() so - // src and destination types are identical. BitCast is the only possibility. - CastInst *NC = new BitCastInst( - AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); - AI->replaceAllUsesWith(NC); - // Normally its is forbidden to replace a CastInst's operand because it - // could cause the opcode to reflect an illegal conversion. However, we're - // replacing it here with the same value it was constructed with to simply - // make NC its user. - NC->setOperand(0, AI); + Type *Ty = AI->getType(); + // Aggregate types can't be cast, but are legal argument types, so we have + // to handle them differently. We use an extract/insert pair as a + // lightweight method to achieve the same goal. + if (isa(Ty) || isa(Ty) || isa(Ty)) { + Instruction *EI = ExtractValueInst::Create(AI, 0, "",AfterAllocaInsertPt); + Instruction *NI = InsertValueInst::Create(AI, EI, 0); + NI->insertAfter(EI); + AI->replaceAllUsesWith(NI); + // Set the operand of the instructions back to the AllocaInst. + EI->setOperand(0, AI); + NI->setOperand(0, AI); + } else { + // This is always a no-op cast because we're casting AI to AI->getType() + // so src and destination types are identical. BitCast is the only + // possibility. + CastInst *NC = new BitCastInst( + AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); + AI->replaceAllUsesWith(NC); + // Set the operand of the cast instruction back to the AllocaInst. + // Normally it's forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, + // we're replacing it here with the same value it was constructed with. + // We do this because the above replaceAllUsesWith() clobbered the + // operand, but we want this one to remain. + NC->setOperand(0, AI); + } } // Finally, scan the code looking for instructions with bad live ranges. @@ -372,7 +338,7 @@ splitLiveRangesLiveAcrossInvokes(std::vector &Invokes) { continue; // Avoid iterator invalidation by copying users to a temporary vector. - std::vector Users; + SmallVector Users; for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { Instruction *User = cast(*UI); @@ -422,9 +388,9 @@ splitLiveRangesLiveAcrossInvokes(std::vector &Invokes) { } bool LowerInvoke::insertExpensiveEHSupport(Function &F) { - std::vector Returns; - std::vector Unwinds; - std::vector Invokes; + SmallVector Returns; + SmallVector Invokes; + UnreachableInst* UnreachablePlaceholder = 0; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { @@ -433,14 +399,11 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { Returns.push_back(RI); } else if (InvokeInst *II = dyn_cast(BB->getTerminator())) { Invokes.push_back(II); - } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { - Unwinds.push_back(UI); } - if (Unwinds.empty() && Invokes.empty()) return false; + if (Invokes.empty()) return false; NumInvokes += Invokes.size(); - NumUnwinds += Unwinds.size(); // TODO: This is not an optimal way to do this. In particular, this always // inserts setjmp calls into the entries of functions with invoke instructions @@ -469,13 +432,13 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { // alloca because the value needs to be live across invokes. unsigned Align = TLI ? TLI->getJumpBufAlignment() : 0; AllocaInst *JmpBuf = - new AllocaInst(JBLinkTy, 0, Align, "jblink", F.begin()->begin()); + new AllocaInst(JBLinkTy, 0, Align, + "jblink", F.begin()->begin()); - std::vector Idx; - Idx.push_back(Constant::getNullValue(Type::Int32Ty)); - Idx.push_back(ConstantInt::get(Type::Int32Ty, 1)); - OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx.begin(), Idx.end(), - "OldBuf", EntryBB->getTerminator()); + Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())), + ConstantInt::get(Type::getInt32Ty(F.getContext()), 1) }; + OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "OldBuf", + EntryBB->getTerminator()); // Copy the JBListHead to the alloca. Value *OldBuf = new LoadInst(JBListHead, "oldjmpbufptr", true, @@ -487,20 +450,28 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { // Create the catch block. The catch block is basically a big switch // statement that goes to all of the invoke catch blocks. - BasicBlock *CatchBB = BasicBlock::Create("setjmp.catch", &F); + BasicBlock *CatchBB = + BasicBlock::Create(F.getContext(), "setjmp.catch", &F); + + // Create an alloca which keeps track of the stack pointer before every + // invoke, this allows us to properly restore the stack pointer after + // long jumping. + AllocaInst *StackPtr = new AllocaInst(Type::getInt8PtrTy(F.getContext()), 0, + "stackptr", EntryBB->begin()); // Create an alloca which keeps track of which invoke is currently // executing. For normal calls it contains zero. - AllocaInst *InvokeNum = new AllocaInst(Type::Int32Ty, 0, "invokenum", - EntryBB->begin()); - new StoreInst(ConstantInt::get(Type::Int32Ty, 0), InvokeNum, true, - EntryBB->getTerminator()); + AllocaInst *InvokeNum = new AllocaInst(Type::getInt32Ty(F.getContext()), 0, + "invokenum",EntryBB->begin()); + new StoreInst(ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), + InvokeNum, true, EntryBB->getTerminator()); // Insert a load in the Catch block, and a switch on its value. By default, // we go to a block that just does an unwind (which is the correct action - // for a standard call). - BasicBlock *UnwindBB = BasicBlock::Create("unwindbb", &F); - Unwinds.push_back(new UnwindInst(UnwindBB)); + // for a standard call). We insert an unreachable instruction here and + // modify the block to jump to the correct unwinding pad later. + BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F); + UnreachablePlaceholder = new UnreachableInst(F.getContext(), UnwindBB); Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB); SwitchInst *CatchSwitch = @@ -512,19 +483,20 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), "setjmp.cont"); - Idx[1] = ConstantInt::get(Type::Int32Ty, 0); - Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx.begin(), Idx.end(), - "TheJmpBuf", + Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 0); + Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "TheJmpBuf", EntryBB->getTerminator()); - JmpBufPtr = new BitCastInst(JmpBufPtr, PointerType::getUnqual(Type::Int8Ty), + JmpBufPtr = new BitCastInst(JmpBufPtr, + Type::getInt8PtrTy(F.getContext()), "tmp", EntryBB->getTerminator()); Value *SJRet = CallInst::Create(SetJmpFn, JmpBufPtr, "sjret", EntryBB->getTerminator()); // Compare the return value to zero. - Value *IsNormal = new ICmpInst(ICmpInst::ICMP_EQ, SJRet, + Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), + ICmpInst::ICMP_EQ, SJRet, Constant::getNullValue(SJRet->getType()), - "notunwind", EntryBB->getTerminator()); + "notunwind"); // Nuke the uncond branch. EntryBB->getTerminator()->eraseFromParent(); @@ -533,7 +505,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { // At this point, we are all set up, rewrite each invoke instruction. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) - rewriteExpensiveInvoke(Invokes[i], i+1, InvokeNum, CatchSwitch); + rewriteExpensiveInvoke(Invokes[i], i+1, InvokeNum, StackPtr, CatchSwitch); } // We know that there is at least one unwind. @@ -541,9 +513,10 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { // Create three new blocks, the block to load the jmpbuf ptr and compare // against null, the block to do the longjmp, and the error block for if it // is null. Add them at the end of the function because they are not hot. - BasicBlock *UnwindHandler = BasicBlock::Create("dounwind", &F); - BasicBlock *UnwindBlock = BasicBlock::Create("unwind", &F); - BasicBlock *TermBlock = BasicBlock::Create("unwinderror", &F); + BasicBlock *UnwindHandler = BasicBlock::Create(F.getContext(), + "dounwind", &F); + BasicBlock *UnwindBlock = BasicBlock::Create(F.getContext(), "unwind", &F); + BasicBlock *TermBlock = BasicBlock::Create(F.getContext(), "unwinderror", &F); // If this function contains an invoke, restore the old jumpbuf ptr. Value *BufPtr; @@ -556,39 +529,34 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { } // Load the JBList, if it's null, then there was no catch! - Value *NotNull = new ICmpInst(ICmpInst::ICMP_NE, BufPtr, + Value *NotNull = new ICmpInst(*UnwindHandler, ICmpInst::ICMP_NE, BufPtr, Constant::getNullValue(BufPtr->getType()), - "notnull", UnwindHandler); + "notnull"); BranchInst::Create(UnwindBlock, TermBlock, NotNull, UnwindHandler); // Create the block to do the longjmp. // Get a pointer to the jmpbuf and longjmp. - std::vector Idx; - Idx.push_back(Constant::getNullValue(Type::Int32Ty)); - Idx.push_back(ConstantInt::get(Type::Int32Ty, 0)); - Idx[0] = GetElementPtrInst::Create(BufPtr, Idx.begin(), Idx.end(), "JmpBuf", - UnwindBlock); - Idx[0] = new BitCastInst(Idx[0], PointerType::getUnqual(Type::Int8Ty), + Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())), + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) }; + Idx[0] = GetElementPtrInst::Create(BufPtr, Idx, "JmpBuf", UnwindBlock); + Idx[0] = new BitCastInst(Idx[0], + Type::getInt8PtrTy(F.getContext()), "tmp", UnwindBlock); - Idx[1] = ConstantInt::get(Type::Int32Ty, 1); - CallInst::Create(LongJmpFn, Idx.begin(), Idx.end(), "", UnwindBlock); - new UnreachableInst(UnwindBlock); + Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 1); + CallInst::Create(LongJmpFn, Idx, "", UnwindBlock); + new UnreachableInst(F.getContext(), UnwindBlock); // Set up the term block ("throw without a catch"). - new UnreachableInst(TermBlock); - - // Insert a new call to write(2, AbortMessage, AbortMessageLength); - writeAbortMessage(TermBlock->getTerminator()); + new UnreachableInst(F.getContext(), TermBlock); // Insert a call to abort() CallInst::Create(AbortFn, "", TermBlock->getTerminator())->setTailCall(); - - // Replace all unwinds with a branch to the unwind handler. - for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { - BranchInst::Create(UnwindHandler, Unwinds[i]); - Unwinds[i]->eraseFromParent(); + // Replace the inserted unreachable with a branch to the unwind handler. + if (UnreachablePlaceholder) { + BranchInst::Create(UnwindHandler, UnreachablePlaceholder); + UnreachablePlaceholder->eraseFromParent(); } // Finally, for any returns from this function, if this function contains an @@ -607,7 +575,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) { } bool LowerInvoke::runOnFunction(Function &F) { - if (ExpensiveEHSupport) + if (useExpensiveEHSupport) return insertExpensiveEHSupport(F); else return insertCheapEHSupport(F);