LCOV - code coverage report
Current view: top level - lib/Analysis - EHPersonalities.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 25 38 65.8 %
Date: 2018-07-13 00:08:38 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- EHPersonalities.cpp - Compute EH-related information ---------------===//
       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             : #include "llvm/Analysis/EHPersonalities.h"
      11             : #include "llvm/ADT/StringSwitch.h"
      12             : #include "llvm/IR/CFG.h"
      13             : #include "llvm/IR/Constants.h"
      14             : #include "llvm/IR/Function.h"
      15             : #include "llvm/IR/Instructions.h"
      16             : #include "llvm/Support/Debug.h"
      17             : #include "llvm/Support/raw_ostream.h"
      18             : using namespace llvm;
      19             : 
      20             : /// See if the given exception handling personality function is one that we
      21             : /// understand.  If so, return a description of it; otherwise return Unknown.
      22     1181752 : EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
      23             :   const Function *F =
      24     1181752 :       Pers ? dyn_cast<Function>(Pers->stripPointerCasts()) : nullptr;
      25             :   if (!F)
      26             :     return EHPersonality::Unknown;
      27     1055652 :   return StringSwitch<EHPersonality>(F->getName())
      28             :     .Case("__gnat_eh_personality",     EHPersonality::GNU_Ada)
      29             :     .Case("__gxx_personality_v0",      EHPersonality::GNU_CXX)
      30             :     .Case("__gxx_personality_seh0",    EHPersonality::GNU_CXX)
      31             :     .Case("__gxx_personality_sj0",     EHPersonality::GNU_CXX_SjLj)
      32             :     .Case("__gcc_personality_v0",      EHPersonality::GNU_C)
      33             :     .Case("__gcc_personality_seh0",    EHPersonality::GNU_C)
      34             :     .Case("__gcc_personality_sj0",     EHPersonality::GNU_C_SjLj)
      35             :     .Case("__objc_personality_v0",     EHPersonality::GNU_ObjC)
      36             :     .Case("_except_handler3",          EHPersonality::MSVC_X86SEH)
      37             :     .Case("_except_handler4",          EHPersonality::MSVC_X86SEH)
      38             :     .Case("__C_specific_handler",      EHPersonality::MSVC_Win64SEH)
      39             :     .Case("__CxxFrameHandler3",        EHPersonality::MSVC_CXX)
      40             :     .Case("ProcessCLRException",       EHPersonality::CoreCLR)
      41             :     .Case("rust_eh_personality",       EHPersonality::Rust)
      42             :     .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)
      43             :     .Default(EHPersonality::Unknown);
      44             : }
      45             : 
      46           4 : StringRef llvm::getEHPersonalityName(EHPersonality Pers) {
      47           4 :   switch (Pers) {
      48           0 :   case EHPersonality::GNU_Ada:       return "__gnat_eh_personality";
      49           0 :   case EHPersonality::GNU_CXX:       return "__gxx_personality_v0";
      50           0 :   case EHPersonality::GNU_CXX_SjLj:  return "__gxx_personality_sj0";
      51           4 :   case EHPersonality::GNU_C:         return "__gcc_personality_v0";
      52           0 :   case EHPersonality::GNU_C_SjLj:    return "__gcc_personality_sj0";
      53           0 :   case EHPersonality::GNU_ObjC:      return "__objc_personality_v0";
      54           0 :   case EHPersonality::MSVC_X86SEH:   return "_except_handler3";
      55           0 :   case EHPersonality::MSVC_Win64SEH: return "__C_specific_handler";
      56           0 :   case EHPersonality::MSVC_CXX:      return "__CxxFrameHandler3";
      57           0 :   case EHPersonality::CoreCLR:       return "ProcessCLRException";
      58           0 :   case EHPersonality::Rust:          return "rust_eh_personality";
      59           0 :   case EHPersonality::Wasm_CXX:      return "__gxx_wasm_personality_v0";
      60           0 :   case EHPersonality::Unknown:       llvm_unreachable("Unknown EHPersonality!");
      61             :   }
      62             : 
      63           0 :   llvm_unreachable("Invalid EHPersonality!");
      64             : }
      65             : 
      66           4 : EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {
      67           4 :   return EHPersonality::GNU_C;
      68             : }
      69             : 
      70        7231 : bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
      71        7231 :   EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
      72             :   // We can't simplify any invokes to nounwind functions if the personality
      73             :   // function wants to catch asynch exceptions.  The nounwind attribute only
      74             :   // implies that the function does not throw synchronous exceptions.
      75        7231 :   return !isAsynchronousEHPersonality(Personality);
      76             : }
      77             : 
      78         312 : DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
      79             :   SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
      80             :   BasicBlock *EntryBlock = &F.getEntryBlock();
      81             :   DenseMap<BasicBlock *, ColorVector> BlockColors;
      82             : 
      83             :   // Build up the color map, which maps each block to its set of 'colors'.
      84             :   // For any block B the "colors" of B are the set of funclets F (possibly
      85             :   // including a root "funclet" representing the main function) such that
      86             :   // F will need to directly contain B or a copy of B (where the term "directly
      87             :   // contain" is used to distinguish from being "transitively contained" in
      88             :   // a nested funclet).
      89             :   //
      90             :   // Note: Despite not being a funclet in the truest sense, a catchswitch is
      91             :   // considered to belong to its own funclet for the purposes of coloring.
      92             : 
      93             :   DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
      94             :                                                   << F.getName() << "\n");
      95             : 
      96         312 :   Worklist.push_back({EntryBlock, EntryBlock});
      97             : 
      98        2643 :   while (!Worklist.empty()) {
      99             :     BasicBlock *Visiting;
     100             :     BasicBlock *Color;
     101             :     std::tie(Visiting, Color) = Worklist.pop_back_val();
     102             :     DEBUG_WITH_TYPE("winehprepare-coloring",
     103             :                     dbgs() << "Visiting " << Visiting->getName() << ", "
     104             :                            << Color->getName() << "\n");
     105             :     Instruction *VisitingHead = Visiting->getFirstNonPHI();
     106             :     if (VisitingHead->isEHPad()) {
     107             :       // Mark this funclet head as a member of itself.
     108         959 :       Color = Visiting;
     109             :     }
     110             :     // Note that this is a member of the given color.
     111             :     ColorVector &Colors = BlockColors[Visiting];
     112        2794 :     if (!is_contained(Colors, Color))
     113        1868 :       Colors.push_back(Color);
     114             :     else
     115         463 :       continue;
     116             : 
     117             :     DEBUG_WITH_TYPE("winehprepare-coloring",
     118             :                     dbgs() << "  Assigned color \'" << Color->getName()
     119             :                            << "\' to block \'" << Visiting->getName()
     120             :                            << "\'.\n");
     121             : 
     122        1868 :     BasicBlock *SuccColor = Color;
     123        1868 :     TerminatorInst *Terminator = Visiting->getTerminator();
     124             :     if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
     125             :       Value *ParentPad = CatchRet->getCatchSwitchParentPad();
     126         293 :       if (isa<ConstantTokenNone>(ParentPad))
     127             :         SuccColor = EntryBlock;
     128             :       else
     129          21 :         SuccColor = cast<Instruction>(ParentPad)->getParent();
     130             :     }
     131             : 
     132        1868 :     for (BasicBlock *Succ : successors(Visiting))
     133        2019 :       Worklist.push_back({Succ, SuccColor});
     134             :   }
     135         312 :   return BlockColors;
     136             : }

Generated by: LCOV version 1.13