LCOV - code coverage report
Current view: top level - lib/Analysis - EHPersonalities.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 49 61 80.3 %
Date: 2017-09-14 15:23:50 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      695518 : EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
      23             :   const Function *F =
      24     1108989 :       Pers ? dyn_cast<Function>(Pers->stripPointerCasts()) : nullptr;
      25             :   if (!F)
      26             :     return EHPersonality::Unknown;
      27      413471 :   return StringSwitch<EHPersonality>(F->getName())
      28     1240413 :     .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
      29     1240413 :     .Case("__gxx_personality_v0",  EHPersonality::GNU_CXX)
      30     1240413 :     .Case("__gxx_personality_seh0",EHPersonality::GNU_CXX)
      31     1240413 :     .Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
      32     1240413 :     .Case("__gcc_personality_v0",  EHPersonality::GNU_C)
      33     1240413 :     .Case("__gcc_personality_seh0",EHPersonality::GNU_C)
      34     1240413 :     .Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
      35     1240413 :     .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
      36     1240413 :     .Case("_except_handler3",      EHPersonality::MSVC_X86SEH)
      37     1240413 :     .Case("_except_handler4",      EHPersonality::MSVC_X86SEH)
      38     1240413 :     .Case("__C_specific_handler",  EHPersonality::MSVC_Win64SEH)
      39     1240413 :     .Case("__CxxFrameHandler3",    EHPersonality::MSVC_CXX)
      40     1240413 :     .Case("ProcessCLRException",   EHPersonality::CoreCLR)
      41     1240413 :     .Case("rust_eh_personality",   EHPersonality::Rust)
      42      826942 :     .Default(EHPersonality::Unknown);
      43             : }
      44             : 
      45           4 : StringRef llvm::getEHPersonalityName(EHPersonality Pers) {
      46           4 :   switch (Pers) {
      47           0 :   case EHPersonality::GNU_Ada:       return "__gnat_eh_personality";
      48           0 :   case EHPersonality::GNU_CXX:       return "__gxx_personality_v0";
      49           0 :   case EHPersonality::GNU_CXX_SjLj:  return "__gxx_personality_sj0";
      50           4 :   case EHPersonality::GNU_C:         return "__gcc_personality_v0";
      51           0 :   case EHPersonality::GNU_C_SjLj:    return "__gcc_personality_sj0";
      52           0 :   case EHPersonality::GNU_ObjC:      return "__objc_personality_v0";
      53           0 :   case EHPersonality::MSVC_X86SEH:   return "_except_handler3";
      54           0 :   case EHPersonality::MSVC_Win64SEH: return "__C_specific_handler";
      55           0 :   case EHPersonality::MSVC_CXX:      return "__CxxFrameHandler3";
      56           0 :   case EHPersonality::CoreCLR:       return "ProcessCLRException";
      57           0 :   case EHPersonality::Rust:          return "rust_eh_personality";
      58           0 :   case EHPersonality::Unknown:       llvm_unreachable("Unknown EHPersonality!");
      59             :   }
      60             : 
      61           0 :   llvm_unreachable("Invalid EHPersonality!");
      62             : }
      63             : 
      64           4 : EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {
      65           4 :   return EHPersonality::GNU_C;
      66             : }
      67             : 
      68        6682 : bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
      69        6682 :   EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
      70             :   // We can't simplify any invokes to nounwind functions if the personality
      71             :   // function wants to catch asynch exceptions.  The nounwind attribute only
      72             :   // implies that the function does not throw synchronous exceptions.
      73        6682 :   return !isAsynchronousEHPersonality(Personality);
      74             : }
      75             : 
      76         278 : DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
      77         556 :   SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
      78         278 :   BasicBlock *EntryBlock = &F.getEntryBlock();
      79         278 :   DenseMap<BasicBlock *, ColorVector> BlockColors;
      80             : 
      81             :   // Build up the color map, which maps each block to its set of 'colors'.
      82             :   // For any block B the "colors" of B are the set of funclets F (possibly
      83             :   // including a root "funclet" representing the main function) such that
      84             :   // F will need to directly contain B or a copy of B (where the term "directly
      85             :   // contain" is used to distinguish from being "transitively contained" in
      86             :   // a nested funclet).
      87             :   //
      88             :   // Note: Despite not being a funclet in the truest sense, a catchswitch is
      89             :   // considered to belong to its own funclet for the purposes of coloring.
      90             : 
      91             :   DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
      92             :                                                   << F.getName() << "\n");
      93             : 
      94         278 :   Worklist.push_back({EntryBlock, EntryBlock});
      95             : 
      96        2363 :   while (!Worklist.empty()) {
      97             :     BasicBlock *Visiting;
      98             :     BasicBlock *Color;
      99        6255 :     std::tie(Visiting, Color) = Worklist.pop_back_val();
     100             :     DEBUG_WITH_TYPE("winehprepare-coloring",
     101             :                     dbgs() << "Visiting " << Visiting->getName() << ", "
     102             :                            << Color->getName() << "\n");
     103        4170 :     Instruction *VisitingHead = Visiting->getFirstNonPHI();
     104         875 :     if (VisitingHead->isEHPad()) {
     105             :       // Mark this funclet head as a member of itself.
     106         875 :       Color = Visiting;
     107             :     }
     108             :     // Note that this is a member of the given color.
     109        2085 :     ColorVector &Colors = BlockColors[Visiting];
     110        2504 :     if (!is_contained(Colors, Color))
     111        1666 :       Colors.push_back(Color);
     112             :     else
     113         419 :       continue;
     114             : 
     115             :     DEBUG_WITH_TYPE("winehprepare-coloring",
     116             :                     dbgs() << "  Assigned color \'" << Color->getName()
     117             :                            << "\' to block \'" << Visiting->getName()
     118             :                            << "\'.\n");
     119             : 
     120        1666 :     BasicBlock *SuccColor = Color;
     121        3332 :     TerminatorInst *Terminator = Visiting->getTerminator();
     122         274 :     if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
     123         274 :       Value *ParentPad = CatchRet->getCatchSwitchParentPad();
     124         548 :       if (isa<ConstantTokenNone>(ParentPad))
     125             :         SuccColor = EntryBlock;
     126             :       else
     127          40 :         SuccColor = cast<Instruction>(ParentPad)->getParent();
     128             :     }
     129             : 
     130        6946 :     for (BasicBlock *Succ : successors(Visiting))
     131        1807 :       Worklist.push_back({Succ, SuccColor});
     132             :   }
     133         278 :   return BlockColors;
     134             : }

Generated by: LCOV version 1.13