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 140b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 160b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 170b57cec5SDimitry Andric #include "llvm/Analysis/CFG.h" 18e8d8bef9SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 190b57cec5SDimitry Andric #include "llvm/Analysis/EHPersonalities.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/RuntimeLibcalls.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" 270b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 280b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 290b57cec5SDimitry Andric #include "llvm/IR/Function.h" 300b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 310b57cec5SDimitry Andric #include "llvm/IR/Module.h" 320b57cec5SDimitry Andric #include "llvm/IR/Type.h" 33480093f4SDimitry Andric #include "llvm/InitializePasses.h" 340b57cec5SDimitry Andric #include "llvm/Pass.h" 350b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 360b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 37480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 380b57cec5SDimitry Andric #include <cstddef> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric using namespace llvm; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric #define DEBUG_TYPE "dwarfehprepare" 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric STATISTIC(NumResumesLowered, "Number of resume calls lowered"); 45*fe6060f1SDimitry Andric STATISTIC(NumCleanupLandingPadsUnreachable, 46*fe6060f1SDimitry Andric "Number of cleanup landing pads found unreachable"); 47*fe6060f1SDimitry Andric STATISTIC(NumCleanupLandingPadsRemaining, 48*fe6060f1SDimitry Andric "Number of cleanup landing pads remaining"); 49*fe6060f1SDimitry Andric STATISTIC(NumNoUnwind, "Number of functions with nounwind"); 50*fe6060f1SDimitry Andric STATISTIC(NumUnwind, "Number of functions with unwind"); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric namespace { 530b57cec5SDimitry Andric 54e8d8bef9SDimitry Andric class DwarfEHPrepare { 555ffd83dbSDimitry Andric CodeGenOpt::Level OptLevel; 560b57cec5SDimitry Andric 57e8d8bef9SDimitry Andric // RewindFunction - _Unwind_Resume or the target equivalent. 58e8d8bef9SDimitry Andric FunctionCallee &RewindFunction; 590b57cec5SDimitry Andric 60e8d8bef9SDimitry Andric Function &F; 61e8d8bef9SDimitry Andric const TargetLowering &TLI; 62e8d8bef9SDimitry Andric DomTreeUpdater *DTU; 63e8d8bef9SDimitry Andric const TargetTransformInfo *TTI; 640b57cec5SDimitry Andric 65e8d8bef9SDimitry Andric /// Return the exception object from the value passed into 660b57cec5SDimitry Andric /// the 'resume' instruction (typically an aggregate). Clean up any dead 670b57cec5SDimitry Andric /// instructions, including the 'resume' instruction. 68e8d8bef9SDimitry Andric Value *GetExceptionObject(ResumeInst *RI); 69e8d8bef9SDimitry Andric 70e8d8bef9SDimitry Andric /// Replace resumes that are not reachable from a cleanup landing pad with 71e8d8bef9SDimitry Andric /// unreachable and then simplify those blocks. 72e8d8bef9SDimitry Andric size_t 73e8d8bef9SDimitry Andric pruneUnreachableResumes(SmallVectorImpl<ResumeInst *> &Resumes, 74e8d8bef9SDimitry Andric SmallVectorImpl<LandingPadInst *> &CleanupLPads); 75e8d8bef9SDimitry Andric 76e8d8bef9SDimitry Andric /// Convert the ResumeInsts that are still present 77e8d8bef9SDimitry Andric /// into calls to the appropriate _Unwind_Resume function. 78e8d8bef9SDimitry Andric bool InsertUnwindResumeCalls(); 79e8d8bef9SDimitry Andric 80e8d8bef9SDimitry Andric public: 81e8d8bef9SDimitry Andric DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_, 82e8d8bef9SDimitry Andric Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_, 83e8d8bef9SDimitry Andric const TargetTransformInfo *TTI_) 84e8d8bef9SDimitry Andric : OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_), 85e8d8bef9SDimitry Andric DTU(DTU_), TTI(TTI_) {} 86e8d8bef9SDimitry Andric 87e8d8bef9SDimitry Andric bool run(); 88e8d8bef9SDimitry Andric }; 89e8d8bef9SDimitry Andric 90e8d8bef9SDimitry Andric } // namespace 91e8d8bef9SDimitry Andric 920b57cec5SDimitry Andric Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { 930b57cec5SDimitry Andric Value *V = RI->getOperand(0); 940b57cec5SDimitry Andric Value *ExnObj = nullptr; 950b57cec5SDimitry Andric InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V); 960b57cec5SDimitry Andric LoadInst *SelLoad = nullptr; 970b57cec5SDimitry Andric InsertValueInst *ExcIVI = nullptr; 980b57cec5SDimitry Andric bool EraseIVIs = false; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric if (SelIVI) { 1010b57cec5SDimitry Andric if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { 1020b57cec5SDimitry Andric ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0)); 1030b57cec5SDimitry Andric if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) && 1040b57cec5SDimitry Andric ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { 1050b57cec5SDimitry Andric ExnObj = ExcIVI->getOperand(1); 1060b57cec5SDimitry Andric SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1)); 1070b57cec5SDimitry Andric EraseIVIs = true; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric if (!ExnObj) 1130b57cec5SDimitry Andric ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric RI->eraseFromParent(); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (EraseIVIs) { 1180b57cec5SDimitry Andric if (SelIVI->use_empty()) 1190b57cec5SDimitry Andric SelIVI->eraseFromParent(); 1200b57cec5SDimitry Andric if (ExcIVI->use_empty()) 1210b57cec5SDimitry Andric ExcIVI->eraseFromParent(); 1220b57cec5SDimitry Andric if (SelLoad && SelLoad->use_empty()) 1230b57cec5SDimitry Andric SelLoad->eraseFromParent(); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric return ExnObj; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric size_t DwarfEHPrepare::pruneUnreachableResumes( 130e8d8bef9SDimitry Andric SmallVectorImpl<ResumeInst *> &Resumes, 1310b57cec5SDimitry Andric SmallVectorImpl<LandingPadInst *> &CleanupLPads) { 132e8d8bef9SDimitry Andric assert(DTU && "Should have DomTreeUpdater here."); 133e8d8bef9SDimitry Andric 1340b57cec5SDimitry Andric BitVector ResumeReachable(Resumes.size()); 1350b57cec5SDimitry Andric size_t ResumeIndex = 0; 1360b57cec5SDimitry Andric for (auto *RI : Resumes) { 1370b57cec5SDimitry Andric for (auto *LP : CleanupLPads) { 138e8d8bef9SDimitry Andric if (isPotentiallyReachable(LP, RI, nullptr, &DTU->getDomTree())) { 1390b57cec5SDimitry Andric ResumeReachable.set(ResumeIndex); 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric ++ResumeIndex; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // If everything is reachable, there is no change. 1470b57cec5SDimitry Andric if (ResumeReachable.all()) 1480b57cec5SDimitry Andric return Resumes.size(); 1490b57cec5SDimitry Andric 150e8d8bef9SDimitry Andric LLVMContext &Ctx = F.getContext(); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Otherwise, insert unreachable instructions and call simplifycfg. 1530b57cec5SDimitry Andric size_t ResumesLeft = 0; 1540b57cec5SDimitry Andric for (size_t I = 0, E = Resumes.size(); I < E; ++I) { 1550b57cec5SDimitry Andric ResumeInst *RI = Resumes[I]; 1560b57cec5SDimitry Andric if (ResumeReachable[I]) { 1570b57cec5SDimitry Andric Resumes[ResumesLeft++] = RI; 1580b57cec5SDimitry Andric } else { 1590b57cec5SDimitry Andric BasicBlock *BB = RI->getParent(); 1600b57cec5SDimitry Andric new UnreachableInst(Ctx, RI); 1610b57cec5SDimitry Andric RI->eraseFromParent(); 162*fe6060f1SDimitry Andric simplifyCFG(BB, *TTI, DTU); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric Resumes.resize(ResumesLeft); 1660b57cec5SDimitry Andric return ResumesLeft; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 169e8d8bef9SDimitry Andric bool DwarfEHPrepare::InsertUnwindResumeCalls() { 1700b57cec5SDimitry Andric SmallVector<ResumeInst *, 16> Resumes; 1710b57cec5SDimitry Andric SmallVector<LandingPadInst *, 16> CleanupLPads; 172*fe6060f1SDimitry Andric if (F.doesNotThrow()) 173*fe6060f1SDimitry Andric NumNoUnwind++; 174*fe6060f1SDimitry Andric else 175*fe6060f1SDimitry Andric NumUnwind++; 176e8d8bef9SDimitry Andric for (BasicBlock &BB : F) { 1770b57cec5SDimitry Andric if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator())) 1780b57cec5SDimitry Andric Resumes.push_back(RI); 1790b57cec5SDimitry Andric if (auto *LP = BB.getLandingPadInst()) 1800b57cec5SDimitry Andric if (LP->isCleanup()) 1810b57cec5SDimitry Andric CleanupLPads.push_back(LP); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 184*fe6060f1SDimitry Andric NumCleanupLandingPadsRemaining += CleanupLPads.size(); 185*fe6060f1SDimitry Andric 1860b57cec5SDimitry Andric if (Resumes.empty()) 1870b57cec5SDimitry Andric return false; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // Check the personality, don't do anything if it's scope-based. 190e8d8bef9SDimitry Andric EHPersonality Pers = classifyEHPersonality(F.getPersonalityFn()); 1910b57cec5SDimitry Andric if (isScopedEHPersonality(Pers)) 1920b57cec5SDimitry Andric return false; 1930b57cec5SDimitry Andric 194e8d8bef9SDimitry Andric LLVMContext &Ctx = F.getContext(); 1950b57cec5SDimitry Andric 1965ffd83dbSDimitry Andric size_t ResumesLeft = Resumes.size(); 197*fe6060f1SDimitry Andric if (OptLevel != CodeGenOpt::None) { 198e8d8bef9SDimitry Andric ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads); 199*fe6060f1SDimitry Andric #if LLVM_ENABLE_STATS 200*fe6060f1SDimitry Andric unsigned NumRemainingLPs = 0; 201*fe6060f1SDimitry Andric for (BasicBlock &BB : F) { 202*fe6060f1SDimitry Andric if (auto *LP = BB.getLandingPadInst()) 203*fe6060f1SDimitry Andric if (LP->isCleanup()) 204*fe6060f1SDimitry Andric NumRemainingLPs++; 205*fe6060f1SDimitry Andric } 206*fe6060f1SDimitry Andric NumCleanupLandingPadsUnreachable += CleanupLPads.size() - NumRemainingLPs; 207*fe6060f1SDimitry Andric NumCleanupLandingPadsRemaining -= CleanupLPads.size() - NumRemainingLPs; 208*fe6060f1SDimitry Andric #endif 209*fe6060f1SDimitry Andric } 2105ffd83dbSDimitry Andric 2110b57cec5SDimitry Andric if (ResumesLeft == 0) 2120b57cec5SDimitry Andric return true; // We pruned them all. 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric // Find the rewind function if we didn't already. 2150b57cec5SDimitry Andric if (!RewindFunction) { 216e8d8bef9SDimitry Andric FunctionType *FTy = 217e8d8bef9SDimitry Andric FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false); 218e8d8bef9SDimitry Andric const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); 219e8d8bef9SDimitry Andric RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric // Create the basic block where the _Unwind_Resume call will live. 2230b57cec5SDimitry Andric if (ResumesLeft == 1) { 2240b57cec5SDimitry Andric // Instead of creating a new BB and PHI node, just append the call to 2250b57cec5SDimitry Andric // _Unwind_Resume to the end of the single resume block. 2260b57cec5SDimitry Andric ResumeInst *RI = Resumes.front(); 2270b57cec5SDimitry Andric BasicBlock *UnwindBB = RI->getParent(); 2280b57cec5SDimitry Andric Value *ExnObj = GetExceptionObject(RI); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Call the _Unwind_Resume function. 2310b57cec5SDimitry Andric CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); 232e8d8bef9SDimitry Andric CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // We never expect _Unwind_Resume to return. 235e8d8bef9SDimitry Andric CI->setDoesNotReturn(); 2360b57cec5SDimitry Andric new UnreachableInst(Ctx, UnwindBB); 2370b57cec5SDimitry Andric return true; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 240e8d8bef9SDimitry Andric std::vector<DominatorTree::UpdateType> Updates; 241e8d8bef9SDimitry Andric Updates.reserve(Resumes.size()); 242e8d8bef9SDimitry Andric 243e8d8bef9SDimitry Andric BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F); 244e8d8bef9SDimitry Andric PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj", 245e8d8bef9SDimitry Andric UnwindBB); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // Extract the exception object from the ResumeInst and add it to the PHI node 2480b57cec5SDimitry Andric // that feeds the _Unwind_Resume call. 2490b57cec5SDimitry Andric for (ResumeInst *RI : Resumes) { 2500b57cec5SDimitry Andric BasicBlock *Parent = RI->getParent(); 2510b57cec5SDimitry Andric BranchInst::Create(UnwindBB, Parent); 252e8d8bef9SDimitry Andric Updates.push_back({DominatorTree::Insert, Parent, UnwindBB}); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric Value *ExnObj = GetExceptionObject(RI); 2550b57cec5SDimitry Andric PN->addIncoming(ExnObj, Parent); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric ++NumResumesLowered; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // Call the function. 2610b57cec5SDimitry Andric CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); 262e8d8bef9SDimitry Andric CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // We never expect _Unwind_Resume to return. 265e8d8bef9SDimitry Andric CI->setDoesNotReturn(); 2660b57cec5SDimitry Andric new UnreachableInst(Ctx, UnwindBB); 267e8d8bef9SDimitry Andric 268*fe6060f1SDimitry Andric if (DTU) 269e8d8bef9SDimitry Andric DTU->applyUpdates(Updates); 270e8d8bef9SDimitry Andric 2710b57cec5SDimitry Andric return true; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 274e8d8bef9SDimitry Andric bool DwarfEHPrepare::run() { 275e8d8bef9SDimitry Andric bool Changed = InsertUnwindResumeCalls(); 276e8d8bef9SDimitry Andric 277e8d8bef9SDimitry Andric return Changed; 278e8d8bef9SDimitry Andric } 279e8d8bef9SDimitry Andric 280e8d8bef9SDimitry Andric static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, 281e8d8bef9SDimitry Andric FunctionCallee &RewindFunction, Function &F, 282e8d8bef9SDimitry Andric const TargetLowering &TLI, DominatorTree *DT, 283e8d8bef9SDimitry Andric const TargetTransformInfo *TTI) { 284*fe6060f1SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 285e8d8bef9SDimitry Andric 286e8d8bef9SDimitry Andric return DwarfEHPrepare(OptLevel, RewindFunction, F, TLI, DT ? &DTU : nullptr, 287e8d8bef9SDimitry Andric TTI) 288e8d8bef9SDimitry Andric .run(); 289e8d8bef9SDimitry Andric } 290e8d8bef9SDimitry Andric 291e8d8bef9SDimitry Andric namespace { 292e8d8bef9SDimitry Andric 293e8d8bef9SDimitry Andric class DwarfEHPrepareLegacyPass : public FunctionPass { 294e8d8bef9SDimitry Andric // RewindFunction - _Unwind_Resume or the target equivalent. 295e8d8bef9SDimitry Andric FunctionCallee RewindFunction = nullptr; 296e8d8bef9SDimitry Andric 297e8d8bef9SDimitry Andric CodeGenOpt::Level OptLevel; 298e8d8bef9SDimitry Andric 299e8d8bef9SDimitry Andric public: 300e8d8bef9SDimitry Andric static char ID; // Pass identification, replacement for typeid. 301e8d8bef9SDimitry Andric 302e8d8bef9SDimitry Andric DwarfEHPrepareLegacyPass(CodeGenOpt::Level OptLevel = CodeGenOpt::Default) 303e8d8bef9SDimitry Andric : FunctionPass(ID), OptLevel(OptLevel) {} 304e8d8bef9SDimitry Andric 305e8d8bef9SDimitry Andric bool runOnFunction(Function &F) override { 3060b57cec5SDimitry Andric const TargetMachine &TM = 3070b57cec5SDimitry Andric getAnalysis<TargetPassConfig>().getTM<TargetMachine>(); 308e8d8bef9SDimitry Andric const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering(); 309e8d8bef9SDimitry Andric DominatorTree *DT = nullptr; 310e8d8bef9SDimitry Andric const TargetTransformInfo *TTI = nullptr; 311*fe6060f1SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) 312*fe6060f1SDimitry Andric DT = &DTWP->getDomTree(); 313e8d8bef9SDimitry Andric if (OptLevel != CodeGenOpt::None) { 314*fe6060f1SDimitry Andric if (!DT) 315e8d8bef9SDimitry Andric DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 316e8d8bef9SDimitry Andric TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 317e8d8bef9SDimitry Andric } 318e8d8bef9SDimitry Andric return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI); 319e8d8bef9SDimitry Andric } 320e8d8bef9SDimitry Andric 321e8d8bef9SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 322e8d8bef9SDimitry Andric AU.addRequired<TargetPassConfig>(); 323e8d8bef9SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 324e8d8bef9SDimitry Andric if (OptLevel != CodeGenOpt::None) { 325e8d8bef9SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 326e8d8bef9SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 327e8d8bef9SDimitry Andric } 328*fe6060f1SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 329e8d8bef9SDimitry Andric } 330e8d8bef9SDimitry Andric 331e8d8bef9SDimitry Andric StringRef getPassName() const override { 332e8d8bef9SDimitry Andric return "Exception handling preparation"; 333e8d8bef9SDimitry Andric } 334e8d8bef9SDimitry Andric }; 335e8d8bef9SDimitry Andric 336e8d8bef9SDimitry Andric } // end anonymous namespace 337e8d8bef9SDimitry Andric 338e8d8bef9SDimitry Andric char DwarfEHPrepareLegacyPass::ID = 0; 339e8d8bef9SDimitry Andric 340e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE, 341e8d8bef9SDimitry Andric "Prepare DWARF exceptions", false, false) 342e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 343e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 344e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 345e8d8bef9SDimitry Andric INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass, DEBUG_TYPE, 346e8d8bef9SDimitry Andric "Prepare DWARF exceptions", false, false) 347e8d8bef9SDimitry Andric 348e8d8bef9SDimitry Andric FunctionPass *llvm::createDwarfEHPass(CodeGenOpt::Level OptLevel) { 349e8d8bef9SDimitry Andric return new DwarfEHPrepareLegacyPass(OptLevel); 3500b57cec5SDimitry Andric } 351