bool LowerEmExceptions::runOnModule(Module &M) { TheModule = &M; // Add functions Type *i32 = Type::getInt32Ty(M.getContext()); Type *i8 = Type::getInt8Ty(M.getContext()); Type *i1 = Type::getInt1Ty(M.getContext()); Type *i8P = i8->getPointerTo(); Type *Void = Type::getVoidTy(M.getContext()); if (!(GetHigh = TheModule->getFunction("getHigh32"))) { FunctionType *GetHighFunc = FunctionType::get(i32, false); GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, "getHigh32", TheModule); } if (!(PreInvoke = TheModule->getFunction("emscripten_preinvoke"))) { FunctionType *VoidFunc = FunctionType::get(Void, false); PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "emscripten_preinvoke", TheModule); } if (!(PostInvoke = TheModule->getFunction("emscripten_postinvoke"))) { FunctionType *IntFunc = FunctionType::get(i32, false); PostInvoke = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "emscripten_postinvoke", TheModule); } FunctionType *LandingPadFunc = FunctionType::get(i8P, true); LandingPad = Function::Create(LandingPadFunc, GlobalValue::ExternalLinkage, "emscripten_landingpad", TheModule); FunctionType *ResumeFunc = FunctionType::get(Void, true); Resume = Function::Create(ResumeFunc, GlobalValue::ExternalLinkage, "emscripten_resume", TheModule); // Process bool HasWhitelist = Whitelist.size() > 0; std::string WhitelistChecker; if (HasWhitelist) WhitelistChecker = "," + Whitelist + ","; bool Changed = false; for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { Function *F = Iter++; std::vector<Instruction*> ToErase; std::set<LandingPadInst*> LandingPads; bool AllowExceptionsInFunc = !HasWhitelist || int(WhitelistChecker.find(F->getName())) > 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // check terminator for invokes if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) { LandingPads.insert(II->getLandingPadInst()); bool NeedInvoke = AllowExceptionsInFunc && canThrow(II->getCalledValue()); if (NeedInvoke) { // Insert a normal call instruction folded in between pre- and post-invoke CallInst::Create(PreInvoke, "", II); SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); ToErase.push_back(II); CallInst *Post = CallInst::Create(PostInvoke, "", II); Instruction *Post1 = new TruncInst(Post, i1, "", II); // Insert a branch based on the postInvoke BranchInst::Create(II->getUnwindDest(), II->getNormalDest(), Post1, II); } else { // This can't throw, and we don't need this invoke, just replace it with a call+branch SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); ToErase.push_back(II); BranchInst::Create(II->getNormalDest(), II); // Remove any PHI node entries from the exception destination. II->getUnwindDest()->removePredecessor(BB); } Changed = true; } // scan the body of the basic block for resumes for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E; ) { Instruction *I = Iter++; if (ResumeInst *R = dyn_cast<ResumeInst>(I)) { // split the input into legal values Value *Input = R->getValue(); ExtractValueInst *Low = ExtractValueInst::Create(Input, 0, "", R); ExtractValueInst *High = ExtractValueInst::Create(Input, 1, "", R); // create a resume call SmallVector<Value*,2> CallArgs; CallArgs.push_back(Low); CallArgs.push_back(High); CallInst::Create(Resume, CallArgs, "", R); new UnreachableInst(TheModule->getContext(), R); // add a terminator to the block ToErase.push_back(R); } } } // Look for orphan landingpads, can occur in blocks with no predecesors for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { Instruction *I = BB->getFirstNonPHI(); if (LandingPadInst *LP = dyn_cast<LandingPadInst>(I)) { LandingPads.insert(LP); } } // Handle all the landingpad for this function together, as multiple invokes may share a single lp for (std::set<LandingPadInst*>::iterator I = LandingPads.begin(); I != LandingPads.end(); I++) { // Replace the landingpad with a landingpad call to get the low part, and a getHigh for the high LandingPadInst *LP = *I; unsigned Num = LP->getNumClauses(); SmallVector<Value*,16> NewLPArgs; NewLPArgs.push_back(LP->getPersonalityFn()); for (unsigned i = 0; i < Num; i++) { Value *Arg = LP->getClause(i); // As a temporary workaround for the lack of aggregate varargs support // in the varargs lowering code, break out filter operands into their // component elements. if (LP->isFilter(i)) { ArrayType *ATy = cast<ArrayType>(Arg->getType()); for (unsigned elem = 0, elemEnd = ATy->getNumElements(); elem != elemEnd; ++elem) { Instruction *EE = ExtractValueInst::Create(Arg, makeArrayRef(elem), "", LP); NewLPArgs.push_back(EE); } } else { NewLPArgs.push_back(Arg); } } NewLPArgs.push_back(LP->isCleanup() ? ConstantInt::getTrue(i1) : ConstantInt::getFalse(i1)); CallInst *NewLP = CallInst::Create(LandingPad, NewLPArgs, "", LP); Instruction *High = CallInst::Create(GetHigh, "", LP); // New recreate an aggregate for them, which will be all simplified later (simplification cannot handle landingpad, hence all this) InsertValueInst *IVA = InsertValueInst::Create(UndefValue::get(LP->getType()), NewLP, 0, "", LP); InsertValueInst *IVB = InsertValueInst::Create(IVA, High, 1, "", LP); LP->replaceAllUsesWith(IVB); ToErase.push_back(LP); } // erase everything we no longer need in this function for (unsigned i = 0; i < ToErase.size(); i++) ToErase[i]->eraseFromParent(); } return Changed; }
/// SplitLandingPadPredecessors - This method transforms the landing pad, /// OrigBB, by introducing two new basic blocks into the function. One of those /// new basic blocks gets the predecessors listed in Preds. The other basic /// block gets the remaining predecessors of OrigBB. The landingpad instruction /// OrigBB is clone into both of the new basic blocks. The new blocks are given /// the suffixes 'Suffix1' and 'Suffix2', and are returned in the NewBBs vector. /// /// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, /// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. In particular, /// it does not preserve LoopSimplify (because it's complicated to handle the /// case where one of the edges being split is an exit of a loop with other /// exits). /// void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB, ArrayRef<BasicBlock*> Preds, const char *Suffix1, const char *Suffix2, Pass *P, SmallVectorImpl<BasicBlock*> &NewBBs) { assert(OrigBB->isLandingPad() && "Trying to split a non-landing pad!"); // Create a new basic block for OrigBB's predecessors listed in Preds. Insert // it right before the original block. BasicBlock *NewBB1 = BasicBlock::Create(OrigBB->getContext(), OrigBB->getName() + Suffix1, OrigBB->getParent(), OrigBB); NewBBs.push_back(NewBB1); // The new block unconditionally branches to the old block. BranchInst *BI1 = BranchInst::Create(OrigBB, NewBB1); // Move the edges from Preds to point to NewBB1 instead of OrigBB. for (unsigned i = 0, e = Preds.size(); i != e; ++i) { // This is slightly more strict than necessary; the minimum requirement // is that there be no more than one indirectbr branching to BB. And // all BlockAddress uses would need to be updated. assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) && "Cannot split an edge from an IndirectBrInst"); Preds[i]->getTerminator()->replaceUsesOfWith(OrigBB, NewBB1); } // Update DominatorTree, LoopInfo, and LCCSA analysis information. bool HasLoopExit = false; UpdateAnalysisInformation(OrigBB, NewBB1, Preds, P, HasLoopExit); // Update the PHI nodes in OrigBB with the values coming from NewBB1. UpdatePHINodes(OrigBB, NewBB1, Preds, BI1, P, HasLoopExit); // Move the remaining edges from OrigBB to point to NewBB2. SmallVector<BasicBlock*, 8> NewBB2Preds; for (pred_iterator i = pred_begin(OrigBB), e = pred_end(OrigBB); i != e; ) { BasicBlock *Pred = *i++; if (Pred == NewBB1) continue; assert(!isa<IndirectBrInst>(Pred->getTerminator()) && "Cannot split an edge from an IndirectBrInst"); NewBB2Preds.push_back(Pred); e = pred_end(OrigBB); } BasicBlock *NewBB2 = 0; if (!NewBB2Preds.empty()) { // Create another basic block for the rest of OrigBB's predecessors. NewBB2 = BasicBlock::Create(OrigBB->getContext(), OrigBB->getName() + Suffix2, OrigBB->getParent(), OrigBB); NewBBs.push_back(NewBB2); // The new block unconditionally branches to the old block. BranchInst *BI2 = BranchInst::Create(OrigBB, NewBB2); // Move the remaining edges from OrigBB to point to NewBB2. for (SmallVectorImpl<BasicBlock*>::iterator i = NewBB2Preds.begin(), e = NewBB2Preds.end(); i != e; ++i) (*i)->getTerminator()->replaceUsesOfWith(OrigBB, NewBB2); // Update DominatorTree, LoopInfo, and LCCSA analysis information. HasLoopExit = false; UpdateAnalysisInformation(OrigBB, NewBB2, NewBB2Preds, P, HasLoopExit); // Update the PHI nodes in OrigBB with the values coming from NewBB2. UpdatePHINodes(OrigBB, NewBB2, NewBB2Preds, BI2, P, HasLoopExit); } LandingPadInst *LPad = OrigBB->getLandingPadInst(); Instruction *Clone1 = LPad->clone(); Clone1->setName(Twine("lpad") + Suffix1); NewBB1->getInstList().insert(NewBB1->getFirstInsertionPt(), Clone1); if (NewBB2) { Instruction *Clone2 = LPad->clone(); Clone2->setName(Twine("lpad") + Suffix2); NewBB2->getInstList().insert(NewBB2->getFirstInsertionPt(), Clone2); // Create a PHI node for the two cloned landingpad instructions. PHINode *PN = PHINode::Create(LPad->getType(), 2, "lpad.phi", LPad); PN->addIncoming(Clone1, NewBB1); PN->addIncoming(Clone2, NewBB2); LPad->replaceAllUsesWith(PN); LPad->eraseFromParent(); } else { // There is no second clone. Just replace the landing pad with the first // clone. LPad->replaceAllUsesWith(Clone1); LPad->eraseFromParent(); } }
/// 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<LandingPadInst*> 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); AllocaInst *FuncCtx = new AllocaInst(FunctionContextTy, 0, Align, "fn_context", EntryBB->begin()); // Fill in the function context structure. Value *Idxs[2]; Type *Int32Ty = Type::getInt32Ty(F.getContext()); Value *Zero = ConstantInt::get(Int32Ty, 0); Value *One = ConstantInt::get(Int32Ty, 1); // Keep around a reference to the call_site field. Idxs[0] = Zero; Idxs[1] = One; CallSite = GetElementPtrInst::Create(FuncCtx, Idxs, "call_site", EntryBB->getTerminator()); // Reference the __data field. Idxs[1] = ConstantInt::get(Int32Ty, 2); Value *FCData = GetElementPtrInst::Create(FuncCtx, Idxs, "__data", EntryBB->getTerminator()); // The exception value comes back in context->__data[0]. Idxs[1] = Zero; Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, "exception_gep", EntryBB->getTerminator()); // The exception selector comes back in context->__data[1]. Idxs[1] = One; Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, "exn_selector_gep", EntryBB->getTerminator()); for (unsigned I = 0, E = LPads.size(); I != E; ++I) { LandingPadInst *LPI = LPads[I]; IRBuilder<> Builder(LPI->getParent()->getFirstInsertionPt()); Value *ExnVal = Builder.CreateLoad(ExceptionAddr, true, "exn_val"); ExnVal = Builder.CreateIntToPtr(ExnVal, Type::getInt8PtrTy(F.getContext())); Value *SelVal = Builder.CreateLoad(SelectorAddr, true, "exn_selector_val"); Type *LPadType = LPI->getType(); Value *LPadVal = UndefValue::get(LPadType); LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0, "lpad.val"); LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1, "lpad.val"); LPI->replaceAllUsesWith(LPadVal); } // Personality function Idxs[1] = ConstantInt::get(Int32Ty, 3); 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 Idxs[1] = ConstantInt::get(Int32Ty, 4); Value *LSDAFieldPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "lsda_gep", EntryBB->getTerminator()); Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", EntryBB->getTerminator()); new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); return FuncCtx; }