10b57cec5SDimitry Andric //===- SjLjEHPrepare.cpp - Eliminate Invoke & Unwind instructions ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This transformation is designed for use by code generators which use SjLj 100b57cec5SDimitry Andric // based exception handling. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 145f757f3fSDimitry Andric #include "llvm/CodeGen/SjLjEHPrepare.h" 150b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 180b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 200b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 210b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 220b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 230b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 240b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 250b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 260b57cec5SDimitry Andric #include "llvm/IR/Module.h" 27480093f4SDimitry Andric #include "llvm/InitializePasses.h" 280b57cec5SDimitry Andric #include "llvm/Pass.h" 290b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 315ffd83dbSDimitry Andric #include "llvm/Target/TargetMachine.h" 32480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric 355f757f3fSDimitry Andric #define DEBUG_TYPE "sjlj-eh-prepare" 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric STATISTIC(NumInvokes, "Number of invokes replaced"); 380b57cec5SDimitry Andric STATISTIC(NumSpilled, "Number of registers live across unwind edges"); 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric namespace { 415f757f3fSDimitry Andric class SjLjEHPrepareImpl { 4206c3fb27SDimitry Andric IntegerType *DataTy = nullptr; 4306c3fb27SDimitry Andric Type *doubleUnderDataTy = nullptr; 4406c3fb27SDimitry Andric Type *doubleUnderJBufTy = nullptr; 4506c3fb27SDimitry Andric Type *FunctionContextTy = nullptr; 460b57cec5SDimitry Andric FunctionCallee RegisterFn; 470b57cec5SDimitry Andric FunctionCallee UnregisterFn; 4806c3fb27SDimitry Andric Function *BuiltinSetupDispatchFn = nullptr; 4906c3fb27SDimitry Andric Function *FrameAddrFn = nullptr; 5006c3fb27SDimitry Andric Function *StackAddrFn = nullptr; 5106c3fb27SDimitry Andric Function *StackRestoreFn = nullptr; 5206c3fb27SDimitry Andric Function *LSDAAddrFn = nullptr; 5306c3fb27SDimitry Andric Function *CallSiteFn = nullptr; 5406c3fb27SDimitry Andric Function *FuncCtxFn = nullptr; 5506c3fb27SDimitry Andric AllocaInst *FuncCtx = nullptr; 5606c3fb27SDimitry Andric const TargetMachine *TM = nullptr; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric public: 595f757f3fSDimitry Andric explicit SjLjEHPrepareImpl(const TargetMachine *TM = nullptr) : TM(TM) {} 605f757f3fSDimitry Andric bool doInitialization(Module &M); 615f757f3fSDimitry Andric bool runOnFunction(Function &F); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric private: 640b57cec5SDimitry Andric bool setupEntryBlockAndCallSites(Function &F); 650b57cec5SDimitry Andric void substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, Value *SelVal); 660b57cec5SDimitry Andric Value *setupFunctionContext(Function &F, ArrayRef<LandingPadInst *> LPads); 670b57cec5SDimitry Andric void lowerIncomingArguments(Function &F); 680b57cec5SDimitry Andric void lowerAcrossUnwindEdges(Function &F, ArrayRef<InvokeInst *> Invokes); 690b57cec5SDimitry Andric void insertCallSiteStore(Instruction *I, int Number); 700b57cec5SDimitry Andric }; 715f757f3fSDimitry Andric 725f757f3fSDimitry Andric class SjLjEHPrepare : public FunctionPass { 735f757f3fSDimitry Andric SjLjEHPrepareImpl Impl; 745f757f3fSDimitry Andric 755f757f3fSDimitry Andric public: 765f757f3fSDimitry Andric static char ID; // Pass identification, replacement for typeid 775f757f3fSDimitry Andric explicit SjLjEHPrepare(const TargetMachine *TM = nullptr) 785f757f3fSDimitry Andric : FunctionPass(ID), Impl(TM) {} 795f757f3fSDimitry Andric bool doInitialization(Module &M) override { return Impl.doInitialization(M); } 805f757f3fSDimitry Andric bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); }; 815f757f3fSDimitry Andric 825f757f3fSDimitry Andric StringRef getPassName() const override { 835f757f3fSDimitry Andric return "SJLJ Exception Handling preparation"; 845f757f3fSDimitry Andric } 855f757f3fSDimitry Andric }; 865f757f3fSDimitry Andric 870b57cec5SDimitry Andric } // end anonymous namespace 880b57cec5SDimitry Andric 895f757f3fSDimitry Andric PreservedAnalyses SjLjEHPreparePass::run(Function &F, 905f757f3fSDimitry Andric FunctionAnalysisManager &FAM) { 915f757f3fSDimitry Andric SjLjEHPrepareImpl Impl(TM); 925f757f3fSDimitry Andric Impl.doInitialization(*F.getParent()); 935f757f3fSDimitry Andric bool Changed = Impl.runOnFunction(F); 945f757f3fSDimitry Andric return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); 955f757f3fSDimitry Andric } 965f757f3fSDimitry Andric 970b57cec5SDimitry Andric char SjLjEHPrepare::ID = 0; 980b57cec5SDimitry Andric INITIALIZE_PASS(SjLjEHPrepare, DEBUG_TYPE, "Prepare SjLj exceptions", 990b57cec5SDimitry Andric false, false) 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric // Public Interface To the SjLjEHPrepare pass. 1025ffd83dbSDimitry Andric FunctionPass *llvm::createSjLjEHPreparePass(const TargetMachine *TM) { 1035ffd83dbSDimitry Andric return new SjLjEHPrepare(TM); 1045ffd83dbSDimitry Andric } 1055ffd83dbSDimitry Andric 1060b57cec5SDimitry Andric // doInitialization - Set up decalarations and types needed to process 1070b57cec5SDimitry Andric // exceptions. 1085f757f3fSDimitry Andric bool SjLjEHPrepareImpl::doInitialization(Module &M) { 1090b57cec5SDimitry Andric // Build the function context structure. 1100b57cec5SDimitry Andric // builtin_setjmp uses a five word jbuf 1115f757f3fSDimitry Andric Type *VoidPtrTy = PointerType::getUnqual(M.getContext()); 1125ffd83dbSDimitry Andric unsigned DataBits = 1135ffd83dbSDimitry Andric TM ? TM->getSjLjDataSize() : TargetMachine::DefaultSjLjDataSize; 1145ffd83dbSDimitry Andric DataTy = Type::getIntNTy(M.getContext(), DataBits); 1155ffd83dbSDimitry Andric doubleUnderDataTy = ArrayType::get(DataTy, 4); 1160b57cec5SDimitry Andric doubleUnderJBufTy = ArrayType::get(VoidPtrTy, 5); 1170b57cec5SDimitry Andric FunctionContextTy = StructType::get(VoidPtrTy, // __prev 1185ffd83dbSDimitry Andric DataTy, // call_site 1190b57cec5SDimitry Andric doubleUnderDataTy, // __data 1200b57cec5SDimitry Andric VoidPtrTy, // __personality 1210b57cec5SDimitry Andric VoidPtrTy, // __lsda 1220b57cec5SDimitry Andric doubleUnderJBufTy // __jbuf 1230b57cec5SDimitry Andric ); 1240b57cec5SDimitry Andric 1255f757f3fSDimitry Andric return false; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric /// insertCallSiteStore - Insert a store of the call-site value to the 1290b57cec5SDimitry Andric /// function context 1305f757f3fSDimitry Andric void SjLjEHPrepareImpl::insertCallSiteStore(Instruction *I, int Number) { 1310b57cec5SDimitry Andric IRBuilder<> Builder(I); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // Get a reference to the call_site field. 1340b57cec5SDimitry Andric Type *Int32Ty = Type::getInt32Ty(I->getContext()); 1350b57cec5SDimitry Andric Value *Zero = ConstantInt::get(Int32Ty, 0); 1360b57cec5SDimitry Andric Value *One = ConstantInt::get(Int32Ty, 1); 1370b57cec5SDimitry Andric Value *Idxs[2] = { Zero, One }; 1380b57cec5SDimitry Andric Value *CallSite = 1390b57cec5SDimitry Andric Builder.CreateGEP(FunctionContextTy, FuncCtx, Idxs, "call_site"); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Insert a store of the call-site number 1425ffd83dbSDimitry Andric ConstantInt *CallSiteNoC = ConstantInt::get(DataTy, Number); 1430b57cec5SDimitry Andric Builder.CreateStore(CallSiteNoC, CallSite, true /*volatile*/); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric /// MarkBlocksLiveIn - Insert BB and all of its predecessors into LiveBBs until 1470b57cec5SDimitry Andric /// we reach blocks we've already seen. 1480b57cec5SDimitry Andric static void MarkBlocksLiveIn(BasicBlock *BB, 1490b57cec5SDimitry Andric SmallPtrSetImpl<BasicBlock *> &LiveBBs) { 1500b57cec5SDimitry Andric if (!LiveBBs.insert(BB).second) 1510b57cec5SDimitry Andric return; // already been here. 1520b57cec5SDimitry Andric 153*0fca6ea1SDimitry Andric for (BasicBlock *B : inverse_depth_first(BB)) 1540b57cec5SDimitry Andric LiveBBs.insert(B); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// substituteLPadValues - Substitute the values returned by the landingpad 1580b57cec5SDimitry Andric /// instruction with those returned by the personality function. 1595f757f3fSDimitry Andric void SjLjEHPrepareImpl::substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, 1600b57cec5SDimitry Andric Value *SelVal) { 161e8d8bef9SDimitry Andric SmallVector<Value *, 8> UseWorkList(LPI->users()); 1620b57cec5SDimitry Andric while (!UseWorkList.empty()) { 1630b57cec5SDimitry Andric Value *Val = UseWorkList.pop_back_val(); 1640b57cec5SDimitry Andric auto *EVI = dyn_cast<ExtractValueInst>(Val); 1650b57cec5SDimitry Andric if (!EVI) 1660b57cec5SDimitry Andric continue; 1670b57cec5SDimitry Andric if (EVI->getNumIndices() != 1) 1680b57cec5SDimitry Andric continue; 1690b57cec5SDimitry Andric if (*EVI->idx_begin() == 0) 1700b57cec5SDimitry Andric EVI->replaceAllUsesWith(ExnVal); 1710b57cec5SDimitry Andric else if (*EVI->idx_begin() == 1) 1720b57cec5SDimitry Andric EVI->replaceAllUsesWith(SelVal); 1730b57cec5SDimitry Andric if (EVI->use_empty()) 1740b57cec5SDimitry Andric EVI->eraseFromParent(); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (LPI->use_empty()) 1780b57cec5SDimitry Andric return; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // There are still some uses of LPI. Construct an aggregate with the exception 1810b57cec5SDimitry Andric // values and replace the LPI with that aggregate. 1820b57cec5SDimitry Andric Type *LPadType = LPI->getType(); 183bdd1243dSDimitry Andric Value *LPadVal = PoisonValue::get(LPadType); 1840b57cec5SDimitry Andric auto *SelI = cast<Instruction>(SelVal); 1850b57cec5SDimitry Andric IRBuilder<> Builder(SelI->getParent(), std::next(SelI->getIterator())); 1860b57cec5SDimitry Andric LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0, "lpad.val"); 1870b57cec5SDimitry Andric LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1, "lpad.val"); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric LPI->replaceAllUsesWith(LPadVal); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric /// setupFunctionContext - Allocate the function context on the stack and fill 1930b57cec5SDimitry Andric /// it with all of the data that we know at this point. 1945f757f3fSDimitry Andric Value * 1955f757f3fSDimitry Andric SjLjEHPrepareImpl::setupFunctionContext(Function &F, 1960b57cec5SDimitry Andric ArrayRef<LandingPadInst *> LPads) { 1970b57cec5SDimitry Andric BasicBlock *EntryBB = &F.front(); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Create an alloca for the incoming jump buffer ptr and the new jump buffer 2000b57cec5SDimitry Andric // that needs to be restored on all exits from the function. This is an alloca 2010b57cec5SDimitry Andric // because the value needs to be added to the global context list. 202*0fca6ea1SDimitry Andric auto &DL = F.getDataLayout(); 203bdd1243dSDimitry Andric const Align Alignment = DL.getPrefTypeAlign(FunctionContextTy); 204480093f4SDimitry Andric FuncCtx = new AllocaInst(FunctionContextTy, DL.getAllocaAddrSpace(), nullptr, 205*0fca6ea1SDimitry Andric Alignment, "fn_context", EntryBB->begin()); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric // Fill in the function context structure. 2080b57cec5SDimitry Andric for (LandingPadInst *LPI : LPads) { 2090b57cec5SDimitry Andric IRBuilder<> Builder(LPI->getParent(), 2100b57cec5SDimitry Andric LPI->getParent()->getFirstInsertionPt()); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // Reference the __data field. 2130b57cec5SDimitry Andric Value *FCData = 2140b57cec5SDimitry Andric Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 2, "__data"); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // The exception values come back in context->__data[0]. 2170b57cec5SDimitry Andric Value *ExceptionAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData, 2180b57cec5SDimitry Andric 0, 0, "exception_gep"); 2195ffd83dbSDimitry Andric Value *ExnVal = Builder.CreateLoad(DataTy, ExceptionAddr, true, "exn_val"); 2205f757f3fSDimitry Andric ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getPtrTy()); 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric Value *SelectorAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData, 2230b57cec5SDimitry Andric 0, 1, "exn_selector_gep"); 2240b57cec5SDimitry Andric Value *SelVal = 2255ffd83dbSDimitry Andric Builder.CreateLoad(DataTy, SelectorAddr, true, "exn_selector_val"); 2265ffd83dbSDimitry Andric 2275ffd83dbSDimitry Andric // SelVal must be Int32Ty, so trunc it 2285ffd83dbSDimitry Andric SelVal = Builder.CreateTrunc(SelVal, Type::getInt32Ty(F.getContext())); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric substituteLPadValues(LPI, ExnVal, SelVal); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // Personality function 2340b57cec5SDimitry Andric IRBuilder<> Builder(EntryBB->getTerminator()); 2350b57cec5SDimitry Andric Value *PersonalityFn = F.getPersonalityFn(); 2360b57cec5SDimitry Andric Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32( 2370b57cec5SDimitry Andric FunctionContextTy, FuncCtx, 0, 3, "pers_fn_gep"); 2385f757f3fSDimitry Andric Builder.CreateStore(PersonalityFn, PersonalityFieldPtr, /*isVolatile=*/true); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric // LSDA address 2410b57cec5SDimitry Andric Value *LSDA = Builder.CreateCall(LSDAAddrFn, {}, "lsda_addr"); 2420b57cec5SDimitry Andric Value *LSDAFieldPtr = 2430b57cec5SDimitry Andric Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 4, "lsda_gep"); 2440b57cec5SDimitry Andric Builder.CreateStore(LSDA, LSDAFieldPtr, /*isVolatile=*/true); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric return FuncCtx; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric /// lowerIncomingArguments - To avoid having to handle incoming arguments 2500b57cec5SDimitry Andric /// specially, we lower each arg to a copy instruction in the entry block. This 2510b57cec5SDimitry Andric /// ensures that the argument value itself cannot be live out of the entry 2520b57cec5SDimitry Andric /// block. 2535f757f3fSDimitry Andric void SjLjEHPrepareImpl::lowerIncomingArguments(Function &F) { 2540b57cec5SDimitry Andric BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); 2550b57cec5SDimitry Andric while (isa<AllocaInst>(AfterAllocaInsPt) && 2560b57cec5SDimitry Andric cast<AllocaInst>(AfterAllocaInsPt)->isStaticAlloca()) 2570b57cec5SDimitry Andric ++AfterAllocaInsPt; 2580b57cec5SDimitry Andric assert(AfterAllocaInsPt != F.front().end()); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric for (auto &AI : F.args()) { 2610b57cec5SDimitry Andric // Swift error really is a register that we model as memory -- instruction 2620b57cec5SDimitry Andric // selection will perform mem-to-reg for us and spill/reload appropriately 2630b57cec5SDimitry Andric // around calls that clobber it. There is no need to spill this 2640b57cec5SDimitry Andric // value to the stack and doing so would not be allowed. 2650b57cec5SDimitry Andric if (AI.isSwiftError()) 2660b57cec5SDimitry Andric continue; 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric Type *Ty = AI.getType(); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // Use 'select i8 true, %arg, undef' to simulate a 'no-op' instruction. 2710b57cec5SDimitry Andric Value *TrueValue = ConstantInt::getTrue(F.getContext()); 2720b57cec5SDimitry Andric Value *UndefValue = UndefValue::get(Ty); 2730b57cec5SDimitry Andric Instruction *SI = SelectInst::Create( 274*0fca6ea1SDimitry Andric TrueValue, &AI, UndefValue, AI.getName() + ".tmp", AfterAllocaInsPt); 2750b57cec5SDimitry Andric AI.replaceAllUsesWith(SI); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // Reset the operand, because it was clobbered by the RAUW above. 2780b57cec5SDimitry Andric SI->setOperand(1, &AI); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric /// lowerAcrossUnwindEdges - Find all variables which are alive across an unwind 2830b57cec5SDimitry Andric /// edge and spill them. 2845f757f3fSDimitry Andric void SjLjEHPrepareImpl::lowerAcrossUnwindEdges(Function &F, 2850b57cec5SDimitry Andric ArrayRef<InvokeInst *> Invokes) { 2860b57cec5SDimitry Andric // Finally, scan the code looking for instructions with bad live ranges. 2870b57cec5SDimitry Andric for (BasicBlock &BB : F) { 2880b57cec5SDimitry Andric for (Instruction &Inst : BB) { 2890b57cec5SDimitry Andric // Ignore obvious cases we don't have to handle. In particular, most 2900b57cec5SDimitry Andric // instructions either have no uses or only have a single use inside the 2910b57cec5SDimitry Andric // current block. Ignore them quickly. 2920b57cec5SDimitry Andric if (Inst.use_empty()) 2930b57cec5SDimitry Andric continue; 2940b57cec5SDimitry Andric if (Inst.hasOneUse() && 2950b57cec5SDimitry Andric cast<Instruction>(Inst.user_back())->getParent() == &BB && 2960b57cec5SDimitry Andric !isa<PHINode>(Inst.user_back())) 2970b57cec5SDimitry Andric continue; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // If this is an alloca in the entry block, it's not a real register 3000b57cec5SDimitry Andric // value. 3010b57cec5SDimitry Andric if (auto *AI = dyn_cast<AllocaInst>(&Inst)) 3020b57cec5SDimitry Andric if (AI->isStaticAlloca()) 3030b57cec5SDimitry Andric continue; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // Avoid iterator invalidation by copying users to a temporary vector. 3060b57cec5SDimitry Andric SmallVector<Instruction *, 16> Users; 3070b57cec5SDimitry Andric for (User *U : Inst.users()) { 3080b57cec5SDimitry Andric Instruction *UI = cast<Instruction>(U); 3090b57cec5SDimitry Andric if (UI->getParent() != &BB || isa<PHINode>(UI)) 3100b57cec5SDimitry Andric Users.push_back(UI); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Find all of the blocks that this value is live in. 3140b57cec5SDimitry Andric SmallPtrSet<BasicBlock *, 32> LiveBBs; 3150b57cec5SDimitry Andric LiveBBs.insert(&BB); 3160b57cec5SDimitry Andric while (!Users.empty()) { 3170b57cec5SDimitry Andric Instruction *U = Users.pop_back_val(); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric if (!isa<PHINode>(U)) { 3200b57cec5SDimitry Andric MarkBlocksLiveIn(U->getParent(), LiveBBs); 3210b57cec5SDimitry Andric } else { 3220b57cec5SDimitry Andric // Uses for a PHI node occur in their predecessor block. 3230b57cec5SDimitry Andric PHINode *PN = cast<PHINode>(U); 3240b57cec5SDimitry Andric for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) 3250b57cec5SDimitry Andric if (PN->getIncomingValue(i) == &Inst) 3260b57cec5SDimitry Andric MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Now that we know all of the blocks that this thing is live in, see if 3310b57cec5SDimitry Andric // it includes any of the unwind locations. 3320b57cec5SDimitry Andric bool NeedsSpill = false; 3330b57cec5SDimitry Andric for (InvokeInst *Invoke : Invokes) { 3340b57cec5SDimitry Andric BasicBlock *UnwindBlock = Invoke->getUnwindDest(); 3350b57cec5SDimitry Andric if (UnwindBlock != &BB && LiveBBs.count(UnwindBlock)) { 3360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "SJLJ Spill: " << Inst << " around " 3370b57cec5SDimitry Andric << UnwindBlock->getName() << "\n"); 3380b57cec5SDimitry Andric NeedsSpill = true; 3390b57cec5SDimitry Andric break; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // If we decided we need a spill, do it. 3440b57cec5SDimitry Andric // FIXME: Spilling this way is overkill, as it forces all uses of 3450b57cec5SDimitry Andric // the value to be reloaded from the stack slot, even those that aren't 3460b57cec5SDimitry Andric // in the unwind blocks. We should be more selective. 3470b57cec5SDimitry Andric if (NeedsSpill) { 3480b57cec5SDimitry Andric DemoteRegToStack(Inst, true); 3490b57cec5SDimitry Andric ++NumSpilled; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric // Go through the landing pads and remove any PHIs there. 3550b57cec5SDimitry Andric for (InvokeInst *Invoke : Invokes) { 3560b57cec5SDimitry Andric BasicBlock *UnwindBlock = Invoke->getUnwindDest(); 3570b57cec5SDimitry Andric LandingPadInst *LPI = UnwindBlock->getLandingPadInst(); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // Place PHIs into a set to avoid invalidating the iterator. 3600b57cec5SDimitry Andric SmallPtrSet<PHINode *, 8> PHIsToDemote; 3610b57cec5SDimitry Andric for (BasicBlock::iterator PN = UnwindBlock->begin(); isa<PHINode>(PN); ++PN) 3620b57cec5SDimitry Andric PHIsToDemote.insert(cast<PHINode>(PN)); 3630b57cec5SDimitry Andric if (PHIsToDemote.empty()) 3640b57cec5SDimitry Andric continue; 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric // Demote the PHIs to the stack. 3670b57cec5SDimitry Andric for (PHINode *PN : PHIsToDemote) 3680b57cec5SDimitry Andric DemotePHIToStack(PN); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // Move the landingpad instruction back to the top of the landing pad block. 3710b57cec5SDimitry Andric LPI->moveBefore(&UnwindBlock->front()); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric /// setupEntryBlockAndCallSites - Setup the entry block by creating and filling 3760b57cec5SDimitry Andric /// the function context and marking the call sites with the appropriate 3770b57cec5SDimitry Andric /// values. These values are used by the DWARF EH emitter. 3785f757f3fSDimitry Andric bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { 3790b57cec5SDimitry Andric SmallVector<ReturnInst *, 16> Returns; 3800b57cec5SDimitry Andric SmallVector<InvokeInst *, 16> Invokes; 3810b57cec5SDimitry Andric SmallSetVector<LandingPadInst *, 16> LPads; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric // Look through the terminators of the basic blocks to find invokes. 3840b57cec5SDimitry Andric for (BasicBlock &BB : F) 3850b57cec5SDimitry Andric if (auto *II = dyn_cast<InvokeInst>(BB.getTerminator())) { 3860b57cec5SDimitry Andric if (Function *Callee = II->getCalledFunction()) 3870b57cec5SDimitry Andric if (Callee->getIntrinsicID() == Intrinsic::donothing) { 3880b57cec5SDimitry Andric // Remove the NOP invoke. 389*0fca6ea1SDimitry Andric BranchInst::Create(II->getNormalDest(), II->getIterator()); 3900b57cec5SDimitry Andric II->eraseFromParent(); 3910b57cec5SDimitry Andric continue; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric Invokes.push_back(II); 3950b57cec5SDimitry Andric LPads.insert(II->getUnwindDest()->getLandingPadInst()); 3960b57cec5SDimitry Andric } else if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) { 3970b57cec5SDimitry Andric Returns.push_back(RI); 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric if (Invokes.empty()) 4010b57cec5SDimitry Andric return false; 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric NumInvokes += Invokes.size(); 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric lowerIncomingArguments(F); 4060b57cec5SDimitry Andric lowerAcrossUnwindEdges(F, Invokes); 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric Value *FuncCtx = 409bdd1243dSDimitry Andric setupFunctionContext(F, ArrayRef(LPads.begin(), LPads.end())); 4100b57cec5SDimitry Andric BasicBlock *EntryBB = &F.front(); 4110b57cec5SDimitry Andric IRBuilder<> Builder(EntryBB->getTerminator()); 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric // Get a reference to the jump buffer. 4140b57cec5SDimitry Andric Value *JBufPtr = 4150b57cec5SDimitry Andric Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 5, "jbuf_gep"); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // Save the frame pointer. 4180b57cec5SDimitry Andric Value *FramePtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 0, 4190b57cec5SDimitry Andric "jbuf_fp_gep"); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric Value *Val = Builder.CreateCall(FrameAddrFn, Builder.getInt32(0), "fp"); 4220b57cec5SDimitry Andric Builder.CreateStore(Val, FramePtr, /*isVolatile=*/true); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric // Save the stack pointer. 4250b57cec5SDimitry Andric Value *StackPtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 2, 4260b57cec5SDimitry Andric "jbuf_sp_gep"); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric Val = Builder.CreateCall(StackAddrFn, {}, "sp"); 4290b57cec5SDimitry Andric Builder.CreateStore(Val, StackPtr, /*isVolatile=*/true); 4300b57cec5SDimitry Andric 43181ad6265SDimitry Andric // Call the setup_dispatch intrinsic. It fills in the rest of the jmpbuf. 4320b57cec5SDimitry Andric Builder.CreateCall(BuiltinSetupDispatchFn, {}); 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric // Store a pointer to the function context so that the back-end will know 4350b57cec5SDimitry Andric // where to look for it. 4365f757f3fSDimitry Andric Builder.CreateCall(FuncCtxFn, FuncCtx); 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric // At this point, we are all set up, update the invoke instructions to mark 4390b57cec5SDimitry Andric // their call_site values. 4400b57cec5SDimitry Andric for (unsigned I = 0, E = Invokes.size(); I != E; ++I) { 4410b57cec5SDimitry Andric insertCallSiteStore(Invokes[I], I + 1); 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric ConstantInt *CallSiteNum = 4440b57cec5SDimitry Andric ConstantInt::get(Type::getInt32Ty(F.getContext()), I + 1); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric // Record the call site value for the back end so it stays associated with 4470b57cec5SDimitry Andric // the invoke. 448*0fca6ea1SDimitry Andric CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]->getIterator()); 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric // Mark call instructions that aren't nounwind as no-action (call_site == 4520b57cec5SDimitry Andric // -1). Skip the entry block, as prior to then, no function context has been 4530b57cec5SDimitry Andric // created for this function and any unexpected exceptions thrown will go 4540b57cec5SDimitry Andric // directly to the caller's context, which is what we want anyway, so no need 4550b57cec5SDimitry Andric // to do anything here. 4560b57cec5SDimitry Andric for (BasicBlock &BB : F) { 4570b57cec5SDimitry Andric if (&BB == &F.front()) 4580b57cec5SDimitry Andric continue; 4590b57cec5SDimitry Andric for (Instruction &I : BB) 4600b57cec5SDimitry Andric if (I.mayThrow()) 4610b57cec5SDimitry Andric insertCallSiteStore(&I, -1); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric // Register the function context and make sure it's known to not throw 465*0fca6ea1SDimitry Andric CallInst *Register = CallInst::Create( 466*0fca6ea1SDimitry Andric RegisterFn, FuncCtx, "", EntryBB->getTerminator()->getIterator()); 4670b57cec5SDimitry Andric Register->setDoesNotThrow(); 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric // Following any allocas not in the entry block, update the saved SP in the 4700b57cec5SDimitry Andric // jmpbuf to the new value. 4710b57cec5SDimitry Andric for (BasicBlock &BB : F) { 4720b57cec5SDimitry Andric if (&BB == &F.front()) 4730b57cec5SDimitry Andric continue; 4740b57cec5SDimitry Andric for (Instruction &I : BB) { 4750b57cec5SDimitry Andric if (auto *CI = dyn_cast<CallInst>(&I)) { 4760b57cec5SDimitry Andric if (CI->getCalledFunction() != StackRestoreFn) 4770b57cec5SDimitry Andric continue; 4780b57cec5SDimitry Andric } else if (!isa<AllocaInst>(&I)) { 4790b57cec5SDimitry Andric continue; 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp"); 4820b57cec5SDimitry Andric StackAddr->insertAfter(&I); 483*0fca6ea1SDimitry Andric new StoreInst(StackAddr, StackPtr, true, 484*0fca6ea1SDimitry Andric std::next(StackAddr->getIterator())); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric // Finally, for any returns from this function, if this function contains an 4890b57cec5SDimitry Andric // invoke, add a call to unregister the function context. 490fe6060f1SDimitry Andric for (ReturnInst *Return : Returns) { 491fe6060f1SDimitry Andric Instruction *InsertPoint = Return; 492fe6060f1SDimitry Andric if (CallInst *CI = Return->getParent()->getTerminatingMustTailCall()) 493fe6060f1SDimitry Andric InsertPoint = CI; 494*0fca6ea1SDimitry Andric CallInst::Create(UnregisterFn, FuncCtx, "", InsertPoint->getIterator()); 495fe6060f1SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric return true; 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5005f757f3fSDimitry Andric bool SjLjEHPrepareImpl::runOnFunction(Function &F) { 5010b57cec5SDimitry Andric Module &M = *F.getParent(); 5020b57cec5SDimitry Andric RegisterFn = M.getOrInsertFunction( 5030b57cec5SDimitry Andric "_Unwind_SjLj_Register", Type::getVoidTy(M.getContext()), 5040b57cec5SDimitry Andric PointerType::getUnqual(FunctionContextTy)); 5050b57cec5SDimitry Andric UnregisterFn = M.getOrInsertFunction( 5060b57cec5SDimitry Andric "_Unwind_SjLj_Unregister", Type::getVoidTy(M.getContext()), 5070b57cec5SDimitry Andric PointerType::getUnqual(FunctionContextTy)); 5085f757f3fSDimitry Andric 5095f757f3fSDimitry Andric PointerType *AllocaPtrTy = M.getDataLayout().getAllocaPtrType(M.getContext()); 5105f757f3fSDimitry Andric 5115f757f3fSDimitry Andric FrameAddrFn = 5125f757f3fSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::frameaddress, {AllocaPtrTy}); 5135f757f3fSDimitry Andric StackAddrFn = 5145f757f3fSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::stacksave, {AllocaPtrTy}); 5155f757f3fSDimitry Andric StackRestoreFn = 5165f757f3fSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::stackrestore, {AllocaPtrTy}); 5170b57cec5SDimitry Andric BuiltinSetupDispatchFn = 5180b57cec5SDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setup_dispatch); 5190b57cec5SDimitry Andric LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); 5200b57cec5SDimitry Andric CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite); 5210b57cec5SDimitry Andric FuncCtxFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_functioncontext); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric bool Res = setupEntryBlockAndCallSites(F); 5240b57cec5SDimitry Andric return Res; 5250b57cec5SDimitry Andric } 526