xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/DwarfEHPrepare.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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"
18*e8d8bef9SDimitry 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");
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric namespace {
470b57cec5SDimitry Andric 
48*e8d8bef9SDimitry Andric class DwarfEHPrepare {
495ffd83dbSDimitry Andric   CodeGenOpt::Level OptLevel;
500b57cec5SDimitry Andric 
51*e8d8bef9SDimitry Andric   // RewindFunction - _Unwind_Resume or the target equivalent.
52*e8d8bef9SDimitry Andric   FunctionCallee &RewindFunction;
530b57cec5SDimitry Andric 
54*e8d8bef9SDimitry Andric   Function &F;
55*e8d8bef9SDimitry Andric   const TargetLowering &TLI;
56*e8d8bef9SDimitry Andric   DomTreeUpdater *DTU;
57*e8d8bef9SDimitry Andric   const TargetTransformInfo *TTI;
580b57cec5SDimitry Andric 
59*e8d8bef9SDimitry Andric   /// Return the exception object from the value passed into
600b57cec5SDimitry Andric   /// the 'resume' instruction (typically an aggregate). Clean up any dead
610b57cec5SDimitry Andric   /// instructions, including the 'resume' instruction.
62*e8d8bef9SDimitry Andric   Value *GetExceptionObject(ResumeInst *RI);
63*e8d8bef9SDimitry Andric 
64*e8d8bef9SDimitry Andric   /// Replace resumes that are not reachable from a cleanup landing pad with
65*e8d8bef9SDimitry Andric   /// unreachable and then simplify those blocks.
66*e8d8bef9SDimitry Andric   size_t
67*e8d8bef9SDimitry Andric   pruneUnreachableResumes(SmallVectorImpl<ResumeInst *> &Resumes,
68*e8d8bef9SDimitry Andric                           SmallVectorImpl<LandingPadInst *> &CleanupLPads);
69*e8d8bef9SDimitry Andric 
70*e8d8bef9SDimitry Andric   /// Convert the ResumeInsts that are still present
71*e8d8bef9SDimitry Andric   /// into calls to the appropriate _Unwind_Resume function.
72*e8d8bef9SDimitry Andric   bool InsertUnwindResumeCalls();
73*e8d8bef9SDimitry Andric 
74*e8d8bef9SDimitry Andric public:
75*e8d8bef9SDimitry Andric   DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_,
76*e8d8bef9SDimitry Andric                  Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_,
77*e8d8bef9SDimitry Andric                  const TargetTransformInfo *TTI_)
78*e8d8bef9SDimitry Andric       : OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_),
79*e8d8bef9SDimitry Andric         DTU(DTU_), TTI(TTI_) {}
80*e8d8bef9SDimitry Andric 
81*e8d8bef9SDimitry Andric   bool run();
82*e8d8bef9SDimitry Andric };
83*e8d8bef9SDimitry Andric 
84*e8d8bef9SDimitry Andric } // namespace
85*e8d8bef9SDimitry Andric 
860b57cec5SDimitry Andric Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
870b57cec5SDimitry Andric   Value *V = RI->getOperand(0);
880b57cec5SDimitry Andric   Value *ExnObj = nullptr;
890b57cec5SDimitry Andric   InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
900b57cec5SDimitry Andric   LoadInst *SelLoad = nullptr;
910b57cec5SDimitry Andric   InsertValueInst *ExcIVI = nullptr;
920b57cec5SDimitry Andric   bool EraseIVIs = false;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   if (SelIVI) {
950b57cec5SDimitry Andric     if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
960b57cec5SDimitry Andric       ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
970b57cec5SDimitry Andric       if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
980b57cec5SDimitry Andric           ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
990b57cec5SDimitry Andric         ExnObj = ExcIVI->getOperand(1);
1000b57cec5SDimitry Andric         SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
1010b57cec5SDimitry Andric         EraseIVIs = true;
1020b57cec5SDimitry Andric       }
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   if (!ExnObj)
1070b57cec5SDimitry Andric     ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   RI->eraseFromParent();
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   if (EraseIVIs) {
1120b57cec5SDimitry Andric     if (SelIVI->use_empty())
1130b57cec5SDimitry Andric       SelIVI->eraseFromParent();
1140b57cec5SDimitry Andric     if (ExcIVI->use_empty())
1150b57cec5SDimitry Andric       ExcIVI->eraseFromParent();
1160b57cec5SDimitry Andric     if (SelLoad && SelLoad->use_empty())
1170b57cec5SDimitry Andric       SelLoad->eraseFromParent();
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   return ExnObj;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric size_t DwarfEHPrepare::pruneUnreachableResumes(
124*e8d8bef9SDimitry Andric     SmallVectorImpl<ResumeInst *> &Resumes,
1250b57cec5SDimitry Andric     SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
126*e8d8bef9SDimitry Andric   assert(DTU && "Should have DomTreeUpdater here.");
127*e8d8bef9SDimitry Andric 
1280b57cec5SDimitry Andric   BitVector ResumeReachable(Resumes.size());
1290b57cec5SDimitry Andric   size_t ResumeIndex = 0;
1300b57cec5SDimitry Andric   for (auto *RI : Resumes) {
1310b57cec5SDimitry Andric     for (auto *LP : CleanupLPads) {
132*e8d8bef9SDimitry Andric       if (isPotentiallyReachable(LP, RI, nullptr, &DTU->getDomTree())) {
1330b57cec5SDimitry Andric         ResumeReachable.set(ResumeIndex);
1340b57cec5SDimitry Andric         break;
1350b57cec5SDimitry Andric       }
1360b57cec5SDimitry Andric     }
1370b57cec5SDimitry Andric     ++ResumeIndex;
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   // If everything is reachable, there is no change.
1410b57cec5SDimitry Andric   if (ResumeReachable.all())
1420b57cec5SDimitry Andric     return Resumes.size();
1430b57cec5SDimitry Andric 
144*e8d8bef9SDimitry Andric   LLVMContext &Ctx = F.getContext();
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   // Otherwise, insert unreachable instructions and call simplifycfg.
1470b57cec5SDimitry Andric   size_t ResumesLeft = 0;
1480b57cec5SDimitry Andric   for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
1490b57cec5SDimitry Andric     ResumeInst *RI = Resumes[I];
1500b57cec5SDimitry Andric     if (ResumeReachable[I]) {
1510b57cec5SDimitry Andric       Resumes[ResumesLeft++] = RI;
1520b57cec5SDimitry Andric     } else {
1530b57cec5SDimitry Andric       BasicBlock *BB = RI->getParent();
1540b57cec5SDimitry Andric       new UnreachableInst(Ctx, RI);
1550b57cec5SDimitry Andric       RI->eraseFromParent();
156*e8d8bef9SDimitry Andric       simplifyCFG(BB, *TTI, RequireAndPreserveDomTree ? DTU : nullptr);
1570b57cec5SDimitry Andric     }
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric   Resumes.resize(ResumesLeft);
1600b57cec5SDimitry Andric   return ResumesLeft;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
163*e8d8bef9SDimitry Andric bool DwarfEHPrepare::InsertUnwindResumeCalls() {
1640b57cec5SDimitry Andric   SmallVector<ResumeInst *, 16> Resumes;
1650b57cec5SDimitry Andric   SmallVector<LandingPadInst *, 16> CleanupLPads;
166*e8d8bef9SDimitry Andric   for (BasicBlock &BB : F) {
1670b57cec5SDimitry Andric     if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
1680b57cec5SDimitry Andric       Resumes.push_back(RI);
1690b57cec5SDimitry Andric     if (auto *LP = BB.getLandingPadInst())
1700b57cec5SDimitry Andric       if (LP->isCleanup())
1710b57cec5SDimitry Andric         CleanupLPads.push_back(LP);
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   if (Resumes.empty())
1750b57cec5SDimitry Andric     return false;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   // Check the personality, don't do anything if it's scope-based.
178*e8d8bef9SDimitry Andric   EHPersonality Pers = classifyEHPersonality(F.getPersonalityFn());
1790b57cec5SDimitry Andric   if (isScopedEHPersonality(Pers))
1800b57cec5SDimitry Andric     return false;
1810b57cec5SDimitry Andric 
182*e8d8bef9SDimitry Andric   LLVMContext &Ctx = F.getContext();
1830b57cec5SDimitry Andric 
1845ffd83dbSDimitry Andric   size_t ResumesLeft = Resumes.size();
1855ffd83dbSDimitry Andric   if (OptLevel != CodeGenOpt::None)
186*e8d8bef9SDimitry Andric     ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads);
1875ffd83dbSDimitry Andric 
1880b57cec5SDimitry Andric   if (ResumesLeft == 0)
1890b57cec5SDimitry Andric     return true; // We pruned them all.
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // Find the rewind function if we didn't already.
1920b57cec5SDimitry Andric   if (!RewindFunction) {
193*e8d8bef9SDimitry Andric     FunctionType *FTy =
194*e8d8bef9SDimitry Andric         FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false);
195*e8d8bef9SDimitry Andric     const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME);
196*e8d8bef9SDimitry Andric     RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   // Create the basic block where the _Unwind_Resume call will live.
2000b57cec5SDimitry Andric   if (ResumesLeft == 1) {
2010b57cec5SDimitry Andric     // Instead of creating a new BB and PHI node, just append the call to
2020b57cec5SDimitry Andric     // _Unwind_Resume to the end of the single resume block.
2030b57cec5SDimitry Andric     ResumeInst *RI = Resumes.front();
2040b57cec5SDimitry Andric     BasicBlock *UnwindBB = RI->getParent();
2050b57cec5SDimitry Andric     Value *ExnObj = GetExceptionObject(RI);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     // Call the _Unwind_Resume function.
2080b57cec5SDimitry Andric     CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
209*e8d8bef9SDimitry Andric     CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME));
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric     // We never expect _Unwind_Resume to return.
212*e8d8bef9SDimitry Andric     CI->setDoesNotReturn();
2130b57cec5SDimitry Andric     new UnreachableInst(Ctx, UnwindBB);
2140b57cec5SDimitry Andric     return true;
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric 
217*e8d8bef9SDimitry Andric   std::vector<DominatorTree::UpdateType> Updates;
218*e8d8bef9SDimitry Andric   Updates.reserve(Resumes.size());
219*e8d8bef9SDimitry Andric 
220*e8d8bef9SDimitry Andric   BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F);
221*e8d8bef9SDimitry Andric   PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj",
222*e8d8bef9SDimitry Andric                                 UnwindBB);
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   // Extract the exception object from the ResumeInst and add it to the PHI node
2250b57cec5SDimitry Andric   // that feeds the _Unwind_Resume call.
2260b57cec5SDimitry Andric   for (ResumeInst *RI : Resumes) {
2270b57cec5SDimitry Andric     BasicBlock *Parent = RI->getParent();
2280b57cec5SDimitry Andric     BranchInst::Create(UnwindBB, Parent);
229*e8d8bef9SDimitry Andric     Updates.push_back({DominatorTree::Insert, Parent, UnwindBB});
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric     Value *ExnObj = GetExceptionObject(RI);
2320b57cec5SDimitry Andric     PN->addIncoming(ExnObj, Parent);
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric     ++NumResumesLowered;
2350b57cec5SDimitry Andric   }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   // Call the function.
2380b57cec5SDimitry Andric   CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
239*e8d8bef9SDimitry Andric   CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME));
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   // We never expect _Unwind_Resume to return.
242*e8d8bef9SDimitry Andric   CI->setDoesNotReturn();
2430b57cec5SDimitry Andric   new UnreachableInst(Ctx, UnwindBB);
244*e8d8bef9SDimitry Andric 
245*e8d8bef9SDimitry Andric   if (DTU && RequireAndPreserveDomTree)
246*e8d8bef9SDimitry Andric     DTU->applyUpdates(Updates);
247*e8d8bef9SDimitry Andric 
2480b57cec5SDimitry Andric   return true;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
251*e8d8bef9SDimitry Andric bool DwarfEHPrepare::run() {
252*e8d8bef9SDimitry Andric   assert(((OptLevel == CodeGenOpt::None || !RequireAndPreserveDomTree) ||
253*e8d8bef9SDimitry Andric           (DTU &&
254*e8d8bef9SDimitry Andric            DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full))) &&
255*e8d8bef9SDimitry Andric          "Original domtree is invalid?");
256*e8d8bef9SDimitry Andric 
257*e8d8bef9SDimitry Andric   bool Changed = InsertUnwindResumeCalls();
258*e8d8bef9SDimitry Andric 
259*e8d8bef9SDimitry Andric   assert(((OptLevel == CodeGenOpt::None || !RequireAndPreserveDomTree) ||
260*e8d8bef9SDimitry Andric           (DTU &&
261*e8d8bef9SDimitry Andric            DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full))) &&
262*e8d8bef9SDimitry Andric          "Original domtree is invalid?");
263*e8d8bef9SDimitry Andric 
264*e8d8bef9SDimitry Andric   return Changed;
265*e8d8bef9SDimitry Andric }
266*e8d8bef9SDimitry Andric 
267*e8d8bef9SDimitry Andric static bool prepareDwarfEH(CodeGenOpt::Level OptLevel,
268*e8d8bef9SDimitry Andric                            FunctionCallee &RewindFunction, Function &F,
269*e8d8bef9SDimitry Andric                            const TargetLowering &TLI, DominatorTree *DT,
270*e8d8bef9SDimitry Andric                            const TargetTransformInfo *TTI) {
271*e8d8bef9SDimitry Andric   DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
272*e8d8bef9SDimitry Andric 
273*e8d8bef9SDimitry Andric   return DwarfEHPrepare(OptLevel, RewindFunction, F, TLI, DT ? &DTU : nullptr,
274*e8d8bef9SDimitry Andric                         TTI)
275*e8d8bef9SDimitry Andric       .run();
276*e8d8bef9SDimitry Andric }
277*e8d8bef9SDimitry Andric 
278*e8d8bef9SDimitry Andric namespace {
279*e8d8bef9SDimitry Andric 
280*e8d8bef9SDimitry Andric class DwarfEHPrepareLegacyPass : public FunctionPass {
281*e8d8bef9SDimitry Andric   // RewindFunction - _Unwind_Resume or the target equivalent.
282*e8d8bef9SDimitry Andric   FunctionCallee RewindFunction = nullptr;
283*e8d8bef9SDimitry Andric 
284*e8d8bef9SDimitry Andric   CodeGenOpt::Level OptLevel;
285*e8d8bef9SDimitry Andric 
286*e8d8bef9SDimitry Andric public:
287*e8d8bef9SDimitry Andric   static char ID; // Pass identification, replacement for typeid.
288*e8d8bef9SDimitry Andric 
289*e8d8bef9SDimitry Andric   DwarfEHPrepareLegacyPass(CodeGenOpt::Level OptLevel = CodeGenOpt::Default)
290*e8d8bef9SDimitry Andric       : FunctionPass(ID), OptLevel(OptLevel) {}
291*e8d8bef9SDimitry Andric 
292*e8d8bef9SDimitry Andric   bool runOnFunction(Function &F) override {
2930b57cec5SDimitry Andric     const TargetMachine &TM =
2940b57cec5SDimitry Andric         getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
295*e8d8bef9SDimitry Andric     const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering();
296*e8d8bef9SDimitry Andric     DominatorTree *DT = nullptr;
297*e8d8bef9SDimitry Andric     const TargetTransformInfo *TTI = nullptr;
298*e8d8bef9SDimitry Andric     if (OptLevel != CodeGenOpt::None) {
299*e8d8bef9SDimitry Andric       DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
300*e8d8bef9SDimitry Andric       TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
301*e8d8bef9SDimitry Andric     }
302*e8d8bef9SDimitry Andric     return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI);
303*e8d8bef9SDimitry Andric   }
304*e8d8bef9SDimitry Andric 
305*e8d8bef9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
306*e8d8bef9SDimitry Andric     AU.addRequired<TargetPassConfig>();
307*e8d8bef9SDimitry Andric     AU.addRequired<TargetTransformInfoWrapperPass>();
308*e8d8bef9SDimitry Andric     if (OptLevel != CodeGenOpt::None) {
309*e8d8bef9SDimitry Andric       AU.addRequired<DominatorTreeWrapperPass>();
310*e8d8bef9SDimitry Andric       AU.addRequired<TargetTransformInfoWrapperPass>();
311*e8d8bef9SDimitry Andric       if (RequireAndPreserveDomTree)
312*e8d8bef9SDimitry Andric         AU.addPreserved<DominatorTreeWrapperPass>();
313*e8d8bef9SDimitry Andric     }
314*e8d8bef9SDimitry Andric   }
315*e8d8bef9SDimitry Andric 
316*e8d8bef9SDimitry Andric   StringRef getPassName() const override {
317*e8d8bef9SDimitry Andric     return "Exception handling preparation";
318*e8d8bef9SDimitry Andric   }
319*e8d8bef9SDimitry Andric };
320*e8d8bef9SDimitry Andric 
321*e8d8bef9SDimitry Andric } // end anonymous namespace
322*e8d8bef9SDimitry Andric 
323*e8d8bef9SDimitry Andric char DwarfEHPrepareLegacyPass::ID = 0;
324*e8d8bef9SDimitry Andric 
325*e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
326*e8d8bef9SDimitry Andric                       "Prepare DWARF exceptions", false, false)
327*e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
328*e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
329*e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
330*e8d8bef9SDimitry Andric INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
331*e8d8bef9SDimitry Andric                     "Prepare DWARF exceptions", false, false)
332*e8d8bef9SDimitry Andric 
333*e8d8bef9SDimitry Andric FunctionPass *llvm::createDwarfEHPass(CodeGenOpt::Level OptLevel) {
334*e8d8bef9SDimitry Andric   return new DwarfEHPrepareLegacyPass(OptLevel);
3350b57cec5SDimitry Andric }
336