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