X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSjLjEHPrepare.cpp;h=5412c97ef5e1b0ab27fe57d75edb46fdb096a066;hb=9eb5f170a219decc4ee07b57b0403d3836a8d946;hp=58b5213a0ea1a2da7dea2cf05568c3cfe91b65e8;hpb=606f3d696ff78211524fa49c3ca0c4de6db37041;p=oota-llvm.git diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp index 58b5213a0ea..5412c97ef5e 100644 --- a/lib/CodeGen/SjLjEHPrepare.cpp +++ b/lib/CodeGen/SjLjEHPrepare.cpp @@ -22,57 +22,60 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/IRBuilder.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#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"); namespace { - class VISIBILITY_HIDDEN SjLjEHPass : public FunctionPass { - + class SjLjEHPass : public FunctionPass { const TargetLowering *TLI; - - const Type *FunctionContextTy; + Type *FunctionContextTy; Constant *RegisterFn; Constant *UnregisterFn; - Constant *ResumeFn; Constant *BuiltinSetjmpFn; Constant *FrameAddrFn; + Constant *StackAddrFn; + Constant *StackRestoreFn; Constant *LSDAAddrFn; Value *PersonalityFn; - Constant *Selector32Fn; - Constant *Selector64Fn; - Constant *ExceptionFn; - - Value *CallSite; + Constant *CallSiteFn; + Constant *FuncCtxFn; + AllocaInst *FuncCtx; public: static char ID; // Pass identification, replacement for typeid explicit SjLjEHPass(const TargetLowering *tli = NULL) - : FunctionPass(&ID), TLI(tli) { } + : FunctionPass(ID), TLI(tli) { } bool doInitialization(Module &M); bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const { } + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} const char *getPassName() const { return "SJLJ Exception Handling preparation"; } private: - void markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, - Value *CallSite, - SwitchInst *CatchSwitch); - void splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes); - bool insertSjLjEHSupport(Function &F); + bool setupEntryBlockAndCallSites(Function &F); + void substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, + Value *SelVal); + Value *setupFunctionContext(Function &F, ArrayRef LPads); + void lowerIncomingArguments(Function &F); + void lowerAcrossUnwindEdges(Function &F, ArrayRef Invokes); + void insertCallSiteStore(Instruction *I, int Number); }; } // end anonymous namespace @@ -82,17 +85,15 @@ char SjLjEHPass::ID = 0; FunctionPass *llvm::createSjLjEHPass(const TargetLowering *TLI) { return new SjLjEHPass(TLI); } -// doInitialization - Make sure that there is a prototype for abort in the -// current module. +// doInitialization - Set up decalarations and types needed to process +// exceptions. bool SjLjEHPass::doInitialization(Module &M) { // Build the function context structure. // builtin_setjmp uses a five word jbuf - const Type *VoidPtrTy = - PointerType::getUnqual(Type::getInt8Ty(M.getContext())); - const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); + Type *Int32Ty = Type::getInt32Ty(M.getContext()); FunctionContextTy = - StructType::get(M.getContext(), - VoidPtrTy, // __prev + StructType::get(VoidPtrTy, // __prev Int32Ty, // call_site ArrayType::get(Int32Ty, 4), // __data VoidPtrTy, // __personality @@ -108,108 +109,202 @@ bool SjLjEHPass::doInitialization(Module &M) { Type::getVoidTy(M.getContext()), PointerType::getUnqual(FunctionContextTy), (Type *)0); - ResumeFn = - M.getOrInsertFunction("_Unwind_SjLj_Resume", - Type::getVoidTy(M.getContext()), - VoidPtrTy, - (Type *)0); FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress); + StackAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::stacksave); + StackRestoreFn = Intrinsic::getDeclaration(&M, Intrinsic::stackrestore); BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp); LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); - Selector32Fn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector_i32); - Selector64Fn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector_i64); - ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception); + CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite); + FuncCtxFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_functioncontext); + PersonalityFn = 0; return true; } -/// markInvokeCallSite - Insert code to mark the call_site for this invoke -void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, - Value *CallSite, - SwitchInst *CatchSwitch) { - ConstantInt *CallSiteNoC= ConstantInt::get(Type::getInt32Ty(II->getContext()), - InvokeNo); - // The runtime comes back to the dispatcher with the call_site - 1 in - // the context. Odd, but there it is. - ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()), - InvokeNo - 1); - - // If the unwind edge has phi nodes, split the edge. - if (isa(II->getUnwindDest()->begin())) { - SplitCriticalEdge(II, 1, this); - - // If there are any phi nodes left, they must have a single predecessor. - while (PHINode *PN = dyn_cast(II->getUnwindDest()->begin())) { - PN->replaceAllUsesWith(PN->getIncomingValue(0)); - PN->eraseFromParent(); - } - } - - // Insert a store of the invoke num before the invoke and store zero into the - // location afterward. - new StoreInst(CallSiteNoC, CallSite, true, II); // volatile - - // Add a switch case to our unwind block. - CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); - // We still want this to look like an invoke so we emit the LSDA properly - // FIXME: ??? Or will this cause strangeness with mis-matched IDs like - // when it was in the front end? +/// insertCallSiteStore - Insert a store of the call-site value to the +/// function context +void SjLjEHPass::insertCallSiteStore(Instruction *I, int Number) { + IRBuilder<> Builder(I); + + // Get a reference to the call_site field. + Type *Int32Ty = Type::getInt32Ty(I->getContext()); + Value *Zero = ConstantInt::get(Int32Ty, 0); + Value *One = ConstantInt::get(Int32Ty, 1); + Value *Idxs[2] = { Zero, One }; + Value *CallSite = Builder.CreateGEP(FuncCtx, Idxs, "call_site"); + + // Insert a store of the call-site number + ConstantInt *CallSiteNoC = ConstantInt::get(Type::getInt32Ty(I->getContext()), + Number); + Builder.CreateStore(CallSiteNoC, CallSite, true/*volatile*/); } /// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until /// we reach blocks we've already seen. -static void MarkBlocksLiveIn(BasicBlock *BB, std::set &LiveBBs) { - if (!LiveBBs.insert(BB).second) return; // already been here. +static void MarkBlocksLiveIn(BasicBlock *BB, + SmallPtrSet &LiveBBs) { + if (!LiveBBs.insert(BB)) return; // already been here. for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) MarkBlocksLiveIn(*PI, LiveBBs); } -/// splitLiveRangesAcrossInvokes - Each value that is live across an unwind edge -/// we spill into a stack location, guaranteeing that there is nothing live -/// across the unwind edge. This process also splits all critical edges -/// coming out of invoke's. -void SjLjEHPass:: -splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes) { - // First step, split all critical edges from invoke instructions. - for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { - InvokeInst *II = Invokes[i]; - SplitCriticalEdge(II, 0, this); - SplitCriticalEdge(II, 1, this); - assert(!isa(II->getNormalDest()) && - !isa(II->getUnwindDest()) && - "critical edge splitting left single entry phi nodes?"); +/// substituteLPadValues - Substitute the values returned by the landingpad +/// instruction with those returned by the personality function. +void SjLjEHPass::substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, + Value *SelVal) { + SmallVector UseWorkList(LPI->use_begin(), LPI->use_end()); + while (!UseWorkList.empty()) { + Value *Val = UseWorkList.pop_back_val(); + ExtractValueInst *EVI = dyn_cast(Val); + if (!EVI) continue; + if (EVI->getNumIndices() != 1) continue; + if (*EVI->idx_begin() == 0) + EVI->replaceAllUsesWith(ExnVal); + else if (*EVI->idx_begin() == 1) + EVI->replaceAllUsesWith(SelVal); + if (EVI->getNumUses() == 0) + EVI->eraseFromParent(); } - Function *F = Invokes.back()->getParent()->getParent(); - - // To avoid having to handle incoming arguments specially, we lower each arg - // to a copy instruction in the entry block. This ensures that the argument - // value itself cannot be live across the entry block. - BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); - while (isa(AfterAllocaInsertPt) && - isa(cast(AfterAllocaInsertPt)->getArraySize())) - ++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); + if (LPI->getNumUses() == 0) return; + + // There are still some uses of LPI. Construct an aggregate with the exception + // values and replace the LPI with that aggregate. + Type *LPadType = LPI->getType(); + Value *LPadVal = UndefValue::get(LPadType); + IRBuilder<> + Builder(llvm::next(BasicBlock::iterator(cast(SelVal)))); + LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0, "lpad.val"); + LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1, "lpad.val"); + + LPI->replaceAllUsesWith(LPadVal); +} + +/// setupFunctionContext - Allocate the function context on the stack and fill +/// it with all of the data that we know at this point. +Value *SjLjEHPass:: +setupFunctionContext(Function &F, ArrayRef LPads) { + BasicBlock *EntryBB = F.begin(); + + // Create an alloca for the incoming jump buffer ptr and the new jump buffer + // that needs to be restored on all exits from the function. This is an alloca + // because the value needs to be added to the global context list. + unsigned Align = + TLI->getTargetData()->getPrefTypeAlignment(FunctionContextTy); + FuncCtx = + new AllocaInst(FunctionContextTy, 0, Align, "fn_context", EntryBB->begin()); + + // Fill in the function context structure. + Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Value *Zero = ConstantInt::get(Int32Ty, 0); + Value *One = ConstantInt::get(Int32Ty, 1); + Value *Two = ConstantInt::get(Int32Ty, 2); + Value *Three = ConstantInt::get(Int32Ty, 3); + Value *Four = ConstantInt::get(Int32Ty, 4); + + Value *Idxs[2] = { Zero, 0 }; + + for (unsigned I = 0, E = LPads.size(); I != E; ++I) { + LandingPadInst *LPI = LPads[I]; + IRBuilder<> Builder(LPI->getParent()->getFirstInsertionPt()); + + // Reference the __data field. + Idxs[1] = Two; + Value *FCData = Builder.CreateGEP(FuncCtx, Idxs, "__data"); + + // The exception values come back in context->__data[0]. + Idxs[1] = Zero; + Value *ExceptionAddr = Builder.CreateGEP(FCData, Idxs, "exception_gep"); + Value *ExnVal = Builder.CreateLoad(ExceptionAddr, true, "exn_val"); + ExnVal = Builder.CreateIntToPtr(ExnVal, Type::getInt8PtrTy(F.getContext())); + + Idxs[1] = One; + Value *SelectorAddr = Builder.CreateGEP(FCData, Idxs, "exn_selector_gep"); + Value *SelVal = Builder.CreateLoad(SelectorAddr, true, "exn_selector_val"); + + substituteLPadValues(LPI, ExnVal, SelVal); } + // Personality function + Idxs[1] = Three; + if (!PersonalityFn) + PersonalityFn = LPads[0]->getPersonalityFn(); + Value *PersonalityFieldPtr = + GetElementPtrInst::Create(FuncCtx, Idxs, "pers_fn_gep", + EntryBB->getTerminator()); + new StoreInst(PersonalityFn, PersonalityFieldPtr, true, + EntryBB->getTerminator()); + + // LSDA address + Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", + EntryBB->getTerminator()); + Idxs[1] = Four; + Value *LSDAFieldPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "lsda_gep", + EntryBB->getTerminator()); + new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); + + return FuncCtx; +} + +/// lowerIncomingArguments - To avoid having to handle incoming arguments +/// specially, we lower each arg to a copy instruction in the entry block. This +/// ensures that the argument value itself cannot be live out of the entry +/// block. +void SjLjEHPass::lowerIncomingArguments(Function &F) { + BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); + while (isa(AfterAllocaInsPt) && + isa(cast(AfterAllocaInsPt)->getArraySize())) + ++AfterAllocaInsPt; + + for (Function::arg_iterator + AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++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, "", AfterAllocaInsPt); + 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", + AfterAllocaInsPt); + 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); + } + } +} + +/// lowerAcrossUnwindEdges - Find all variables which are alive across an unwind +/// edge and spill them. +void SjLjEHPass::lowerAcrossUnwindEdges(Function &F, + ArrayRef Invokes) { // Finally, scan the code looking for instructions with bad live ranges. - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) - for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { - // Ignore obvious cases we don't have to handle. In particular, most + for (Function::iterator + BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) { + for (BasicBlock::iterator + II = BB->begin(), IIE = BB->end(); II != IIE; ++II) { + // Ignore obvious cases we don't have to handle. In particular, most // instructions either have no uses or only have a single use inside the - // current block. Ignore them quickly. + // current block. Ignore them quickly. Instruction *Inst = II; if (Inst->use_empty()) continue; if (Inst->hasOneUse() && @@ -219,20 +314,20 @@ splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes) { // If this is an alloca in the entry block, it's not a real register // value. if (AllocaInst *AI = dyn_cast(Inst)) - if (isa(AI->getArraySize()) && BB == F->begin()) + if (isa(AI->getArraySize()) && BB == F.begin()) continue; // Avoid iterator invalidation by copying users to a temporary vector. - SmallVector Users; - for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); - UI != E; ++UI) { + SmallVector Users; + for (Value::use_iterator + UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { Instruction *User = cast(*UI); if (User->getParent() != BB || isa(User)) Users.push_back(User); } // Find all of the blocks that this value is live in. - std::set LiveBBs; + SmallPtrSet LiveBBs; LiveBBs.insert(Inst->getParent()); while (!Users.empty()) { Instruction *U = Users.back(); @@ -255,265 +350,176 @@ splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes) { for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + DEBUG(dbgs() << "SJLJ Spill: " << *Inst << " around " + << UnwindBlock->getName() << "\n"); NeedsSpill = true; + break; } } // If we decided we need a spill, do it. + // FIXME: Spilling this way is overkill, as it forces all uses of + // the value to be reloaded from the stack slot, even those that aren't + // in the unwind blocks. We should be more selective. if (NeedsSpill) { - ++NumSpilled; DemoteRegToStack(*Inst, true); + ++NumSpilled; } } + } + + // Go through the landing pads and remove any PHIs there. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); + LandingPadInst *LPI = UnwindBlock->getLandingPadInst(); + + // Place PHIs into a set to avoid invalidating the iterator. + SmallPtrSet PHIsToDemote; + for (BasicBlock::iterator + PN = UnwindBlock->begin(); isa(PN); ++PN) + PHIsToDemote.insert(cast(PN)); + if (PHIsToDemote.empty()) continue; + + // Demote the PHIs to the stack. + for (SmallPtrSet::iterator + I = PHIsToDemote.begin(), E = PHIsToDemote.end(); I != E; ++I) + DemotePHIToStack(*I); + + // Move the landingpad instruction back to the top of the landing pad block. + LPI->moveBefore(UnwindBlock->begin()); + } } -bool SjLjEHPass::insertSjLjEHSupport(Function &F) { - SmallVector Returns; - SmallVector Unwinds; - SmallVector Invokes; +/// setupEntryBlockAndCallSites - Setup the entry block by creating and filling +/// the function context and marking the call sites with the appropriate +/// values. These values are used by the DWARF EH emitter. +bool SjLjEHPass::setupEntryBlockAndCallSites(Function &F) { + SmallVector Returns; + SmallVector Invokes; + SmallSetVector LPads; - // Look through the terminators of the basic blocks to find invokes, returns - // and unwinds + // Look through the terminators of the basic blocks to find invokes. for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - // Remember all return instructions in case we insert an invoke into this - // function. - Returns.push_back(RI); - } else if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + if (InvokeInst *II = dyn_cast(BB->getTerminator())) { Invokes.push_back(II); - } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { - Unwinds.push_back(UI); + LPads.insert(II->getUnwindDest()->getLandingPadInst()); + } else if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + Returns.push_back(RI); } - // If we don't have any invokes or unwinds, there's nothing to do. - if (Unwinds.empty() && Invokes.empty()) return false; - NumInvokes += Invokes.size(); - NumUnwinds += Unwinds.size(); - - - if (!Invokes.empty()) { - // We have invokes, so we need to add register/unregister calls to get - // this function onto the global unwind stack. - // - // First thing we need to do is scan the whole function for values that are - // live across unwind edges. Each value that is live across an unwind edge - // we spill into a stack location, guaranteeing that there is nothing live - // across the unwind edge. This process also splits all critical edges - // coming out of invoke's. - splitLiveRangesLiveAcrossInvokes(Invokes); - - BasicBlock *EntryBB = F.begin(); - // Create an alloca for the incoming jump buffer ptr and the new jump buffer - // that needs to be restored on all exits from the function. This is an - // alloca because the value needs to be added to the global context list. - unsigned Align = 4; // FIXME: Should be a TLI check? - AllocaInst *FunctionContext = - new AllocaInst(FunctionContextTy, 0, Align, - "fcn_context", F.begin()->begin()); - - Value *Idxs[2]; - const Type *Int32Ty = Type::getInt32Ty(F.getContext()); - Value *Zero = ConstantInt::get(Int32Ty, 0); - // We need to also keep around a reference to the call_site field - Idxs[0] = Zero; - Idxs[1] = ConstantInt::get(Int32Ty, 1); - CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "call_site", - EntryBB->getTerminator()); - - // The exception selector comes back in context->data[1] - Idxs[1] = ConstantInt::get(Int32Ty, 2); - Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "fc_data", - EntryBB->getTerminator()); - Idxs[1] = ConstantInt::get(Int32Ty, 1); - Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, - "exc_selector_gep", - EntryBB->getTerminator()); - // The exception value comes back in context->data[0] - Idxs[1] = Zero; - Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, - "exception_gep", - EntryBB->getTerminator()); - - // Find the eh.selector.* and eh.exception calls. We'll use the first - // ex.selector to determine the right personality function to use. For - // SJLJ, we always use the same personality for the whole function, - // not on a per-selector basis. - // FIXME: That's a bit ugly. Better way? - SmallVector EH_Selectors; - SmallVector EH_Exceptions; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - if (CallInst *CI = dyn_cast(I)) { - if (CI->getCalledFunction() == Selector32Fn || - CI->getCalledFunction() == Selector64Fn) { - if (!PersonalityFn) PersonalityFn = CI->getOperand(2); - EH_Selectors.push_back(CI); - } else if (CI->getCalledFunction() == ExceptionFn) { - EH_Exceptions.push_back(CI); - } - } - } - } - // The result of the eh.selector call will be replaced with a - // a reference to the selector value returned in the function - // context. We leave the selector itself so the EH analysis later - // can use it. - for (int i = 0, e = EH_Selectors.size(); i < e; ++i) { - CallInst *I = EH_Selectors[i]; - Value *SelectorVal = new LoadInst(SelectorAddr, "select_val", true, I); - I->replaceAllUsesWith(SelectorVal); - } - // eh.exception calls are replaced with references to the proper - // location in the context. Unlike eh.selector, the eh.exception - // calls are removed entirely. - for (int i = 0, e = EH_Exceptions.size(); i < e; ++i) { - CallInst *I = EH_Exceptions[i]; - // Possible for there to be duplicates, so check to make sure - // the instruction hasn't already been removed. - if (!I->getParent()) continue; - Value *Val = new LoadInst(ExceptionAddr, "exception", true, I); - Type *Ty = PointerType::getUnqual(Type::getInt8Ty(F.getContext())); - Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I); - - I->replaceAllUsesWith(Val); - I->eraseFromParent(); - } + if (Invokes.empty()) return false; + NumInvokes += Invokes.size(); + lowerIncomingArguments(F); + lowerAcrossUnwindEdges(F, Invokes); + Value *FuncCtx = + setupFunctionContext(F, makeArrayRef(LPads.begin(), LPads.end())); + BasicBlock *EntryBB = F.begin(); + Type *Int32Ty = Type::getInt32Ty(F.getContext()); - // The entry block changes to have the eh.sjlj.setjmp, with a conditional - // branch to a dispatch block for non-zero returns. If we return normally, - // we're not handling an exception and just register the function context - // and continue. + Value *Idxs[2] = { + ConstantInt::get(Int32Ty, 0), 0 + }; - // Create the dispatch block. The dispatch block is basically a big switch - // statement that goes to all of the invoke landing pads. - BasicBlock *DispatchBlock = - BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); + // Get a reference to the jump buffer. + Idxs[1] = ConstantInt::get(Int32Ty, 5); + Value *JBufPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "jbuf_gep", + 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 *UnwindBlock = BasicBlock::Create(F.getContext(), "unwindbb", &F); - Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock)); + // Save the frame pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 0); + Value *FramePtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep", + EntryBB->getTerminator()); - Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, - DispatchBlock); - SwitchInst *DispatchSwitch = - SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(), DispatchBlock); - // Split the entry block to insert the conditional branch for the setjmp. - BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), - "eh.sjlj.setjmp.cont"); + Value *Val = CallInst::Create(FrameAddrFn, + ConstantInt::get(Int32Ty, 0), + "fp", + EntryBB->getTerminator()); + new StoreInst(Val, FramePtr, true, EntryBB->getTerminator()); - // Populate the Function Context - // 1. LSDA address - // 2. Personality function address - // 3. jmpbuf (save FP and call eh.sjlj.setjmp) + // Save the stack pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *StackPtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep", + EntryBB->getTerminator()); - // LSDA address - Idxs[0] = Zero; - Idxs[1] = ConstantInt::get(Int32Ty, 4); - Value *LSDAFieldPtr = - GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "lsda_gep", - EntryBB->getTerminator()); - Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", - EntryBB->getTerminator()); - new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); - - Idxs[1] = ConstantInt::get(Int32Ty, 3); - Value *PersonalityFieldPtr = - GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "lsda_gep", - EntryBB->getTerminator()); - new StoreInst(PersonalityFn, PersonalityFieldPtr, true, - EntryBB->getTerminator()); - - // Save the frame pointer. - Idxs[1] = ConstantInt::get(Int32Ty, 5); - Value *FieldPtr - = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "jbuf_gep", - EntryBB->getTerminator()); - Idxs[1] = ConstantInt::get(Int32Ty, 0); - Value *ElemPtr = - GetElementPtrInst::Create(FieldPtr, Idxs, Idxs+2, "jbuf_fp_gep", - EntryBB->getTerminator()); + Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); + new StoreInst(Val, StackPtr, true, EntryBB->getTerminator()); + + // Call the setjmp instrinsic. It fills in the rest of the jmpbuf. + Value *SetjmpArg = CastInst::Create(Instruction::BitCast, JBufPtr, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "", EntryBB->getTerminator()); + + // Store a pointer to the function context so that the back-end will know + // where to look for it. + Value *FuncCtxArg = CastInst::Create(Instruction::BitCast, FuncCtx, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + CallInst::Create(FuncCtxFn, FuncCtxArg, "", EntryBB->getTerminator()); + + // At this point, we are all set up, update the invoke instructions to mark + // their call_site values. + for (unsigned I = 0, E = Invokes.size(); I != E; ++I) { + insertCallSiteStore(Invokes[I], I + 1); + + ConstantInt *CallSiteNum = + ConstantInt::get(Type::getInt32Ty(F.getContext()), I + 1); + + // Record the call site value for the back end so it stays associated with + // the invoke. + CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]); + } - Value *Val = CallInst::Create(FrameAddrFn, - ConstantInt::get(Int32Ty, 0), - "fp", - EntryBB->getTerminator()); - new StoreInst(Val, ElemPtr, true, EntryBB->getTerminator()); - // Call the setjmp instrinsic. It fills in the rest of the jmpbuf - Value *SetjmpArg = - CastInst::Create(Instruction::BitCast, FieldPtr, - Type::getInt8Ty(F.getContext())->getPointerTo(), "", - EntryBB->getTerminator()); - Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, - "dispatch", - EntryBB->getTerminator()); - // check the return value of the setjmp. non-zero goes to dispatcher - Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), - ICmpInst::ICMP_EQ, DispatchVal, Zero, - "notunwind"); - // Nuke the uncond branch. - EntryBB->getTerminator()->eraseFromParent(); - - // Put in a new condbranch in its place. - BranchInst::Create(ContBlock, DispatchBlock, IsNormal, EntryBB); - - // Register the function context and make sure it's known to not throw - CallInst *Register = - CallInst::Create(RegisterFn, FunctionContext, "", - ContBlock->getTerminator()); - Register->setDoesNotThrow(); - - // At this point, we are all set up, update the invoke instructions - // to mark their call_site values, and fill in the dispatch switch - // accordingly. - for (unsigned i = 0, e = Invokes.size(); i != e; ++i) - markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch); - - // The front end has likely added calls to _Unwind_Resume. We need - // to find those calls and mark the call_site as -1 immediately prior. - // resume is a noreturn function, so any block that has a call to it - // should end in an 'unreachable' instruction with the call immediately - // prior. That's how we'll search. - // ??? There's got to be a better way. this is fugly. - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if ((dyn_cast(BB->getTerminator()))) { - BasicBlock::iterator I = BB->getTerminator(); - // Check the previous instruction and see if it's a resume call - if (I == BB->begin()) continue; - if (CallInst *CI = dyn_cast(--I)) { - if (CI->getCalledFunction() == ResumeFn) { - Value *NegativeOne = Constant::getAllOnesValue(Int32Ty); - new StoreInst(NegativeOne, CallSite, true, I); // volatile - } - } + // Mark call instructions that aren't nounwind as no-action (call_site == + // -1). Skip the entry block, as prior to then, no function context has been + // created for this function and any unexpected exceptions thrown will go + // directly to the caller's context, which is what we want anyway, so no need + // to do anything here. + for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) + for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I) + if (CallInst *CI = dyn_cast(I)) { + if (!CI->doesNotThrow()) + insertCallSiteStore(CI, -1); + } else if (ResumeInst *RI = dyn_cast(I)) { + insertCallSiteStore(RI, -1); } - // Replace all unwinds with a branch to the unwind handler. - // ??? Should this ever happen with sjlj exceptions? - for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { - BranchInst::Create(UnwindBlock, Unwinds[i]); - Unwinds[i]->eraseFromParent(); + // Register the function context and make sure it's known to not throw + CallInst *Register = CallInst::Create(RegisterFn, FuncCtx, "", + EntryBB->getTerminator()); + Register->setDoesNotThrow(); + + // Following any allocas not in the entry block, update the saved SP in the + // jmpbuf to the new value. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (BB == F.begin()) + continue; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + if (CallInst *CI = dyn_cast(I)) { + if (CI->getCalledFunction() != StackRestoreFn) + continue; + } else if (!isa(I)) { + continue; + } + Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp"); + StackAddr->insertAfter(I); + Instruction *StoreStackAddr = new StoreInst(StackAddr, StackPtr, true); + StoreStackAddr->insertAfter(StackAddr); } - - // Finally, for any returns from this function, if this function contains an - // invoke, add a call to unregister the function context. - for (unsigned i = 0, e = Returns.size(); i != e; ++i) - CallInst::Create(UnregisterFn, FunctionContext, "", Returns[i]); } + // Finally, for any returns from this function, if this function contains an + // invoke, add a call to unregister the function context. + for (unsigned I = 0, E = Returns.size(); I != E; ++I) + CallInst::Create(UnregisterFn, FuncCtx, "", Returns[I]); + return true; } bool SjLjEHPass::runOnFunction(Function &F) { - bool Res = insertSjLjEHSupport(F); + bool Res = setupEntryBlockAndCallSites(F); return Res; }