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)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)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.
isReachableAmongDominated(const MachineBasicBlock * Src,const MachineBasicBlock * Dst,const MachineBasicBlock * Header,const MachineDominatorTree & MDT)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 
recalculate(MachineFunction & MF,MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)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 
releaseMemory()2710b57cec5SDimitry Andric void WebAssemblyExceptionInfo::releaseMemory() {
2720b57cec5SDimitry Andric   BBMap.clear();
2730b57cec5SDimitry Andric   TopLevelExceptions.clear();
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const2760b57cec5SDimitry 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 
discoverAndMapException(WebAssemblyException * WE,const MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)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 *
getOutermostException(MachineBasicBlock * MBB) const3300b57cec5SDimitry 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 
print(raw_ostream & OS,unsigned Depth) const3390b57cec5SDimitry 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)
dump() const3620b57cec5SDimitry Andric LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); }
3630b57cec5SDimitry Andric #endif
3640b57cec5SDimitry Andric 
operator <<(raw_ostream & OS,const WebAssemblyException & WE)3650b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) {
3660b57cec5SDimitry Andric   WE.print(OS);
3670b57cec5SDimitry Andric   return OS;
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
print(raw_ostream & OS,const Module *) const3700b57cec5SDimitry Andric void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const {
3715ffd83dbSDimitry Andric   for (auto &WE : TopLevelExceptions)
3720b57cec5SDimitry Andric     WE->print(OS);
3730b57cec5SDimitry Andric }
374