LCOV - code coverage report
Current view: top level - lib/CodeGen - DwarfEHPrepare.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 112 113 99.1 %
Date: 2017-09-14 15:23:50 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DwarfEHPrepare - Prepare exception handling for code generation ---===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This pass mulches exception handling code into a form adapted to code
      11             : // generation. Required if using dwarf exception handling.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/ADT/BitVector.h"
      16             : #include "llvm/ADT/Statistic.h"
      17             : #include "llvm/Analysis/CFG.h"
      18             : #include "llvm/Analysis/EHPersonalities.h"
      19             : #include "llvm/Analysis/TargetTransformInfo.h"
      20             : #include "llvm/CodeGen/Passes.h"
      21             : #include "llvm/CodeGen/TargetPassConfig.h"
      22             : #include "llvm/IR/Dominators.h"
      23             : #include "llvm/IR/Function.h"
      24             : #include "llvm/IR/Instructions.h"
      25             : #include "llvm/IR/Module.h"
      26             : #include "llvm/Pass.h"
      27             : #include "llvm/Target/TargetLowering.h"
      28             : #include "llvm/Target/TargetSubtargetInfo.h"
      29             : #include "llvm/Transforms/Utils/Local.h"
      30             : using namespace llvm;
      31             : 
      32             : #define DEBUG_TYPE "dwarfehprepare"
      33             : 
      34             : STATISTIC(NumResumesLowered, "Number of resume calls lowered");
      35             : 
      36             : namespace {
      37       29548 :   class DwarfEHPrepare : public FunctionPass {
      38             :     // RewindFunction - _Unwind_Resume or the target equivalent.
      39             :     Constant *RewindFunction;
      40             : 
      41             :     DominatorTree *DT;
      42             :     const TargetLowering *TLI;
      43             : 
      44             :     bool InsertUnwindResumeCalls(Function &Fn);
      45             :     Value *GetExceptionObject(ResumeInst *RI);
      46             :     size_t
      47             :     pruneUnreachableResumes(Function &Fn,
      48             :                             SmallVectorImpl<ResumeInst *> &Resumes,
      49             :                             SmallVectorImpl<LandingPadInst *> &CleanupLPads);
      50             : 
      51             :   public:
      52             :     static char ID; // Pass identification, replacement for typeid.
      53             : 
      54             :     DwarfEHPrepare()
      55       29724 :         : FunctionPass(ID), RewindFunction(nullptr), DT(nullptr), TLI(nullptr) {
      56             :     }
      57             : 
      58             :     bool runOnFunction(Function &Fn) override;
      59             : 
      60       14748 :     bool doFinalization(Module &M) override {
      61       14748 :       RewindFunction = nullptr;
      62       14748 :       return false;
      63             :     }
      64             : 
      65             :     void getAnalysisUsage(AnalysisUsage &AU) const override;
      66             : 
      67          17 :     StringRef getPassName() const override {
      68          17 :       return "Exception handling preparation";
      69             :     }
      70             :   };
      71             : } // end anonymous namespace
      72             : 
      73             : char DwarfEHPrepare::ID = 0;
      74       26583 : INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
      75             :                       "Prepare DWARF exceptions", false, false)
      76       26583 : INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
      77       26583 : INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
      78       26583 : INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
      79      191385 : INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
      80             :                     "Prepare DWARF exceptions", false, false)
      81             : 
      82       29720 : FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
      83             : 
      84       14832 : void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
      85       14832 :   AU.addRequired<TargetPassConfig>();
      86       14832 :   AU.addRequired<TargetTransformInfoWrapperPass>();
      87       14832 :   AU.addRequired<DominatorTreeWrapperPass>();
      88       14832 : }
      89             : 
      90             : /// GetExceptionObject - Return the exception object from the value passed into
      91             : /// the 'resume' instruction (typically an aggregate). Clean up any dead
      92             : /// instructions, including the 'resume' instruction.
      93        2393 : Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
      94        2393 :   Value *V = RI->getOperand(0);
      95        2393 :   Value *ExnObj = nullptr;
      96        1284 :   InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
      97        1284 :   LoadInst *SelLoad = nullptr;
      98        1284 :   InsertValueInst *ExcIVI = nullptr;
      99        1284 :   bool EraseIVIs = false;
     100             : 
     101             :   if (SelIVI) {
     102        2568 :     if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
     103        2568 :       ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
     104        3852 :       if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
     105        2568 :           ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
     106        1284 :         ExnObj = ExcIVI->getOperand(1);
     107        1284 :         SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
     108             :         EraseIVIs = true;
     109             :       }
     110             :     }
     111             :   }
     112             : 
     113        2393 :   if (!ExnObj)
     114        3327 :     ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
     115             : 
     116        2393 :   RI->eraseFromParent();
     117             : 
     118        2393 :   if (EraseIVIs) {
     119        2568 :     if (SelIVI->use_empty())
     120        1284 :       SelIVI->eraseFromParent();
     121        2568 :     if (ExcIVI->use_empty())
     122        1284 :       ExcIVI->eraseFromParent();
     123        1300 :     if (SelLoad && SelLoad->use_empty())
     124          16 :       SelLoad->eraseFromParent();
     125             :   }
     126             : 
     127        2393 :   return ExnObj;
     128             : }
     129             : 
     130             : /// Replace resumes that are not reachable from a cleanup landing pad with
     131             : /// unreachable and then simplify those blocks.
     132        2142 : size_t DwarfEHPrepare::pruneUnreachableResumes(
     133             :     Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
     134             :     SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
     135        6426 :   BitVector ResumeReachable(Resumes.size());
     136        2142 :   size_t ResumeIndex = 0;
     137        8841 :   for (auto *RI : Resumes) {
     138       13285 :     for (auto *LP : CleanupLPads) {
     139        8433 :       if (isPotentiallyReachable(LP, RI, DT)) {
     140        2393 :         ResumeReachable.set(ResumeIndex);
     141             :         break;
     142             :       }
     143             :     }
     144        2415 :     ++ResumeIndex;
     145             :   }
     146             : 
     147             :   // If everything is reachable, there is no change.
     148        2142 :   if (ResumeReachable.all())
     149        4240 :     return Resumes.size();
     150             : 
     151             :   const TargetTransformInfo &TTI =
     152          22 :       getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
     153          22 :   LLVMContext &Ctx = Fn.getContext();
     154             : 
     155             :   // Otherwise, insert unreachable instructions and call simplifycfg.
     156          22 :   size_t ResumesLeft = 0;
     157          66 :   for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
     158          44 :     ResumeInst *RI = Resumes[I];
     159          66 :     if (ResumeReachable[I]) {
     160           0 :       Resumes[ResumesLeft++] = RI;
     161             :     } else {
     162          22 :       BasicBlock *BB = RI->getParent();
     163          22 :       new UnreachableInst(Ctx, RI);
     164          22 :       RI->eraseFromParent();
     165          22 :       SimplifyCFG(BB, TTI, 1);
     166             :     }
     167             :   }
     168          22 :   Resumes.resize(ResumesLeft);
     169          22 :   return ResumesLeft;
     170             : }
     171             : 
     172             : /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
     173             : /// into calls to the appropriate _Unwind_Resume function.
     174      124367 : bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
     175      248734 :   SmallVector<ResumeInst*, 16> Resumes;
     176      248734 :   SmallVector<LandingPadInst*, 16> CleanupLPads;
     177      631734 :   for (BasicBlock &BB : Fn) {
     178      517266 :     if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
     179        2415 :       Resumes.push_back(RI);
     180      258633 :     if (auto *LP = BB.getLandingPadInst())
     181       43512 :       if (LP->isCleanup())
     182       15715 :         CleanupLPads.push_back(LP);
     183             :   }
     184             : 
     185      124367 :   if (Resumes.empty())
     186             :     return false;
     187             : 
     188             :   // Check the personality, don't do anything if it's funclet-based.
     189        2142 :   EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
     190        2142 :   if (isFuncletEHPersonality(Pers))
     191             :     return false;
     192             : 
     193        2142 :   LLVMContext &Ctx = Fn.getContext();
     194             : 
     195        2142 :   size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
     196        2142 :   if (ResumesLeft == 0)
     197             :     return true; // We pruned them all.
     198             : 
     199             :   // Find the rewind function if we didn't already.
     200        2120 :   if (!RewindFunction) {
     201         272 :     FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
     202         408 :                                           Type::getInt8PtrTy(Ctx), false);
     203         272 :     const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
     204         272 :     RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
     205             :   }
     206             : 
     207             :   // Create the basic block where the _Unwind_Resume call will live.
     208        2120 :   if (ResumesLeft == 1) {
     209             :     // Instead of creating a new BB and PHI node, just append the call to
     210             :     // _Unwind_Resume to the end of the single resume block.
     211        4104 :     ResumeInst *RI = Resumes.front();
     212        2052 :     BasicBlock *UnwindBB = RI->getParent();
     213        2052 :     Value *ExnObj = GetExceptionObject(RI);
     214             : 
     215             :     // Call the _Unwind_Resume function.
     216        4104 :     CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
     217        6156 :     CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
     218             : 
     219             :     // We never expect _Unwind_Resume to return.
     220        2052 :     new UnreachableInst(Ctx, UnwindBB);
     221             :     return true;
     222             :   }
     223             : 
     224         136 :   BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
     225         136 :   PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
     226          68 :                                 "exn.obj", UnwindBB);
     227             : 
     228             :   // Extract the exception object from the ResumeInst and add it to the PHI node
     229             :   // that feeds the _Unwind_Resume call.
     230         545 :   for (ResumeInst *RI : Resumes) {
     231         341 :     BasicBlock *Parent = RI->getParent();
     232         341 :     BranchInst::Create(UnwindBB, Parent);
     233             : 
     234         341 :     Value *ExnObj = GetExceptionObject(RI);
     235         341 :     PN->addIncoming(ExnObj, Parent);
     236             : 
     237         341 :     ++NumResumesLowered;
     238             :   }
     239             : 
     240             :   // Call the function.
     241         136 :   CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
     242         204 :   CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
     243             : 
     244             :   // We never expect _Unwind_Resume to return.
     245          68 :   new UnreachableInst(Ctx, UnwindBB);
     246          68 :   return true;
     247             : }
     248             : 
     249      124367 : bool DwarfEHPrepare::runOnFunction(Function &Fn) {
     250             :   const TargetMachine &TM =
     251      124367 :       getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
     252      248734 :   DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
     253      124367 :   TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
     254      124367 :   bool Changed = InsertUnwindResumeCalls(Fn);
     255      124367 :   DT = nullptr;
     256      124367 :   TLI = nullptr;
     257      124367 :   return Changed;
     258             : }

Generated by: LCOV version 1.13