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