10b57cec5SDimitry Andric //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// \brief This file implements WebAssemblyException information analysis. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "WebAssemblyExceptionInfo.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 16*fe6060f1SDimitry Andric #include "Utils/WebAssemblyUtilities.h" 170b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominanceFrontier.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 20*fe6060f1SDimitry Andric #include "llvm/CodeGen/WasmEHFuncInfo.h" 21480093f4SDimitry Andric #include "llvm/InitializePasses.h" 22*fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 23*fe6060f1SDimitry Andric #include "llvm/Target/TargetMachine.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-exception-info" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric char WebAssemblyExceptionInfo::ID = 0; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE, 320b57cec5SDimitry Andric "WebAssembly Exception Information", true, true) 330b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 340b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier) 350b57cec5SDimitry Andric INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE, 360b57cec5SDimitry Andric "WebAssembly Exception Information", true, true) 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &MF) { 390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Exception Info Calculation **********\n" 400b57cec5SDimitry Andric "********** Function: " 410b57cec5SDimitry Andric << MF.getName() << '\n'); 420b57cec5SDimitry Andric releaseMemory(); 43*fe6060f1SDimitry Andric if (MF.getTarget().getMCAsmInfo()->getExceptionHandlingType() != 44*fe6060f1SDimitry Andric ExceptionHandling::Wasm || 45*fe6060f1SDimitry Andric !MF.getFunction().hasPersonalityFn()) 46*fe6060f1SDimitry Andric return false; 470b57cec5SDimitry Andric auto &MDT = getAnalysis<MachineDominatorTree>(); 480b57cec5SDimitry Andric auto &MDF = getAnalysis<MachineDominanceFrontier>(); 49*fe6060f1SDimitry Andric recalculate(MF, MDT, MDF); 50*fe6060f1SDimitry Andric LLVM_DEBUG(dump()); 51*fe6060f1SDimitry Andric return false; 52*fe6060f1SDimitry Andric } 53*fe6060f1SDimitry Andric 54*fe6060f1SDimitry Andric // Check if Dst is reachable from Src using BFS. Search only within BBs 55*fe6060f1SDimitry Andric // dominated by Header. 56*fe6060f1SDimitry Andric static bool isReachableAmongDominated(const MachineBasicBlock *Src, 57*fe6060f1SDimitry Andric const MachineBasicBlock *Dst, 58*fe6060f1SDimitry Andric const MachineBasicBlock *Header, 59*fe6060f1SDimitry Andric const MachineDominatorTree &MDT) { 60*fe6060f1SDimitry Andric assert(MDT.dominates(Header, Dst)); 61*fe6060f1SDimitry Andric SmallVector<const MachineBasicBlock *, 8> WL; 62*fe6060f1SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 8> Visited; 63*fe6060f1SDimitry Andric WL.push_back(Src); 64*fe6060f1SDimitry Andric 65*fe6060f1SDimitry Andric while (!WL.empty()) { 66*fe6060f1SDimitry Andric const auto *MBB = WL.pop_back_val(); 67*fe6060f1SDimitry Andric if (MBB == Dst) 68*fe6060f1SDimitry Andric return true; 69*fe6060f1SDimitry Andric Visited.insert(MBB); 70*fe6060f1SDimitry Andric for (auto *Succ : MBB->successors()) 71*fe6060f1SDimitry Andric if (!Visited.count(Succ) && MDT.dominates(Header, Succ)) 72*fe6060f1SDimitry Andric WL.push_back(Succ); 73*fe6060f1SDimitry Andric } 740b57cec5SDimitry Andric return false; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric void WebAssemblyExceptionInfo::recalculate( 78*fe6060f1SDimitry Andric MachineFunction &MF, MachineDominatorTree &MDT, 79*fe6060f1SDimitry Andric const MachineDominanceFrontier &MDF) { 800b57cec5SDimitry Andric // Postorder traversal of the dominator tree. 815ffd83dbSDimitry Andric SmallVector<std::unique_ptr<WebAssemblyException>, 8> Exceptions; 820b57cec5SDimitry Andric for (auto DomNode : post_order(&MDT)) { 830b57cec5SDimitry Andric MachineBasicBlock *EHPad = DomNode->getBlock(); 840b57cec5SDimitry Andric if (!EHPad->isEHPad()) 850b57cec5SDimitry Andric continue; 865ffd83dbSDimitry Andric auto WE = std::make_unique<WebAssemblyException>(EHPad); 875ffd83dbSDimitry Andric discoverAndMapException(WE.get(), MDT, MDF); 885ffd83dbSDimitry Andric Exceptions.push_back(std::move(WE)); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 91*fe6060f1SDimitry Andric // WasmEHFuncInfo contains a map of <catchpad, its next unwind destination>, 92*fe6060f1SDimitry Andric // which means, if an exception is not caught by the catchpad, it should end 93*fe6060f1SDimitry Andric // up in the next unwind destination stored in this data structure. (It is 94*fe6060f1SDimitry Andric // written as catchswitch's 'unwind' destination in ll files.) The below is an 95*fe6060f1SDimitry Andric // intuitive example of their relationship in C++ code: 96*fe6060f1SDimitry Andric // try { 97*fe6060f1SDimitry Andric // try { 98*fe6060f1SDimitry Andric // } catch (int) { // catchpad 99*fe6060f1SDimitry Andric // ... // this catch (int) { ... } is grouped as an exception 100*fe6060f1SDimitry Andric // } 101*fe6060f1SDimitry Andric // } catch (...) { // next unwind destination 102*fe6060f1SDimitry Andric // } 103*fe6060f1SDimitry Andric // (The example is try-catches for illustration purpose, but the unwind 104*fe6060f1SDimitry Andric // destination can be also a cleanuppad generated by destructor calls.) So the 105*fe6060f1SDimitry Andric // unwind destination is in the outside of the catchpad's exception. 106*fe6060f1SDimitry Andric // 107*fe6060f1SDimitry Andric // We group exceptions in this analysis simply by including all BBs dominated 108*fe6060f1SDimitry Andric // by an EH pad. But in case the EH pad's unwind destination does not have any 109*fe6060f1SDimitry Andric // children outside of the exception, that unwind destination ends up also 110*fe6060f1SDimitry Andric // being dominated by the EH pad and included in the exception, which is not 111*fe6060f1SDimitry Andric // semantically correct, because it unwinds/rethrows into an inner scope. 112*fe6060f1SDimitry Andric // 113*fe6060f1SDimitry Andric // Here we extract those unwind destinations from their (incorrect) parent 114*fe6060f1SDimitry Andric // exception. Note that the unwind destinations may not be an immediate 115*fe6060f1SDimitry Andric // children of the parent exception, so we have to traverse the parent chain. 116*fe6060f1SDimitry Andric // 117*fe6060f1SDimitry Andric // We should traverse BBs in the preorder of the dominator tree, because 118*fe6060f1SDimitry Andric // otherwise the result can be incorrect. For example, when there are three 119*fe6060f1SDimitry Andric // exceptions A, B, and C and A > B > C (> is subexception relationship here), 120*fe6060f1SDimitry Andric // and A's unwind destination is B and B's is C. When we visit B before A, we 121*fe6060f1SDimitry Andric // end up extracting C only out of B but not out of A. 122*fe6060f1SDimitry Andric const auto *EHInfo = MF.getWasmEHFuncInfo(); 123*fe6060f1SDimitry Andric SmallVector<std::pair<WebAssemblyException *, WebAssemblyException *>> 124*fe6060f1SDimitry Andric UnwindWEVec; 125*fe6060f1SDimitry Andric for (auto *DomNode : depth_first(&MDT)) { 126*fe6060f1SDimitry Andric MachineBasicBlock *EHPad = DomNode->getBlock(); 127*fe6060f1SDimitry Andric if (!EHPad->isEHPad()) 128*fe6060f1SDimitry Andric continue; 129*fe6060f1SDimitry Andric if (!EHInfo->hasUnwindDest(EHPad)) 130*fe6060f1SDimitry Andric continue; 131*fe6060f1SDimitry Andric auto *UnwindDest = EHInfo->getUnwindDest(EHPad); 132*fe6060f1SDimitry Andric auto *SrcWE = getExceptionFor(EHPad); 133*fe6060f1SDimitry Andric auto *DstWE = getExceptionFor(UnwindDest); 134*fe6060f1SDimitry Andric if (SrcWE->contains(DstWE)) { 135*fe6060f1SDimitry Andric UnwindWEVec.push_back(std::make_pair(SrcWE, DstWE)); 136*fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Unwind destination ExceptionInfo fix:\n " 137*fe6060f1SDimitry Andric << DstWE->getEHPad()->getNumber() << "." 138*fe6060f1SDimitry Andric << DstWE->getEHPad()->getName() 139*fe6060f1SDimitry Andric << "'s exception is taken out of " 140*fe6060f1SDimitry Andric << SrcWE->getEHPad()->getNumber() << "." 141*fe6060f1SDimitry Andric << SrcWE->getEHPad()->getName() << "'s exception\n"); 142*fe6060f1SDimitry Andric DstWE->setParentException(SrcWE->getParentException()); 143*fe6060f1SDimitry Andric } 144*fe6060f1SDimitry Andric } 145*fe6060f1SDimitry Andric 146*fe6060f1SDimitry Andric // After fixing subexception relationship between unwind destinations above, 147*fe6060f1SDimitry Andric // there can still be remaining discrepancies. 148*fe6060f1SDimitry Andric // 149*fe6060f1SDimitry Andric // For example, suppose Exception A is dominated by EHPad A and Exception B is 150*fe6060f1SDimitry Andric // dominated by EHPad B. EHPad A's unwind destination is EHPad B, but because 151*fe6060f1SDimitry Andric // EHPad B is dominated by EHPad A, the initial grouping makes Exception B a 152*fe6060f1SDimitry Andric // subexception of Exception A, and we fix it by taking Exception B out of 153*fe6060f1SDimitry Andric // Exception A above. But there can still be remaining BBs within Exception A 154*fe6060f1SDimitry Andric // that are reachable from Exception B. These BBs semantically don't belong 155*fe6060f1SDimitry Andric // to Exception A and were not a part of this 'catch' clause or cleanup code 156*fe6060f1SDimitry Andric // in the original code, but they just happened to be grouped within Exception 157*fe6060f1SDimitry Andric // A because they were dominated by EHPad A. We fix this case by taking those 158*fe6060f1SDimitry Andric // BBs out of the incorrect exception and all its subexceptions that it 159*fe6060f1SDimitry Andric // belongs to. 160*fe6060f1SDimitry Andric // 161*fe6060f1SDimitry Andric // 1. First, we take out remaining incorrect subexceptions. This part is 162*fe6060f1SDimitry Andric // easier, because we haven't added BBs to exceptions yet, we only need to 163*fe6060f1SDimitry Andric // change parent exception pointer. 164*fe6060f1SDimitry Andric for (auto *DomNode : depth_first(&MDT)) { 165*fe6060f1SDimitry Andric MachineBasicBlock *EHPad = DomNode->getBlock(); 166*fe6060f1SDimitry Andric if (!EHPad->isEHPad()) 167*fe6060f1SDimitry Andric continue; 168*fe6060f1SDimitry Andric auto *WE = getExceptionFor(EHPad); 169*fe6060f1SDimitry Andric 170*fe6060f1SDimitry Andric // For each source EHPad -> unwind destination EHPad 171*fe6060f1SDimitry Andric for (auto &P : UnwindWEVec) { 172*fe6060f1SDimitry Andric auto *SrcWE = P.first; 173*fe6060f1SDimitry Andric auto *DstWE = P.second; 174*fe6060f1SDimitry Andric // If WE (the current EH pad's exception) is still contained in SrcWE but 175*fe6060f1SDimitry Andric // reachable from DstWE that was taken out of SrcWE above, we have to take 176*fe6060f1SDimitry Andric // out WE out of SrcWE too. 177*fe6060f1SDimitry Andric if (WE != SrcWE && SrcWE->contains(WE) && !DstWE->contains(WE) && 178*fe6060f1SDimitry Andric isReachableAmongDominated(DstWE->getEHPad(), EHPad, SrcWE->getEHPad(), 179*fe6060f1SDimitry Andric MDT)) { 180*fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Remaining reachable ExceptionInfo fix:\n " 181*fe6060f1SDimitry Andric << WE->getEHPad()->getNumber() << "." 182*fe6060f1SDimitry Andric << WE->getEHPad()->getName() 183*fe6060f1SDimitry Andric << "'s exception is taken out of " 184*fe6060f1SDimitry Andric << SrcWE->getEHPad()->getNumber() << "." 185*fe6060f1SDimitry Andric << SrcWE->getEHPad()->getName() << "'s exception\n"); 186*fe6060f1SDimitry Andric WE->setParentException(SrcWE->getParentException()); 187*fe6060f1SDimitry Andric } 188*fe6060f1SDimitry Andric } 189*fe6060f1SDimitry Andric } 190*fe6060f1SDimitry Andric 191*fe6060f1SDimitry Andric // Add BBs to exceptions' block set. This is a preparation to take out 192*fe6060f1SDimitry Andric // remaining incorect BBs from exceptions, because we need to iterate over BBs 193*fe6060f1SDimitry Andric // for each exception. 194*fe6060f1SDimitry Andric for (auto *DomNode : post_order(&MDT)) { 195*fe6060f1SDimitry Andric MachineBasicBlock *MBB = DomNode->getBlock(); 196*fe6060f1SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 197*fe6060f1SDimitry Andric for (; WE; WE = WE->getParentException()) 198*fe6060f1SDimitry Andric WE->addToBlocksSet(MBB); 199*fe6060f1SDimitry Andric } 200*fe6060f1SDimitry Andric 201*fe6060f1SDimitry Andric // 2. We take out remaining individual BBs out. Now we have added BBs to each 202*fe6060f1SDimitry Andric // exceptions' BlockSet, when we take a BB out of an exception, we need to fix 203*fe6060f1SDimitry Andric // those sets too. 204*fe6060f1SDimitry Andric for (auto &P : UnwindWEVec) { 205*fe6060f1SDimitry Andric auto *SrcWE = P.first; 206*fe6060f1SDimitry Andric auto *DstWE = P.second; 207*fe6060f1SDimitry Andric 208*fe6060f1SDimitry Andric for (auto *MBB : SrcWE->getBlocksSet()) { 209*fe6060f1SDimitry Andric if (MBB->isEHPad()) { 210*fe6060f1SDimitry Andric assert(!isReachableAmongDominated(DstWE->getEHPad(), MBB, 211*fe6060f1SDimitry Andric SrcWE->getEHPad(), MDT) && 212*fe6060f1SDimitry Andric "We already handled EH pads above"); 213*fe6060f1SDimitry Andric continue; 214*fe6060f1SDimitry Andric } 215*fe6060f1SDimitry Andric if (isReachableAmongDominated(DstWE->getEHPad(), MBB, SrcWE->getEHPad(), 216*fe6060f1SDimitry Andric MDT)) { 217*fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Remainder BB: " << MBB->getNumber() << "." 218*fe6060f1SDimitry Andric << MBB->getName() << " is\n"); 219*fe6060f1SDimitry Andric WebAssemblyException *InnerWE = getExceptionFor(MBB); 220*fe6060f1SDimitry Andric while (InnerWE != SrcWE) { 221*fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() 222*fe6060f1SDimitry Andric << " removed from " << InnerWE->getEHPad()->getNumber() 223*fe6060f1SDimitry Andric << "." << InnerWE->getEHPad()->getName() 224*fe6060f1SDimitry Andric << "'s exception\n"); 225*fe6060f1SDimitry Andric InnerWE->removeFromBlocksSet(MBB); 226*fe6060f1SDimitry Andric InnerWE = InnerWE->getParentException(); 227*fe6060f1SDimitry Andric } 228*fe6060f1SDimitry Andric SrcWE->removeFromBlocksSet(MBB); 229*fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << " removed from " << SrcWE->getEHPad()->getNumber() 230*fe6060f1SDimitry Andric << "." << SrcWE->getEHPad()->getName() 231*fe6060f1SDimitry Andric << "'s exception\n"); 232*fe6060f1SDimitry Andric changeExceptionFor(MBB, SrcWE->getParentException()); 233*fe6060f1SDimitry Andric if (SrcWE->getParentException()) 234*fe6060f1SDimitry Andric SrcWE->getParentException()->addToBlocksSet(MBB); 235*fe6060f1SDimitry Andric } 236*fe6060f1SDimitry Andric } 237*fe6060f1SDimitry Andric } 238*fe6060f1SDimitry Andric 239*fe6060f1SDimitry Andric // Add BBs to exceptions' block vector 2400b57cec5SDimitry Andric for (auto DomNode : post_order(&MDT)) { 2410b57cec5SDimitry Andric MachineBasicBlock *MBB = DomNode->getBlock(); 2420b57cec5SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 2430b57cec5SDimitry Andric for (; WE; WE = WE->getParentException()) 244*fe6060f1SDimitry Andric WE->addToBlocksVector(MBB); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2475ffd83dbSDimitry Andric SmallVector<WebAssemblyException*, 8> ExceptionPointers; 2485ffd83dbSDimitry Andric ExceptionPointers.reserve(Exceptions.size()); 2495ffd83dbSDimitry Andric 2500b57cec5SDimitry Andric // Add subexceptions to exceptions 2515ffd83dbSDimitry Andric for (auto &WE : Exceptions) { 2525ffd83dbSDimitry Andric ExceptionPointers.push_back(WE.get()); 2530b57cec5SDimitry Andric if (WE->getParentException()) 2545ffd83dbSDimitry Andric WE->getParentException()->getSubExceptions().push_back(std::move(WE)); 2550b57cec5SDimitry Andric else 2565ffd83dbSDimitry Andric addTopLevelException(std::move(WE)); 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // For convenience, Blocks and SubExceptions are inserted in postorder. 2600b57cec5SDimitry Andric // Reverse the lists. 2615ffd83dbSDimitry Andric for (auto *WE : ExceptionPointers) { 2620b57cec5SDimitry Andric WE->reverseBlock(); 2630b57cec5SDimitry Andric std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end()); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric void WebAssemblyExceptionInfo::releaseMemory() { 2680b57cec5SDimitry Andric BBMap.clear(); 2690b57cec5SDimitry Andric TopLevelExceptions.clear(); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const { 2730b57cec5SDimitry Andric AU.setPreservesAll(); 2740b57cec5SDimitry Andric AU.addRequired<MachineDominatorTree>(); 2750b57cec5SDimitry Andric AU.addRequired<MachineDominanceFrontier>(); 2760b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric void WebAssemblyExceptionInfo::discoverAndMapException( 2800b57cec5SDimitry Andric WebAssemblyException *WE, const MachineDominatorTree &MDT, 2810b57cec5SDimitry Andric const MachineDominanceFrontier &MDF) { 2820b57cec5SDimitry Andric unsigned NumBlocks = 0; 2830b57cec5SDimitry Andric unsigned NumSubExceptions = 0; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric // Map blocks that belong to a catchpad / cleanuppad 2860b57cec5SDimitry Andric MachineBasicBlock *EHPad = WE->getEHPad(); 2870b57cec5SDimitry Andric SmallVector<MachineBasicBlock *, 8> WL; 2880b57cec5SDimitry Andric WL.push_back(EHPad); 2890b57cec5SDimitry Andric while (!WL.empty()) { 2900b57cec5SDimitry Andric MachineBasicBlock *MBB = WL.pop_back_val(); 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // Find its outermost discovered exception. If this is a discovered block, 2930b57cec5SDimitry Andric // check if it is already discovered to be a subexception of this exception. 2940b57cec5SDimitry Andric WebAssemblyException *SubE = getOutermostException(MBB); 2950b57cec5SDimitry Andric if (SubE) { 2960b57cec5SDimitry Andric if (SubE != WE) { 2970b57cec5SDimitry Andric // Discover a subexception of this exception. 2980b57cec5SDimitry Andric SubE->setParentException(WE); 2990b57cec5SDimitry Andric ++NumSubExceptions; 3000b57cec5SDimitry Andric NumBlocks += SubE->getBlocksVector().capacity(); 3010b57cec5SDimitry Andric // All blocks that belong to this subexception have been already 3020b57cec5SDimitry Andric // discovered. Skip all of them. Add the subexception's landing pad's 3030b57cec5SDimitry Andric // dominance frontier to the worklist. 3040b57cec5SDimitry Andric for (auto &Frontier : MDF.find(SubE->getEHPad())->second) 3050b57cec5SDimitry Andric if (MDT.dominates(EHPad, Frontier)) 3060b57cec5SDimitry Andric WL.push_back(Frontier); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric continue; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // This is an undiscovered block. Map it to the current exception. 3120b57cec5SDimitry Andric changeExceptionFor(MBB, WE); 3130b57cec5SDimitry Andric ++NumBlocks; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric // Add successors dominated by the current BB to the worklist. 3160b57cec5SDimitry Andric for (auto *Succ : MBB->successors()) 3170b57cec5SDimitry Andric if (MDT.dominates(EHPad, Succ)) 3180b57cec5SDimitry Andric WL.push_back(Succ); 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric WE->getSubExceptions().reserve(NumSubExceptions); 3220b57cec5SDimitry Andric WE->reserveBlocks(NumBlocks); 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric WebAssemblyException * 3260b57cec5SDimitry Andric WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const { 3270b57cec5SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 3280b57cec5SDimitry Andric if (WE) { 3290b57cec5SDimitry Andric while (WebAssemblyException *Parent = WE->getParentException()) 3300b57cec5SDimitry Andric WE = Parent; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric return WE; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const { 3360b57cec5SDimitry Andric OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth() 3370b57cec5SDimitry Andric << " containing: "; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric for (unsigned I = 0; I < getBlocks().size(); ++I) { 3400b57cec5SDimitry Andric MachineBasicBlock *MBB = getBlocks()[I]; 3410b57cec5SDimitry Andric if (I) 3420b57cec5SDimitry Andric OS << ", "; 3430b57cec5SDimitry Andric OS << "%bb." << MBB->getNumber(); 3440b57cec5SDimitry Andric if (const auto *BB = MBB->getBasicBlock()) 3450b57cec5SDimitry Andric if (BB->hasName()) 3460b57cec5SDimitry Andric OS << "." << BB->getName(); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric if (getEHPad() == MBB) 3490b57cec5SDimitry Andric OS << " (landing-pad)"; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric OS << "\n"; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric for (auto &SubE : SubExceptions) 3540b57cec5SDimitry Andric SubE->print(OS, Depth + 2); 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 3580b57cec5SDimitry Andric LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); } 3590b57cec5SDimitry Andric #endif 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) { 3620b57cec5SDimitry Andric WE.print(OS); 3630b57cec5SDimitry Andric return OS; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const { 3675ffd83dbSDimitry Andric for (auto &WE : TopLevelExceptions) 3680b57cec5SDimitry Andric WE->print(OS); 3690b57cec5SDimitry Andric } 370