10b57cec5SDimitry Andric //===- DwarfEHPrepare - Prepare exception handling for code generation ----===// 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 pass mulches exception handling code into a form adapted to code 100b57cec5SDimitry Andric // generation. Required if using dwarf exception handling. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 145f757f3fSDimitry Andric #include "llvm/CodeGen/DwarfEHPrepare.h" 150b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 180b57cec5SDimitry Andric #include "llvm/Analysis/CFG.h" 19e8d8bef9SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 210fca6ea1SDimitry Andric #include "llvm/CodeGen/RuntimeLibcallUtil.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 250b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 260b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 276246ae0bSDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 280b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 290b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 3006c3fb27SDimitry Andric #include "llvm/IR/EHPersonalities.h" 310b57cec5SDimitry Andric #include "llvm/IR/Function.h" 320b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 330b57cec5SDimitry Andric #include "llvm/IR/Module.h" 340b57cec5SDimitry Andric #include "llvm/IR/Type.h" 35480093f4SDimitry Andric #include "llvm/InitializePasses.h" 360b57cec5SDimitry Andric #include "llvm/Pass.h" 370b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 380b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 3906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 40480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 410b57cec5SDimitry Andric #include <cstddef> 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric using namespace llvm; 440b57cec5SDimitry Andric 455f757f3fSDimitry Andric #define DEBUG_TYPE "dwarf-eh-prepare" 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric STATISTIC(NumResumesLowered, "Number of resume calls lowered"); 48fe6060f1SDimitry Andric STATISTIC(NumCleanupLandingPadsUnreachable, 49fe6060f1SDimitry Andric "Number of cleanup landing pads found unreachable"); 50fe6060f1SDimitry Andric STATISTIC(NumCleanupLandingPadsRemaining, 51fe6060f1SDimitry Andric "Number of cleanup landing pads remaining"); 52fe6060f1SDimitry Andric STATISTIC(NumNoUnwind, "Number of functions with nounwind"); 53fe6060f1SDimitry Andric STATISTIC(NumUnwind, "Number of functions with unwind"); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric namespace { 560b57cec5SDimitry Andric 57e8d8bef9SDimitry Andric class DwarfEHPrepare { 585f757f3fSDimitry Andric CodeGenOptLevel OptLevel; 590b57cec5SDimitry Andric 60e8d8bef9SDimitry Andric Function &F; 61e8d8bef9SDimitry Andric const TargetLowering &TLI; 62e8d8bef9SDimitry Andric DomTreeUpdater *DTU; 63e8d8bef9SDimitry Andric const TargetTransformInfo *TTI; 64349cc55cSDimitry Andric const Triple &TargetTriple; 650b57cec5SDimitry Andric 66e8d8bef9SDimitry Andric /// Return the exception object from the value passed into 670b57cec5SDimitry Andric /// the 'resume' instruction (typically an aggregate). Clean up any dead 680b57cec5SDimitry Andric /// instructions, including the 'resume' instruction. 69e8d8bef9SDimitry Andric Value *GetExceptionObject(ResumeInst *RI); 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric /// Replace resumes that are not reachable from a cleanup landing pad with 72e8d8bef9SDimitry Andric /// unreachable and then simplify those blocks. 73e8d8bef9SDimitry Andric size_t 74e8d8bef9SDimitry Andric pruneUnreachableResumes(SmallVectorImpl<ResumeInst *> &Resumes, 75e8d8bef9SDimitry Andric SmallVectorImpl<LandingPadInst *> &CleanupLPads); 76e8d8bef9SDimitry Andric 77e8d8bef9SDimitry Andric /// Convert the ResumeInsts that are still present 78e8d8bef9SDimitry Andric /// into calls to the appropriate _Unwind_Resume function. 79e8d8bef9SDimitry Andric bool InsertUnwindResumeCalls(); 80e8d8bef9SDimitry Andric 81e8d8bef9SDimitry Andric public: 825f757f3fSDimitry Andric DwarfEHPrepare(CodeGenOptLevel OptLevel_, Function &F_, 83349cc55cSDimitry Andric const TargetLowering &TLI_, DomTreeUpdater *DTU_, 84349cc55cSDimitry Andric const TargetTransformInfo *TTI_, const Triple &TargetTriple_) 85349cc55cSDimitry Andric : OptLevel(OptLevel_), F(F_), TLI(TLI_), DTU(DTU_), TTI(TTI_), 86349cc55cSDimitry Andric TargetTriple(TargetTriple_) {} 87e8d8bef9SDimitry Andric 88e8d8bef9SDimitry Andric bool run(); 89e8d8bef9SDimitry Andric }; 90e8d8bef9SDimitry Andric 91e8d8bef9SDimitry Andric } // namespace 92e8d8bef9SDimitry Andric 930b57cec5SDimitry Andric Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { 940b57cec5SDimitry Andric Value *V = RI->getOperand(0); 950b57cec5SDimitry Andric Value *ExnObj = nullptr; 960b57cec5SDimitry Andric InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V); 970b57cec5SDimitry Andric LoadInst *SelLoad = nullptr; 980b57cec5SDimitry Andric InsertValueInst *ExcIVI = nullptr; 990b57cec5SDimitry Andric bool EraseIVIs = false; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (SelIVI) { 1020b57cec5SDimitry Andric if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { 1030b57cec5SDimitry Andric ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0)); 1040b57cec5SDimitry Andric if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) && 1050b57cec5SDimitry Andric ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { 1060b57cec5SDimitry Andric ExnObj = ExcIVI->getOperand(1); 1070b57cec5SDimitry Andric SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1)); 1080b57cec5SDimitry Andric EraseIVIs = true; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric if (!ExnObj) 1140fca6ea1SDimitry Andric ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", 1150fca6ea1SDimitry Andric RI->getIterator()); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric RI->eraseFromParent(); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric if (EraseIVIs) { 1200b57cec5SDimitry Andric if (SelIVI->use_empty()) 1210b57cec5SDimitry Andric SelIVI->eraseFromParent(); 1220b57cec5SDimitry Andric if (ExcIVI->use_empty()) 1230b57cec5SDimitry Andric ExcIVI->eraseFromParent(); 1240b57cec5SDimitry Andric if (SelLoad && SelLoad->use_empty()) 1250b57cec5SDimitry Andric SelLoad->eraseFromParent(); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric return ExnObj; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric size_t DwarfEHPrepare::pruneUnreachableResumes( 132e8d8bef9SDimitry Andric SmallVectorImpl<ResumeInst *> &Resumes, 1330b57cec5SDimitry Andric SmallVectorImpl<LandingPadInst *> &CleanupLPads) { 134e8d8bef9SDimitry Andric assert(DTU && "Should have DomTreeUpdater here."); 135e8d8bef9SDimitry Andric 1360b57cec5SDimitry Andric BitVector ResumeReachable(Resumes.size()); 1370b57cec5SDimitry Andric size_t ResumeIndex = 0; 1380b57cec5SDimitry Andric for (auto *RI : Resumes) { 1390b57cec5SDimitry Andric for (auto *LP : CleanupLPads) { 140e8d8bef9SDimitry Andric if (isPotentiallyReachable(LP, RI, nullptr, &DTU->getDomTree())) { 1410b57cec5SDimitry Andric ResumeReachable.set(ResumeIndex); 1420b57cec5SDimitry Andric break; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric ++ResumeIndex; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric // If everything is reachable, there is no change. 1490b57cec5SDimitry Andric if (ResumeReachable.all()) 1500b57cec5SDimitry Andric return Resumes.size(); 1510b57cec5SDimitry Andric 152e8d8bef9SDimitry Andric LLVMContext &Ctx = F.getContext(); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric // Otherwise, insert unreachable instructions and call simplifycfg. 1550b57cec5SDimitry Andric size_t ResumesLeft = 0; 1560b57cec5SDimitry Andric for (size_t I = 0, E = Resumes.size(); I < E; ++I) { 1570b57cec5SDimitry Andric ResumeInst *RI = Resumes[I]; 1580b57cec5SDimitry Andric if (ResumeReachable[I]) { 1590b57cec5SDimitry Andric Resumes[ResumesLeft++] = RI; 1600b57cec5SDimitry Andric } else { 1610b57cec5SDimitry Andric BasicBlock *BB = RI->getParent(); 1620fca6ea1SDimitry Andric new UnreachableInst(Ctx, RI->getIterator()); 1630b57cec5SDimitry Andric RI->eraseFromParent(); 164fe6060f1SDimitry Andric simplifyCFG(BB, *TTI, DTU); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric Resumes.resize(ResumesLeft); 1680b57cec5SDimitry Andric return ResumesLeft; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 171e8d8bef9SDimitry Andric bool DwarfEHPrepare::InsertUnwindResumeCalls() { 1720b57cec5SDimitry Andric SmallVector<ResumeInst *, 16> Resumes; 1730b57cec5SDimitry Andric SmallVector<LandingPadInst *, 16> CleanupLPads; 174fe6060f1SDimitry Andric if (F.doesNotThrow()) 175fe6060f1SDimitry Andric NumNoUnwind++; 176fe6060f1SDimitry Andric else 177fe6060f1SDimitry Andric NumUnwind++; 178e8d8bef9SDimitry Andric for (BasicBlock &BB : F) { 1790b57cec5SDimitry Andric if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator())) 1800b57cec5SDimitry Andric Resumes.push_back(RI); 1810b57cec5SDimitry Andric if (auto *LP = BB.getLandingPadInst()) 1820b57cec5SDimitry Andric if (LP->isCleanup()) 1830b57cec5SDimitry Andric CleanupLPads.push_back(LP); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 186fe6060f1SDimitry Andric NumCleanupLandingPadsRemaining += CleanupLPads.size(); 187fe6060f1SDimitry Andric 1880b57cec5SDimitry Andric if (Resumes.empty()) 1890b57cec5SDimitry Andric return false; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // Check the personality, don't do anything if it's scope-based. 192e8d8bef9SDimitry Andric EHPersonality Pers = classifyEHPersonality(F.getPersonalityFn()); 1930b57cec5SDimitry Andric if (isScopedEHPersonality(Pers)) 1940b57cec5SDimitry Andric return false; 1950b57cec5SDimitry Andric 196e8d8bef9SDimitry Andric LLVMContext &Ctx = F.getContext(); 1970b57cec5SDimitry Andric 1985ffd83dbSDimitry Andric size_t ResumesLeft = Resumes.size(); 1995f757f3fSDimitry Andric if (OptLevel != CodeGenOptLevel::None) { 200e8d8bef9SDimitry Andric ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads); 201fe6060f1SDimitry Andric #if LLVM_ENABLE_STATS 202fe6060f1SDimitry Andric unsigned NumRemainingLPs = 0; 203fe6060f1SDimitry Andric for (BasicBlock &BB : F) { 204fe6060f1SDimitry Andric if (auto *LP = BB.getLandingPadInst()) 205fe6060f1SDimitry Andric if (LP->isCleanup()) 206fe6060f1SDimitry Andric NumRemainingLPs++; 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric NumCleanupLandingPadsUnreachable += CleanupLPads.size() - NumRemainingLPs; 209fe6060f1SDimitry Andric NumCleanupLandingPadsRemaining -= CleanupLPads.size() - NumRemainingLPs; 210fe6060f1SDimitry Andric #endif 211fe6060f1SDimitry Andric } 2125ffd83dbSDimitry Andric 2130b57cec5SDimitry Andric if (ResumesLeft == 0) 2140b57cec5SDimitry Andric return true; // We pruned them all. 2150b57cec5SDimitry Andric 216349cc55cSDimitry Andric // RewindFunction - _Unwind_Resume or the target equivalent. 217349cc55cSDimitry Andric FunctionCallee RewindFunction; 218349cc55cSDimitry Andric CallingConv::ID RewindFunctionCallingConv; 219349cc55cSDimitry Andric FunctionType *FTy; 220349cc55cSDimitry Andric const char *RewindName; 221349cc55cSDimitry Andric bool DoesRewindFunctionNeedExceptionObject; 222349cc55cSDimitry Andric 223349cc55cSDimitry Andric if ((Pers == EHPersonality::GNU_CXX || Pers == EHPersonality::GNU_CXX_SjLj) && 224349cc55cSDimitry Andric TargetTriple.isTargetEHABICompatible()) { 225349cc55cSDimitry Andric RewindName = TLI.getLibcallName(RTLIB::CXA_END_CLEANUP); 226349cc55cSDimitry Andric FTy = FunctionType::get(Type::getVoidTy(Ctx), false); 227349cc55cSDimitry Andric RewindFunctionCallingConv = 228349cc55cSDimitry Andric TLI.getLibcallCallingConv(RTLIB::CXA_END_CLEANUP); 229349cc55cSDimitry Andric DoesRewindFunctionNeedExceptionObject = false; 230349cc55cSDimitry Andric } else { 231349cc55cSDimitry Andric RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); 2325f757f3fSDimitry Andric FTy = FunctionType::get(Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx), 2335f757f3fSDimitry Andric false); 234349cc55cSDimitry Andric RewindFunctionCallingConv = TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME); 235349cc55cSDimitry Andric DoesRewindFunctionNeedExceptionObject = true; 2360b57cec5SDimitry Andric } 237349cc55cSDimitry Andric RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric // Create the basic block where the _Unwind_Resume call will live. 2400b57cec5SDimitry Andric if (ResumesLeft == 1) { 2410b57cec5SDimitry Andric // Instead of creating a new BB and PHI node, just append the call to 2420b57cec5SDimitry Andric // _Unwind_Resume to the end of the single resume block. 2430b57cec5SDimitry Andric ResumeInst *RI = Resumes.front(); 2440b57cec5SDimitry Andric BasicBlock *UnwindBB = RI->getParent(); 2450b57cec5SDimitry Andric Value *ExnObj = GetExceptionObject(RI); 246349cc55cSDimitry Andric llvm::SmallVector<Value *, 1> RewindFunctionArgs; 247349cc55cSDimitry Andric if (DoesRewindFunctionNeedExceptionObject) 248349cc55cSDimitry Andric RewindFunctionArgs.push_back(ExnObj); 2490b57cec5SDimitry Andric 250349cc55cSDimitry Andric // Call the rewind function. 251349cc55cSDimitry Andric CallInst *CI = 252349cc55cSDimitry Andric CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB); 2536246ae0bSDimitry Andric // The verifier requires that all calls of debug-info-bearing functions 2546246ae0bSDimitry Andric // from debug-info-bearing functions have a debug location (for inlining 2556246ae0bSDimitry Andric // purposes). Assign a dummy location to satisfy the constraint. 2566246ae0bSDimitry Andric Function *RewindFn = dyn_cast<Function>(RewindFunction.getCallee()); 2576246ae0bSDimitry Andric if (RewindFn && RewindFn->getSubprogram()) 2586246ae0bSDimitry Andric if (DISubprogram *SP = F.getSubprogram()) 2596246ae0bSDimitry Andric CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP)); 260349cc55cSDimitry Andric CI->setCallingConv(RewindFunctionCallingConv); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric // We never expect _Unwind_Resume to return. 263e8d8bef9SDimitry Andric CI->setDoesNotReturn(); 2640b57cec5SDimitry Andric new UnreachableInst(Ctx, UnwindBB); 2650b57cec5SDimitry Andric return true; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 268e8d8bef9SDimitry Andric std::vector<DominatorTree::UpdateType> Updates; 269e8d8bef9SDimitry Andric Updates.reserve(Resumes.size()); 270e8d8bef9SDimitry Andric 271349cc55cSDimitry Andric llvm::SmallVector<Value *, 1> RewindFunctionArgs; 272349cc55cSDimitry Andric 273e8d8bef9SDimitry Andric BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F); 2745f757f3fSDimitry Andric PHINode *PN = PHINode::Create(PointerType::getUnqual(Ctx), ResumesLeft, 2755f757f3fSDimitry Andric "exn.obj", UnwindBB); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // Extract the exception object from the ResumeInst and add it to the PHI node 2780b57cec5SDimitry Andric // that feeds the _Unwind_Resume call. 2790b57cec5SDimitry Andric for (ResumeInst *RI : Resumes) { 2800b57cec5SDimitry Andric BasicBlock *Parent = RI->getParent(); 2810b57cec5SDimitry Andric BranchInst::Create(UnwindBB, Parent); 282e8d8bef9SDimitry Andric Updates.push_back({DominatorTree::Insert, Parent, UnwindBB}); 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric Value *ExnObj = GetExceptionObject(RI); 2850b57cec5SDimitry Andric PN->addIncoming(ExnObj, Parent); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric ++NumResumesLowered; 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 290349cc55cSDimitry Andric if (DoesRewindFunctionNeedExceptionObject) 291349cc55cSDimitry Andric RewindFunctionArgs.push_back(PN); 292349cc55cSDimitry Andric 2930b57cec5SDimitry Andric // Call the function. 294349cc55cSDimitry Andric CallInst *CI = 295349cc55cSDimitry Andric CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB); 296*6c4b055cSDimitry Andric // The verifier requires that all calls of debug-info-bearing functions 297*6c4b055cSDimitry Andric // from debug-info-bearing functions have a debug location (for inlining 298*6c4b055cSDimitry Andric // purposes). Assign a dummy location to satisfy the constraint. 299*6c4b055cSDimitry Andric Function *RewindFn = dyn_cast<Function>(RewindFunction.getCallee()); 300*6c4b055cSDimitry Andric if (RewindFn && RewindFn->getSubprogram()) 301*6c4b055cSDimitry Andric if (DISubprogram *SP = F.getSubprogram()) 302*6c4b055cSDimitry Andric CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP)); 303349cc55cSDimitry Andric CI->setCallingConv(RewindFunctionCallingConv); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // We never expect _Unwind_Resume to return. 306e8d8bef9SDimitry Andric CI->setDoesNotReturn(); 3070b57cec5SDimitry Andric new UnreachableInst(Ctx, UnwindBB); 308e8d8bef9SDimitry Andric 309fe6060f1SDimitry Andric if (DTU) 310e8d8bef9SDimitry Andric DTU->applyUpdates(Updates); 311e8d8bef9SDimitry Andric 3120b57cec5SDimitry Andric return true; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 315e8d8bef9SDimitry Andric bool DwarfEHPrepare::run() { 316e8d8bef9SDimitry Andric bool Changed = InsertUnwindResumeCalls(); 317e8d8bef9SDimitry Andric 318e8d8bef9SDimitry Andric return Changed; 319e8d8bef9SDimitry Andric } 320e8d8bef9SDimitry Andric 3215f757f3fSDimitry Andric static bool prepareDwarfEH(CodeGenOptLevel OptLevel, Function &F, 322e8d8bef9SDimitry Andric const TargetLowering &TLI, DominatorTree *DT, 323349cc55cSDimitry Andric const TargetTransformInfo *TTI, 324349cc55cSDimitry Andric const Triple &TargetTriple) { 325fe6060f1SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 326e8d8bef9SDimitry Andric 327349cc55cSDimitry Andric return DwarfEHPrepare(OptLevel, F, TLI, DT ? &DTU : nullptr, TTI, 328349cc55cSDimitry Andric TargetTriple) 329e8d8bef9SDimitry Andric .run(); 330e8d8bef9SDimitry Andric } 331e8d8bef9SDimitry Andric 332e8d8bef9SDimitry Andric namespace { 333e8d8bef9SDimitry Andric 334e8d8bef9SDimitry Andric class DwarfEHPrepareLegacyPass : public FunctionPass { 335e8d8bef9SDimitry Andric 3365f757f3fSDimitry Andric CodeGenOptLevel OptLevel; 337e8d8bef9SDimitry Andric 338e8d8bef9SDimitry Andric public: 339e8d8bef9SDimitry Andric static char ID; // Pass identification, replacement for typeid. 340e8d8bef9SDimitry Andric 3415f757f3fSDimitry Andric DwarfEHPrepareLegacyPass(CodeGenOptLevel OptLevel = CodeGenOptLevel::Default) 342e8d8bef9SDimitry Andric : FunctionPass(ID), OptLevel(OptLevel) {} 343e8d8bef9SDimitry Andric 344e8d8bef9SDimitry Andric bool runOnFunction(Function &F) override { 3450b57cec5SDimitry Andric const TargetMachine &TM = 3460b57cec5SDimitry Andric getAnalysis<TargetPassConfig>().getTM<TargetMachine>(); 347e8d8bef9SDimitry Andric const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering(); 348e8d8bef9SDimitry Andric DominatorTree *DT = nullptr; 349e8d8bef9SDimitry Andric const TargetTransformInfo *TTI = nullptr; 350fe6060f1SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) 351fe6060f1SDimitry Andric DT = &DTWP->getDomTree(); 3525f757f3fSDimitry Andric if (OptLevel != CodeGenOptLevel::None) { 353fe6060f1SDimitry Andric if (!DT) 354e8d8bef9SDimitry Andric DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 355e8d8bef9SDimitry Andric TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 356e8d8bef9SDimitry Andric } 357349cc55cSDimitry Andric return prepareDwarfEH(OptLevel, F, TLI, DT, TTI, TM.getTargetTriple()); 358e8d8bef9SDimitry Andric } 359e8d8bef9SDimitry Andric 360e8d8bef9SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 361e8d8bef9SDimitry Andric AU.addRequired<TargetPassConfig>(); 362e8d8bef9SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 3635f757f3fSDimitry Andric if (OptLevel != CodeGenOptLevel::None) { 364e8d8bef9SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 365e8d8bef9SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 366e8d8bef9SDimitry Andric } 367fe6060f1SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 368e8d8bef9SDimitry Andric } 369e8d8bef9SDimitry Andric 370e8d8bef9SDimitry Andric StringRef getPassName() const override { 371e8d8bef9SDimitry Andric return "Exception handling preparation"; 372e8d8bef9SDimitry Andric } 373e8d8bef9SDimitry Andric }; 374e8d8bef9SDimitry Andric 375e8d8bef9SDimitry Andric } // end anonymous namespace 376e8d8bef9SDimitry Andric 3775f757f3fSDimitry Andric PreservedAnalyses DwarfEHPreparePass::run(Function &F, 3785f757f3fSDimitry Andric FunctionAnalysisManager &FAM) { 3795f757f3fSDimitry Andric const auto &TLI = *TM->getSubtargetImpl(F)->getTargetLowering(); 3805f757f3fSDimitry Andric auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F); 3815f757f3fSDimitry Andric const TargetTransformInfo *TTI = nullptr; 3825f757f3fSDimitry Andric auto OptLevel = TM->getOptLevel(); 3835f757f3fSDimitry Andric if (OptLevel != CodeGenOptLevel::None) { 3845f757f3fSDimitry Andric if (!DT) 3855f757f3fSDimitry Andric DT = &FAM.getResult<DominatorTreeAnalysis>(F); 3865f757f3fSDimitry Andric TTI = &FAM.getResult<TargetIRAnalysis>(F); 3875f757f3fSDimitry Andric } 3885f757f3fSDimitry Andric bool Changed = 3895f757f3fSDimitry Andric prepareDwarfEH(OptLevel, F, TLI, DT, TTI, TM->getTargetTriple()); 3905f757f3fSDimitry Andric 3915f757f3fSDimitry Andric if (!Changed) 3925f757f3fSDimitry Andric return PreservedAnalyses::all(); 3935f757f3fSDimitry Andric PreservedAnalyses PA; 3945f757f3fSDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 3955f757f3fSDimitry Andric return PA; 3965f757f3fSDimitry Andric } 3975f757f3fSDimitry Andric 398e8d8bef9SDimitry Andric char DwarfEHPrepareLegacyPass::ID = 0; 399e8d8bef9SDimitry Andric 400e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE, 401e8d8bef9SDimitry Andric "Prepare DWARF exceptions", false, false) 402e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 403e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 404e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 405e8d8bef9SDimitry Andric INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass, DEBUG_TYPE, 406e8d8bef9SDimitry Andric "Prepare DWARF exceptions", false, false) 407e8d8bef9SDimitry Andric 4085f757f3fSDimitry Andric FunctionPass *llvm::createDwarfEHPass(CodeGenOptLevel OptLevel) { 409e8d8bef9SDimitry Andric return new DwarfEHPrepareLegacyPass(OptLevel); 4100b57cec5SDimitry Andric } 411