1 //===-- WebAssemblyExceptionInfo.h - WebAssembly Exception Info -*- C++ -*-===// 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 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H 16 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H 17 18 #include "WebAssembly.h" 19 #include "llvm/ADT/SetVector.h" 20 #include "llvm/CodeGen/MachineFunctionPass.h" 21 22 namespace llvm { 23 24 class MachineDominatorTree; 25 class MachineDominanceFrontier; 26 27 // WebAssembly instructions for exception handling are structured as follows: 28 // try 29 // instructions* 30 // catch ----| 31 // instructions* | -> A WebAssemblyException consists of this region 32 // end ----| 33 // 34 // A WebAssemblyException object contains BBs that belong to a 'catch' part of 35 // the try-catch-end structure to be created later. 'try' and 'end' markers 36 // are not present at this stage and will be generated in CFGStackify pass. 37 // Because CFGSort requires all the BBs within a catch part to be sorted 38 // together as it does for loops, this pass calculates the nesting structure of 39 // catch part of exceptions in a function. 40 // 41 // An exception catch part is defined as a BB with catch instruction and all 42 // other BBs dominated by this BB. 43 class WebAssemblyException { 44 MachineBasicBlock *EHPad = nullptr; 45 46 WebAssemblyException *ParentException = nullptr; 47 std::vector<WebAssemblyException *> SubExceptions; 48 std::vector<MachineBasicBlock *> Blocks; 49 SmallPtrSet<const MachineBasicBlock *, 8> BlockSet; 50 51 public: WebAssemblyException(MachineBasicBlock * EHPad)52 WebAssemblyException(MachineBasicBlock *EHPad) : EHPad(EHPad) {} ~WebAssemblyException()53 ~WebAssemblyException() { DeleteContainerPointers(SubExceptions); } 54 WebAssemblyException(const WebAssemblyException &) = delete; 55 const WebAssemblyException &operator=(const WebAssemblyException &) = delete; 56 getEHPad()57 MachineBasicBlock *getEHPad() const { return EHPad; } getHeader()58 MachineBasicBlock *getHeader() const { return EHPad; } getParentException()59 WebAssemblyException *getParentException() const { return ParentException; } setParentException(WebAssemblyException * WE)60 void setParentException(WebAssemblyException *WE) { ParentException = WE; } 61 contains(const WebAssemblyException * WE)62 bool contains(const WebAssemblyException *WE) const { 63 if (WE == this) 64 return true; 65 if (!WE) 66 return false; 67 return contains(WE->getParentException()); 68 } contains(const MachineBasicBlock * MBB)69 bool contains(const MachineBasicBlock *MBB) const { 70 return BlockSet.count(MBB); 71 } 72 addBlock(MachineBasicBlock * MBB)73 void addBlock(MachineBasicBlock *MBB) { 74 Blocks.push_back(MBB); 75 BlockSet.insert(MBB); 76 } getBlocks()77 ArrayRef<MachineBasicBlock *> getBlocks() const { return Blocks; } 78 using block_iterator = typename ArrayRef<MachineBasicBlock *>::const_iterator; block_begin()79 block_iterator block_begin() const { return getBlocks().begin(); } block_end()80 block_iterator block_end() const { return getBlocks().end(); } blocks()81 inline iterator_range<block_iterator> blocks() const { 82 return make_range(block_begin(), block_end()); 83 } getNumBlocks()84 unsigned getNumBlocks() const { return Blocks.size(); } getBlocksVector()85 std::vector<MachineBasicBlock *> &getBlocksVector() { return Blocks; } 86 getSubExceptions()87 const std::vector<WebAssemblyException *> &getSubExceptions() const { 88 return SubExceptions; 89 } getSubExceptions()90 std::vector<WebAssemblyException *> &getSubExceptions() { 91 return SubExceptions; 92 } addSubException(WebAssemblyException * E)93 void addSubException(WebAssemblyException *E) { SubExceptions.push_back(E); } 94 using iterator = typename std::vector<WebAssemblyException *>::const_iterator; begin()95 iterator begin() const { return SubExceptions.begin(); } end()96 iterator end() const { return SubExceptions.end(); } 97 reserveBlocks(unsigned Size)98 void reserveBlocks(unsigned Size) { Blocks.reserve(Size); } 99 void reverseBlock(unsigned From = 0) { 100 std::reverse(Blocks.begin() + From, Blocks.end()); 101 } 102 103 // Return the nesting level. An outermost one has depth 1. getExceptionDepth()104 unsigned getExceptionDepth() const { 105 unsigned D = 1; 106 for (const WebAssemblyException *CurException = ParentException; 107 CurException; CurException = CurException->ParentException) 108 ++D; 109 return D; 110 } 111 112 void print(raw_ostream &OS, unsigned Depth = 0) const; 113 void dump() const; 114 }; 115 116 raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE); 117 118 class WebAssemblyExceptionInfo final : public MachineFunctionPass { 119 // Mapping of basic blocks to the innermost exception they occur in 120 DenseMap<const MachineBasicBlock *, WebAssemblyException *> BBMap; 121 std::vector<WebAssemblyException *> TopLevelExceptions; 122 123 void discoverAndMapException(WebAssemblyException *WE, 124 const MachineDominatorTree &MDT, 125 const MachineDominanceFrontier &MDF); 126 WebAssemblyException *getOutermostException(MachineBasicBlock *MBB) const; 127 128 public: 129 static char ID; WebAssemblyExceptionInfo()130 WebAssemblyExceptionInfo() : MachineFunctionPass(ID) { 131 initializeWebAssemblyExceptionInfoPass(*PassRegistry::getPassRegistry()); 132 } ~WebAssemblyExceptionInfo()133 ~WebAssemblyExceptionInfo() override { releaseMemory(); } 134 WebAssemblyExceptionInfo(const WebAssemblyExceptionInfo &) = delete; 135 WebAssemblyExceptionInfo & 136 operator=(const WebAssemblyExceptionInfo &) = delete; 137 138 bool runOnMachineFunction(MachineFunction &) override; 139 void releaseMemory() override; 140 void recalculate(MachineDominatorTree &MDT, 141 const MachineDominanceFrontier &MDF); 142 void getAnalysisUsage(AnalysisUsage &AU) const override; 143 empty()144 bool empty() const { return TopLevelExceptions.empty(); } 145 146 // Return the innermost exception that MBB lives in. If the block is not in an 147 // exception, null is returned. getExceptionFor(const MachineBasicBlock * MBB)148 WebAssemblyException *getExceptionFor(const MachineBasicBlock *MBB) const { 149 return BBMap.lookup(MBB); 150 } 151 changeExceptionFor(MachineBasicBlock * MBB,WebAssemblyException * WE)152 void changeExceptionFor(MachineBasicBlock *MBB, WebAssemblyException *WE) { 153 if (!WE) { 154 BBMap.erase(MBB); 155 return; 156 } 157 BBMap[MBB] = WE; 158 } 159 addTopLevelException(WebAssemblyException * WE)160 void addTopLevelException(WebAssemblyException *WE) { 161 assert(!WE->getParentException() && "Not a top level exception!"); 162 TopLevelExceptions.push_back(WE); 163 } 164 165 void print(raw_ostream &OS, const Module *M = nullptr) const override; 166 }; 167 168 } // end namespace llvm 169 170 #endif 171