104c48949SHeejin Ahn //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===//
204c48949SHeejin Ahn //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604c48949SHeejin Ahn //
704c48949SHeejin Ahn //===----------------------------------------------------------------------===//
804c48949SHeejin Ahn ///
904c48949SHeejin Ahn /// \file
1004c48949SHeejin Ahn /// \brief This file implements WebAssemblyException information analysis.
1104c48949SHeejin Ahn ///
1204c48949SHeejin Ahn //===----------------------------------------------------------------------===//
1304c48949SHeejin Ahn 
1404c48949SHeejin Ahn #include "WebAssemblyExceptionInfo.h"
1504c48949SHeejin Ahn #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
160b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h"
17*989f1c72Sserge-sans-paille #include "llvm/ADT/DepthFirstIterator.h"
1804c48949SHeejin Ahn #include "llvm/ADT/PostOrderIterator.h"
1904c48949SHeejin Ahn #include "llvm/CodeGen/MachineDominanceFrontier.h"
2004c48949SHeejin Ahn #include "llvm/CodeGen/MachineDominators.h"
21ea8c6375SHeejin Ahn #include "llvm/CodeGen/WasmEHFuncInfo.h"
2205da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
234a58116bSHeejin Ahn #include "llvm/MC/MCAsmInfo.h"
244a58116bSHeejin Ahn #include "llvm/Target/TargetMachine.h"
2504c48949SHeejin Ahn 
2604c48949SHeejin Ahn using namespace llvm;
2704c48949SHeejin Ahn 
2804c48949SHeejin Ahn #define DEBUG_TYPE "wasm-exception-info"
2904c48949SHeejin Ahn 
3004c48949SHeejin Ahn char WebAssemblyExceptionInfo::ID = 0;
3104c48949SHeejin Ahn 
3204c48949SHeejin Ahn INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE,
3304c48949SHeejin Ahn                       "WebAssembly Exception Information", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)3404c48949SHeejin Ahn INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
3504c48949SHeejin Ahn INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
3604c48949SHeejin Ahn INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE,
3704c48949SHeejin Ahn                     "WebAssembly Exception Information", true, true)
3804c48949SHeejin Ahn 
39569f0909SHeejin Ahn bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &MF) {
40569f0909SHeejin Ahn   LLVM_DEBUG(dbgs() << "********** Exception Info Calculation **********\n"
41569f0909SHeejin Ahn                        "********** Function: "
42569f0909SHeejin Ahn                     << MF.getName() << '\n');
4304c48949SHeejin Ahn   releaseMemory();
444a58116bSHeejin Ahn   if (MF.getTarget().getMCAsmInfo()->getExceptionHandlingType() !=
454a58116bSHeejin Ahn           ExceptionHandling::Wasm ||
464a58116bSHeejin Ahn       !MF.getFunction().hasPersonalityFn())
474a58116bSHeejin Ahn     return false;
4804c48949SHeejin Ahn   auto &MDT = getAnalysis<MachineDominatorTree>();
4904c48949SHeejin Ahn   auto &MDF = getAnalysis<MachineDominanceFrontier>();
50ea8c6375SHeejin Ahn   recalculate(MF, MDT, MDF);
514a58116bSHeejin Ahn   LLVM_DEBUG(dump());
524a58116bSHeejin Ahn   return false;
534a58116bSHeejin Ahn }
544a58116bSHeejin Ahn 
554a58116bSHeejin Ahn // Check if Dst is reachable from Src using BFS. Search only within BBs
564a58116bSHeejin Ahn // dominated by Header.
isReachableAmongDominated(const MachineBasicBlock * Src,const MachineBasicBlock * Dst,const MachineBasicBlock * Header,const MachineDominatorTree & MDT)574a58116bSHeejin Ahn static bool isReachableAmongDominated(const MachineBasicBlock *Src,
584a58116bSHeejin Ahn                                       const MachineBasicBlock *Dst,
594a58116bSHeejin Ahn                                       const MachineBasicBlock *Header,
604a58116bSHeejin Ahn                                       const MachineDominatorTree &MDT) {
614a58116bSHeejin Ahn   assert(MDT.dominates(Header, Dst));
624a58116bSHeejin Ahn   SmallVector<const MachineBasicBlock *, 8> WL;
634a58116bSHeejin Ahn   SmallPtrSet<const MachineBasicBlock *, 8> Visited;
644a58116bSHeejin Ahn   WL.push_back(Src);
654a58116bSHeejin Ahn 
664a58116bSHeejin Ahn   while (!WL.empty()) {
674a58116bSHeejin Ahn     const auto *MBB = WL.pop_back_val();
684a58116bSHeejin Ahn     if (MBB == Dst)
694a58116bSHeejin Ahn       return true;
704a58116bSHeejin Ahn     Visited.insert(MBB);
714a58116bSHeejin Ahn     for (auto *Succ : MBB->successors())
724a58116bSHeejin Ahn       if (!Visited.count(Succ) && MDT.dominates(Header, Succ))
734a58116bSHeejin Ahn         WL.push_back(Succ);
744a58116bSHeejin Ahn   }
7504c48949SHeejin Ahn   return false;
7604c48949SHeejin Ahn }
7704c48949SHeejin Ahn 
recalculate(MachineFunction & MF,MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)7804c48949SHeejin Ahn void WebAssemblyExceptionInfo::recalculate(
79ea8c6375SHeejin Ahn     MachineFunction &MF, MachineDominatorTree &MDT,
80ea8c6375SHeejin Ahn     const MachineDominanceFrontier &MDF) {
8104c48949SHeejin Ahn   // Postorder traversal of the dominator tree.
82f6d5320eSDavid Blaikie   SmallVector<std::unique_ptr<WebAssemblyException>, 8> Exceptions;
8304c48949SHeejin Ahn   for (auto DomNode : post_order(&MDT)) {
8404c48949SHeejin Ahn     MachineBasicBlock *EHPad = DomNode->getBlock();
8504c48949SHeejin Ahn     if (!EHPad->isEHPad())
8604c48949SHeejin Ahn       continue;
87f6d5320eSDavid Blaikie     auto WE = std::make_unique<WebAssemblyException>(EHPad);
88f6d5320eSDavid Blaikie     discoverAndMapException(WE.get(), MDT, MDF);
89f6d5320eSDavid Blaikie     Exceptions.push_back(std::move(WE));
9004c48949SHeejin Ahn   }
9104c48949SHeejin Ahn 
92ea8c6375SHeejin Ahn   // WasmEHFuncInfo contains a map of <catchpad, its next unwind destination>,
93ea8c6375SHeejin Ahn   // which means, if an exception is not caught by the catchpad, it should end
94ea8c6375SHeejin Ahn   // up in the next unwind destination stored in this data structure. (It is
95ea8c6375SHeejin Ahn   // written as catchswitch's 'unwind' destination in ll files.) The below is an
96ea8c6375SHeejin Ahn   // intuitive example of their relationship in C++ code:
97ea8c6375SHeejin Ahn   // try {
98ea8c6375SHeejin Ahn   //   try {
99ea8c6375SHeejin Ahn   //   } catch (int) { // catchpad
100ea8c6375SHeejin Ahn   //      ...          // this catch (int) { ... } is grouped as an exception
101ea8c6375SHeejin Ahn   //   }
102ea8c6375SHeejin Ahn   // } catch (...) {   // next unwind destination
103ea8c6375SHeejin Ahn   // }
104ea8c6375SHeejin Ahn   // (The example is try-catches for illustration purpose, but the unwind
105ea8c6375SHeejin Ahn   // destination can be also a cleanuppad generated by destructor calls.) So the
106ea8c6375SHeejin Ahn   // unwind destination is in the outside of the catchpad's exception.
107ea8c6375SHeejin Ahn   //
108ea8c6375SHeejin Ahn   // We group exceptions in this analysis simply by including all BBs dominated
109ea8c6375SHeejin Ahn   // by an EH pad. But in case the EH pad's unwind destination does not have any
110ea8c6375SHeejin Ahn   // children outside of the exception, that unwind destination ends up also
111ea8c6375SHeejin Ahn   // being dominated by the EH pad and included in the exception, which is not
112ea8c6375SHeejin Ahn   // semantically correct, because it unwinds/rethrows into an inner scope.
113ea8c6375SHeejin Ahn   //
114ea8c6375SHeejin Ahn   // Here we extract those unwind destinations from their (incorrect) parent
115ea8c6375SHeejin Ahn   // exception. Note that the unwind destinations may not be an immediate
116ea8c6375SHeejin Ahn   // children of the parent exception, so we have to traverse the parent chain.
1174a58116bSHeejin Ahn   //
1184a58116bSHeejin Ahn   // We should traverse BBs in the preorder of the dominator tree, because
1194a58116bSHeejin Ahn   // otherwise the result can be incorrect. For example, when there are three
1204a58116bSHeejin Ahn   // exceptions A, B, and C and A > B > C (> is subexception relationship here),
1214a58116bSHeejin Ahn   // and A's unwind destination is B and B's is C. When we visit B before A, we
1224a58116bSHeejin Ahn   // end up extracting C only out of B but not out of A.
123ea8c6375SHeejin Ahn   const auto *EHInfo = MF.getWasmEHFuncInfo();
1242b957ed4SHeejin Ahn   SmallVector<std::pair<WebAssemblyException *, WebAssemblyException *>>
1252b957ed4SHeejin Ahn       UnwindWEVec;
1264a58116bSHeejin Ahn   for (auto *DomNode : depth_first(&MDT)) {
1274a58116bSHeejin Ahn     MachineBasicBlock *EHPad = DomNode->getBlock();
1284a58116bSHeejin Ahn     if (!EHPad->isEHPad())
129ea8c6375SHeejin Ahn       continue;
130ea8c6375SHeejin Ahn     if (!EHInfo->hasUnwindDest(EHPad))
131ea8c6375SHeejin Ahn       continue;
132ea8c6375SHeejin Ahn     auto *UnwindDest = EHInfo->getUnwindDest(EHPad);
1332b957ed4SHeejin Ahn     auto *SrcWE = getExceptionFor(EHPad);
1342b957ed4SHeejin Ahn     auto *DstWE = getExceptionFor(UnwindDest);
1352b957ed4SHeejin Ahn     if (SrcWE->contains(DstWE)) {
1362b957ed4SHeejin Ahn       UnwindWEVec.push_back(std::make_pair(SrcWE, DstWE));
1372b957ed4SHeejin Ahn       LLVM_DEBUG(dbgs() << "Unwind destination ExceptionInfo fix:\n  "
1382b957ed4SHeejin Ahn                         << DstWE->getEHPad()->getNumber() << "."
1392b957ed4SHeejin Ahn                         << DstWE->getEHPad()->getName()
1404a58116bSHeejin Ahn                         << "'s exception is taken out of "
1412b957ed4SHeejin Ahn                         << SrcWE->getEHPad()->getNumber() << "."
1422b957ed4SHeejin Ahn                         << SrcWE->getEHPad()->getName() << "'s exception\n");
1432b957ed4SHeejin Ahn       DstWE->setParentException(SrcWE->getParentException());
144ea8c6375SHeejin Ahn     }
145ea8c6375SHeejin Ahn   }
146ea8c6375SHeejin Ahn 
1474a58116bSHeejin Ahn   // After fixing subexception relationship between unwind destinations above,
1484a58116bSHeejin Ahn   // there can still be remaining discrepancies.
1494a58116bSHeejin Ahn   //
1504a58116bSHeejin Ahn   // For example, suppose Exception A is dominated by EHPad A and Exception B is
1514a58116bSHeejin Ahn   // dominated by EHPad B. EHPad A's unwind destination is EHPad B, but because
1524a58116bSHeejin Ahn   // EHPad B is dominated by EHPad A, the initial grouping makes Exception B a
1534a58116bSHeejin Ahn   // subexception of Exception A, and we fix it by taking Exception B out of
1544a58116bSHeejin Ahn   // Exception A above. But there can still be remaining BBs within Exception A
1554a58116bSHeejin Ahn   // that are reachable from Exception B. These BBs semantically don't belong
1562b957ed4SHeejin Ahn   // to Exception A and were not a part of this 'catch' clause or cleanup code
1572b957ed4SHeejin Ahn   // in the original code, but they just happened to be grouped within Exception
1582b957ed4SHeejin Ahn   // A because they were dominated by EHPad A. We fix this case by taking those
1594a58116bSHeejin Ahn   // BBs out of the incorrect exception and all its subexceptions that it
1604a58116bSHeejin Ahn   // belongs to.
1612b957ed4SHeejin Ahn   //
1622b957ed4SHeejin Ahn   // 1. First, we take out remaining incorrect subexceptions. This part is
1632b957ed4SHeejin Ahn   // easier, because we haven't added BBs to exceptions yet, we only need to
1642b957ed4SHeejin Ahn   // change parent exception pointer.
1652b957ed4SHeejin Ahn   for (auto *DomNode : depth_first(&MDT)) {
1662b957ed4SHeejin Ahn     MachineBasicBlock *EHPad = DomNode->getBlock();
1672b957ed4SHeejin Ahn     if (!EHPad->isEHPad())
1682b957ed4SHeejin Ahn       continue;
1692b957ed4SHeejin Ahn     auto *WE = getExceptionFor(EHPad);
1704a58116bSHeejin Ahn 
1712b957ed4SHeejin Ahn     // For each source EHPad -> unwind destination EHPad
1722b957ed4SHeejin Ahn     for (auto &P : UnwindWEVec) {
1732b957ed4SHeejin Ahn       auto *SrcWE = P.first;
1742b957ed4SHeejin Ahn       auto *DstWE = P.second;
1752b957ed4SHeejin Ahn       // If WE (the current EH pad's exception) is still contained in SrcWE but
1762b957ed4SHeejin Ahn       // reachable from DstWE that was taken out of SrcWE above, we have to take
1772b957ed4SHeejin Ahn       // out WE out of SrcWE too.
1782b957ed4SHeejin Ahn       if (WE != SrcWE && SrcWE->contains(WE) && !DstWE->contains(WE) &&
1792b957ed4SHeejin Ahn           isReachableAmongDominated(DstWE->getEHPad(), EHPad, SrcWE->getEHPad(),
1802b957ed4SHeejin Ahn                                     MDT)) {
1812b957ed4SHeejin Ahn         LLVM_DEBUG(dbgs() << "Remaining reachable ExceptionInfo fix:\n  "
1822b957ed4SHeejin Ahn                           << WE->getEHPad()->getNumber() << "."
1832b957ed4SHeejin Ahn                           << WE->getEHPad()->getName()
1842b957ed4SHeejin Ahn                           << "'s exception is taken out of "
1852b957ed4SHeejin Ahn                           << SrcWE->getEHPad()->getNumber() << "."
1862b957ed4SHeejin Ahn                           << SrcWE->getEHPad()->getName() << "'s exception\n");
1872b957ed4SHeejin Ahn         WE->setParentException(SrcWE->getParentException());
1882b957ed4SHeejin Ahn       }
1892b957ed4SHeejin Ahn     }
1902b957ed4SHeejin Ahn   }
1912b957ed4SHeejin Ahn 
1922b957ed4SHeejin Ahn   // Add BBs to exceptions' block set. This is a preparation to take out
1932b957ed4SHeejin Ahn   // remaining incorect BBs from exceptions, because we need to iterate over BBs
1942b957ed4SHeejin Ahn   // for each exception.
1952b957ed4SHeejin Ahn   for (auto *DomNode : post_order(&MDT)) {
1962b957ed4SHeejin Ahn     MachineBasicBlock *MBB = DomNode->getBlock();
1972b957ed4SHeejin Ahn     WebAssemblyException *WE = getExceptionFor(MBB);
1982b957ed4SHeejin Ahn     for (; WE; WE = WE->getParentException())
1992b957ed4SHeejin Ahn       WE->addToBlocksSet(MBB);
2002b957ed4SHeejin Ahn   }
2012b957ed4SHeejin Ahn 
2022b957ed4SHeejin Ahn   // 2. We take out remaining individual BBs out. Now we have added BBs to each
2032b957ed4SHeejin Ahn   // exceptions' BlockSet, when we take a BB out of an exception, we need to fix
2042b957ed4SHeejin Ahn   // those sets too.
2052b957ed4SHeejin Ahn   for (auto &P : UnwindWEVec) {
2062b957ed4SHeejin Ahn     auto *SrcWE = P.first;
2072b957ed4SHeejin Ahn     auto *DstWE = P.second;
2082b957ed4SHeejin Ahn 
2092b957ed4SHeejin Ahn     for (auto *MBB : SrcWE->getBlocksSet()) {
2104a58116bSHeejin Ahn       if (MBB->isEHPad()) {
2112b957ed4SHeejin Ahn         assert(!isReachableAmongDominated(DstWE->getEHPad(), MBB,
2122b957ed4SHeejin Ahn                                           SrcWE->getEHPad(), MDT) &&
2132b957ed4SHeejin Ahn                "We already handled EH pads above");
2144a58116bSHeejin Ahn         continue;
2154a58116bSHeejin Ahn       }
2162b957ed4SHeejin Ahn       if (isReachableAmongDominated(DstWE->getEHPad(), MBB, SrcWE->getEHPad(),
2174a58116bSHeejin Ahn                                     MDT)) {
2184a58116bSHeejin Ahn         LLVM_DEBUG(dbgs() << "Remainder BB: " << MBB->getNumber() << "."
2192b957ed4SHeejin Ahn                           << MBB->getName() << " is\n");
2204a58116bSHeejin Ahn         WebAssemblyException *InnerWE = getExceptionFor(MBB);
2212b957ed4SHeejin Ahn         while (InnerWE != SrcWE) {
2224a58116bSHeejin Ahn           LLVM_DEBUG(dbgs()
2234a58116bSHeejin Ahn                      << "  removed from " << InnerWE->getEHPad()->getNumber()
2244a58116bSHeejin Ahn                      << "." << InnerWE->getEHPad()->getName()
2254a58116bSHeejin Ahn                      << "'s exception\n");
2264a58116bSHeejin Ahn           InnerWE->removeFromBlocksSet(MBB);
2274a58116bSHeejin Ahn           InnerWE = InnerWE->getParentException();
2284a58116bSHeejin Ahn         }
2292b957ed4SHeejin Ahn         SrcWE->removeFromBlocksSet(MBB);
2302b957ed4SHeejin Ahn         LLVM_DEBUG(dbgs() << "  removed from " << SrcWE->getEHPad()->getNumber()
2312b957ed4SHeejin Ahn                           << "." << SrcWE->getEHPad()->getName()
2324a58116bSHeejin Ahn                           << "'s exception\n");
2332b957ed4SHeejin Ahn         changeExceptionFor(MBB, SrcWE->getParentException());
2342b957ed4SHeejin Ahn         if (SrcWE->getParentException())
2352b957ed4SHeejin Ahn           SrcWE->getParentException()->addToBlocksSet(MBB);
2364a58116bSHeejin Ahn       }
2374a58116bSHeejin Ahn     }
2384a58116bSHeejin Ahn   }
2394a58116bSHeejin Ahn 
2404a58116bSHeejin Ahn   // Add BBs to exceptions' block vector
24104c48949SHeejin Ahn   for (auto DomNode : post_order(&MDT)) {
24204c48949SHeejin Ahn     MachineBasicBlock *MBB = DomNode->getBlock();
24304c48949SHeejin Ahn     WebAssemblyException *WE = getExceptionFor(MBB);
24404c48949SHeejin Ahn     for (; WE; WE = WE->getParentException())
2454a58116bSHeejin Ahn       WE->addToBlocksVector(MBB);
24604c48949SHeejin Ahn   }
24704c48949SHeejin Ahn 
248f6d5320eSDavid Blaikie   SmallVector<WebAssemblyException*, 8> ExceptionPointers;
249f6d5320eSDavid Blaikie   ExceptionPointers.reserve(Exceptions.size());
250f6d5320eSDavid Blaikie 
25104c48949SHeejin Ahn   // Add subexceptions to exceptions
252f6d5320eSDavid Blaikie   for (auto &WE : Exceptions) {
253f6d5320eSDavid Blaikie     ExceptionPointers.push_back(WE.get());
25404c48949SHeejin Ahn     if (WE->getParentException())
255f6d5320eSDavid Blaikie       WE->getParentException()->getSubExceptions().push_back(std::move(WE));
25604c48949SHeejin Ahn     else
257f6d5320eSDavid Blaikie       addTopLevelException(std::move(WE));
25804c48949SHeejin Ahn   }
25904c48949SHeejin Ahn 
26004c48949SHeejin Ahn   // For convenience, Blocks and SubExceptions are inserted in postorder.
26104c48949SHeejin Ahn   // Reverse the lists.
262f6d5320eSDavid Blaikie   for (auto *WE : ExceptionPointers) {
26304c48949SHeejin Ahn     WE->reverseBlock();
26404c48949SHeejin Ahn     std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end());
26504c48949SHeejin Ahn   }
26604c48949SHeejin Ahn }
26704c48949SHeejin Ahn 
releaseMemory()26804c48949SHeejin Ahn void WebAssemblyExceptionInfo::releaseMemory() {
26904c48949SHeejin Ahn   BBMap.clear();
27004c48949SHeejin Ahn   TopLevelExceptions.clear();
27104c48949SHeejin Ahn }
27204c48949SHeejin Ahn 
getAnalysisUsage(AnalysisUsage & AU) const27304c48949SHeejin Ahn void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const {
27404c48949SHeejin Ahn   AU.setPreservesAll();
27504c48949SHeejin Ahn   AU.addRequired<MachineDominatorTree>();
27604c48949SHeejin Ahn   AU.addRequired<MachineDominanceFrontier>();
27704c48949SHeejin Ahn   MachineFunctionPass::getAnalysisUsage(AU);
27804c48949SHeejin Ahn }
27904c48949SHeejin Ahn 
discoverAndMapException(WebAssemblyException * WE,const MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)28004c48949SHeejin Ahn void WebAssemblyExceptionInfo::discoverAndMapException(
28104c48949SHeejin Ahn     WebAssemblyException *WE, const MachineDominatorTree &MDT,
28204c48949SHeejin Ahn     const MachineDominanceFrontier &MDF) {
28304c48949SHeejin Ahn   unsigned NumBlocks = 0;
28404c48949SHeejin Ahn   unsigned NumSubExceptions = 0;
28504c48949SHeejin Ahn 
28604c48949SHeejin Ahn   // Map blocks that belong to a catchpad / cleanuppad
28704c48949SHeejin Ahn   MachineBasicBlock *EHPad = WE->getEHPad();
28804c48949SHeejin Ahn   SmallVector<MachineBasicBlock *, 8> WL;
28904c48949SHeejin Ahn   WL.push_back(EHPad);
29004c48949SHeejin Ahn   while (!WL.empty()) {
29104c48949SHeejin Ahn     MachineBasicBlock *MBB = WL.pop_back_val();
29204c48949SHeejin Ahn 
29304c48949SHeejin Ahn     // Find its outermost discovered exception. If this is a discovered block,
29404c48949SHeejin Ahn     // check if it is already discovered to be a subexception of this exception.
29504c48949SHeejin Ahn     WebAssemblyException *SubE = getOutermostException(MBB);
29604c48949SHeejin Ahn     if (SubE) {
29704c48949SHeejin Ahn       if (SubE != WE) {
29804c48949SHeejin Ahn         // Discover a subexception of this exception.
29904c48949SHeejin Ahn         SubE->setParentException(WE);
30004c48949SHeejin Ahn         ++NumSubExceptions;
30104c48949SHeejin Ahn         NumBlocks += SubE->getBlocksVector().capacity();
30204c48949SHeejin Ahn         // All blocks that belong to this subexception have been already
30304c48949SHeejin Ahn         // discovered. Skip all of them. Add the subexception's landing pad's
30404c48949SHeejin Ahn         // dominance frontier to the worklist.
30504c48949SHeejin Ahn         for (auto &Frontier : MDF.find(SubE->getEHPad())->second)
30604c48949SHeejin Ahn           if (MDT.dominates(EHPad, Frontier))
30704c48949SHeejin Ahn             WL.push_back(Frontier);
30804c48949SHeejin Ahn       }
30904c48949SHeejin Ahn       continue;
31004c48949SHeejin Ahn     }
31104c48949SHeejin Ahn 
31204c48949SHeejin Ahn     // This is an undiscovered block. Map it to the current exception.
31304c48949SHeejin Ahn     changeExceptionFor(MBB, WE);
31404c48949SHeejin Ahn     ++NumBlocks;
31504c48949SHeejin Ahn 
31604c48949SHeejin Ahn     // Add successors dominated by the current BB to the worklist.
31704c48949SHeejin Ahn     for (auto *Succ : MBB->successors())
31804c48949SHeejin Ahn       if (MDT.dominates(EHPad, Succ))
31904c48949SHeejin Ahn         WL.push_back(Succ);
32004c48949SHeejin Ahn   }
32104c48949SHeejin Ahn 
32204c48949SHeejin Ahn   WE->getSubExceptions().reserve(NumSubExceptions);
32304c48949SHeejin Ahn   WE->reserveBlocks(NumBlocks);
32404c48949SHeejin Ahn }
32504c48949SHeejin Ahn 
32604c48949SHeejin Ahn WebAssemblyException *
getOutermostException(MachineBasicBlock * MBB) const32704c48949SHeejin Ahn WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const {
32804c48949SHeejin Ahn   WebAssemblyException *WE = getExceptionFor(MBB);
32904c48949SHeejin Ahn   if (WE) {
33004c48949SHeejin Ahn     while (WebAssemblyException *Parent = WE->getParentException())
33104c48949SHeejin Ahn       WE = Parent;
33204c48949SHeejin Ahn   }
33304c48949SHeejin Ahn   return WE;
33404c48949SHeejin Ahn }
33504c48949SHeejin Ahn 
print(raw_ostream & OS,unsigned Depth) const33604c48949SHeejin Ahn void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const {
33704c48949SHeejin Ahn   OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth()
33804c48949SHeejin Ahn                        << " containing: ";
33904c48949SHeejin Ahn 
34004c48949SHeejin Ahn   for (unsigned I = 0; I < getBlocks().size(); ++I) {
34104c48949SHeejin Ahn     MachineBasicBlock *MBB = getBlocks()[I];
34204c48949SHeejin Ahn     if (I)
34304c48949SHeejin Ahn       OS << ", ";
34404c48949SHeejin Ahn     OS << "%bb." << MBB->getNumber();
34504c48949SHeejin Ahn     if (const auto *BB = MBB->getBasicBlock())
34604c48949SHeejin Ahn       if (BB->hasName())
34704c48949SHeejin Ahn         OS << "." << BB->getName();
34804c48949SHeejin Ahn 
34904c48949SHeejin Ahn     if (getEHPad() == MBB)
35004c48949SHeejin Ahn       OS << " (landing-pad)";
35104c48949SHeejin Ahn   }
35204c48949SHeejin Ahn   OS << "\n";
35304c48949SHeejin Ahn 
35404c48949SHeejin Ahn   for (auto &SubE : SubExceptions)
35504c48949SHeejin Ahn     SubE->print(OS, Depth + 2);
35604c48949SHeejin Ahn }
35704c48949SHeejin Ahn 
35804c48949SHeejin Ahn #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const35904c48949SHeejin Ahn LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); }
36004c48949SHeejin Ahn #endif
36104c48949SHeejin Ahn 
operator <<(raw_ostream & OS,const WebAssemblyException & WE)36204c48949SHeejin Ahn raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) {
36304c48949SHeejin Ahn   WE.print(OS);
36404c48949SHeejin Ahn   return OS;
36504c48949SHeejin Ahn }
36604c48949SHeejin Ahn 
print(raw_ostream & OS,const Module *) const36704c48949SHeejin Ahn void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const {
368f6d5320eSDavid Blaikie   for (auto &WE : TopLevelExceptions)
36904c48949SHeejin Ahn     WE->print(OS);
37004c48949SHeejin Ahn }
371