LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyExceptionInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 63 87 72.4 %
Date: 2018-10-20 13:21:21 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===//
       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             : /// \file
      11             : /// \brief This file implements WebAssemblyException information analysis.
      12             : ///
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "WebAssemblyExceptionInfo.h"
      16             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      17             : #include "WebAssemblyUtilities.h"
      18             : #include "llvm/ADT/PostOrderIterator.h"
      19             : #include "llvm/CodeGen/MachineDominanceFrontier.h"
      20             : #include "llvm/CodeGen/MachineDominators.h"
      21             : 
      22             : using namespace llvm;
      23             : 
      24             : #define DEBUG_TYPE "wasm-exception-info"
      25             : 
      26             : char WebAssemblyExceptionInfo::ID = 0;
      27             : 
      28       85108 : INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE,
      29             :                       "WebAssembly Exception Information", true, true)
      30       85108 : INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
      31       85108 : INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
      32      199339 : INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE,
      33             :                     "WebAssembly Exception Information", true, true)
      34             : 
      35        2987 : bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &F) {
      36        2987 :   releaseMemory();
      37        2987 :   auto &MDT = getAnalysis<MachineDominatorTree>();
      38        2987 :   auto &MDF = getAnalysis<MachineDominanceFrontier>();
      39        2987 :   recalculate(MDT, MDF);
      40        2987 :   return false;
      41             : }
      42             : 
      43        2990 : void WebAssemblyExceptionInfo::recalculate(
      44             :     MachineDominatorTree &MDT, const MachineDominanceFrontier &MDF) {
      45             :   // Postorder traversal of the dominator tree.
      46             :   SmallVector<WebAssemblyException *, 8> Exceptions;
      47        9576 :   for (auto DomNode : post_order(&MDT)) {
      48        3596 :     MachineBasicBlock *EHPad = DomNode->getBlock();
      49        3596 :     if (!EHPad->isEHPad())
      50        3562 :       continue;
      51             :     // We group catch & catch-all terminate pads together, so skip the second
      52             :     // one
      53          37 :     if (WebAssembly::isCatchAllTerminatePad(*EHPad))
      54             :       continue;
      55          34 :     auto *WE = new WebAssemblyException(EHPad);
      56          34 :     discoverAndMapException(WE, MDT, MDF);
      57          34 :     Exceptions.push_back(WE);
      58             :   }
      59             : 
      60             :   // Add BBs to exceptions
      61        9576 :   for (auto DomNode : post_order(&MDT)) {
      62        3596 :     MachineBasicBlock *MBB = DomNode->getBlock();
      63             :     WebAssemblyException *WE = getExceptionFor(MBB);
      64        3716 :     for (; WE; WE = WE->getParentException())
      65         120 :       WE->addBlock(MBB);
      66             :   }
      67             : 
      68             :   // Add subexceptions to exceptions
      69        3024 :   for (auto *WE : Exceptions) {
      70          34 :     if (WE->getParentException())
      71          16 :       WE->getParentException()->getSubExceptions().push_back(WE);
      72             :     else
      73          18 :       addTopLevelException(WE);
      74             :   }
      75             : 
      76             :   // For convenience, Blocks and SubExceptions are inserted in postorder.
      77             :   // Reverse the lists.
      78        3024 :   for (auto *WE : Exceptions) {
      79             :     WE->reverseBlock();
      80             :     std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end());
      81             :   }
      82        2990 : }
      83             : 
      84        6278 : void WebAssemblyExceptionInfo::releaseMemory() {
      85        6278 :   BBMap.clear();
      86        6278 :   DeleteContainerPointers(TopLevelExceptions);
      87             :   TopLevelExceptions.clear();
      88        6278 : }
      89             : 
      90         306 : void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const {
      91             :   AU.setPreservesAll();
      92             :   AU.addRequired<MachineDominatorTree>();
      93             :   AU.addRequired<MachineDominanceFrontier>();
      94         306 :   MachineFunctionPass::getAnalysisUsage(AU);
      95         306 : }
      96             : 
      97          34 : void WebAssemblyExceptionInfo::discoverAndMapException(
      98             :     WebAssemblyException *WE, const MachineDominatorTree &MDT,
      99             :     const MachineDominanceFrontier &MDF) {
     100             :   unsigned NumBlocks = 0;
     101             :   unsigned NumSubExceptions = 0;
     102             : 
     103             :   // Map blocks that belong to a catchpad / cleanuppad
     104          34 :   MachineBasicBlock *EHPad = WE->getEHPad();
     105             : 
     106             :   // We group catch & catch-all terminate pads together within an exception
     107          34 :   if (WebAssembly::isCatchTerminatePad(*EHPad)) {
     108             :     assert(EHPad->succ_size() == 1 &&
     109             :            "Catch terminate pad has more than one successors");
     110           3 :     changeExceptionFor(EHPad, WE);
     111           6 :     changeExceptionFor(*(EHPad->succ_begin()), WE);
     112           3 :     return;
     113             :   }
     114             : 
     115             :   SmallVector<MachineBasicBlock *, 8> WL;
     116          31 :   WL.push_back(EHPad);
     117         131 :   while (!WL.empty()) {
     118             :     MachineBasicBlock *MBB = WL.pop_back_val();
     119             : 
     120             :     // Find its outermost discovered exception. If this is a discovered block,
     121             :     // check if it is already discovered to be a subexception of this exception.
     122         100 :     WebAssemblyException *SubE = getOutermostException(MBB);
     123         100 :     if (SubE) {
     124          26 :       if (SubE != WE) {
     125             :         // Discover a subexception of this exception.
     126             :         SubE->setParentException(WE);
     127          16 :         ++NumSubExceptions;
     128          16 :         NumBlocks += SubE->getBlocksVector().capacity();
     129             :         // All blocks that belong to this subexception have been already
     130             :         // discovered. Skip all of them. Add the subexception's landing pad's
     131             :         // dominance frontier to the worklist.
     132          43 :         for (auto &Frontier : MDF.find(SubE->getEHPad())->second)
     133          22 :           if (MDT.dominates(EHPad, Frontier))
     134           7 :             WL.push_back(Frontier);
     135             :       }
     136          26 :       continue;
     137             :     }
     138             : 
     139             :     // This is an undiscovered block. Map it to the current exception.
     140          74 :     changeExceptionFor(MBB, WE);
     141          74 :     ++NumBlocks;
     142             : 
     143             :     // Add successors dominated by the current BB to the worklist.
     144         166 :     for (auto *Succ : MBB->successors())
     145         184 :       if (MDT.dominates(EHPad, Succ))
     146          62 :         WL.push_back(Succ);
     147             :   }
     148             : 
     149          31 :   WE->getSubExceptions().reserve(NumSubExceptions);
     150             :   WE->reserveBlocks(NumBlocks);
     151             : }
     152             : 
     153             : WebAssemblyException *
     154         100 : WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const {
     155             :   WebAssemblyException *WE = getExceptionFor(MBB);
     156          26 :   if (WE) {
     157          30 :     while (WebAssemblyException *Parent = WE->getParentException())
     158             :       WE = Parent;
     159             :   }
     160         100 :   return WE;
     161             : }
     162             : 
     163           0 : void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const {
     164           0 :   OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth()
     165           0 :                        << " containing: ";
     166             : 
     167           0 :   for (unsigned I = 0; I < getBlocks().size(); ++I) {
     168           0 :     MachineBasicBlock *MBB = getBlocks()[I];
     169           0 :     if (I)
     170           0 :       OS << ", ";
     171           0 :     OS << "%bb." << MBB->getNumber();
     172           0 :     if (const auto *BB = MBB->getBasicBlock())
     173           0 :       if (BB->hasName())
     174           0 :         OS << "." << BB->getName();
     175             : 
     176           0 :     if (getEHPad() == MBB)
     177           0 :       OS << " (landing-pad)";
     178             :   }
     179           0 :   OS << "\n";
     180             : 
     181           0 :   for (auto &SubE : SubExceptions)
     182           0 :     SubE->print(OS, Depth + 2);
     183           0 : }
     184             : 
     185             : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     186             : LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); }
     187             : #endif
     188             : 
     189           0 : raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) {
     190           0 :   WE.print(OS);
     191           0 :   return OS;
     192             : }
     193             : 
     194           0 : void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const {
     195           0 :   for (auto *WE : TopLevelExceptions)
     196           0 :     WE->print(OS);
     197           0 : }

Generated by: LCOV version 1.13