xref: /src/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1eb11fae6SDimitry Andric //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===//
2eb11fae6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eb11fae6SDimitry Andric //
7eb11fae6SDimitry Andric //===----------------------------------------------------------------------===//
8eb11fae6SDimitry Andric ///
9eb11fae6SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// \brief This file implements WebAssemblyException information analysis.
11eb11fae6SDimitry Andric ///
12eb11fae6SDimitry Andric //===----------------------------------------------------------------------===//
13eb11fae6SDimitry Andric 
14eb11fae6SDimitry Andric #include "WebAssemblyExceptionInfo.h"
15eb11fae6SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16b1c73532SDimitry Andric #include "WebAssemblyUtilities.h"
17145449b1SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
18eb11fae6SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
19eb11fae6SDimitry Andric #include "llvm/CodeGen/MachineDominanceFrontier.h"
20eb11fae6SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
21344a3780SDimitry Andric #include "llvm/CodeGen/WasmEHFuncInfo.h"
22706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
23ac9a064cSDimitry Andric #include "llvm/IR/Function.h"
24344a3780SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
25344a3780SDimitry Andric #include "llvm/Target/TargetMachine.h"
26eb11fae6SDimitry Andric 
27eb11fae6SDimitry Andric using namespace llvm;
28eb11fae6SDimitry Andric 
29eb11fae6SDimitry Andric #define DEBUG_TYPE "wasm-exception-info"
30eb11fae6SDimitry Andric 
31eb11fae6SDimitry Andric char WebAssemblyExceptionInfo::ID = 0;
32eb11fae6SDimitry Andric 
33eb11fae6SDimitry Andric INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE,
34eb11fae6SDimitry Andric                       "WebAssembly Exception Information", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)35ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
36eb11fae6SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
37eb11fae6SDimitry Andric INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE,
38eb11fae6SDimitry Andric                     "WebAssembly Exception Information", true, true)
39eb11fae6SDimitry Andric 
40d8e91e46SDimitry Andric bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &MF) {
41d8e91e46SDimitry Andric   LLVM_DEBUG(dbgs() << "********** Exception Info Calculation **********\n"
42d8e91e46SDimitry Andric                        "********** Function: "
43d8e91e46SDimitry Andric                     << MF.getName() << '\n');
44eb11fae6SDimitry Andric   releaseMemory();
45344a3780SDimitry Andric   if (MF.getTarget().getMCAsmInfo()->getExceptionHandlingType() !=
46344a3780SDimitry Andric           ExceptionHandling::Wasm ||
47344a3780SDimitry Andric       !MF.getFunction().hasPersonalityFn())
48344a3780SDimitry Andric     return false;
49ac9a064cSDimitry Andric   auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
50eb11fae6SDimitry Andric   auto &MDF = getAnalysis<MachineDominanceFrontier>();
51344a3780SDimitry Andric   recalculate(MF, MDT, MDF);
52344a3780SDimitry Andric   LLVM_DEBUG(dump());
53344a3780SDimitry Andric   return false;
54344a3780SDimitry Andric }
55344a3780SDimitry Andric 
56344a3780SDimitry Andric // Check if Dst is reachable from Src using BFS. Search only within BBs
57344a3780SDimitry Andric // dominated by Header.
isReachableAmongDominated(const MachineBasicBlock * Src,const MachineBasicBlock * Dst,const MachineBasicBlock * Header,const MachineDominatorTree & MDT)58344a3780SDimitry Andric static bool isReachableAmongDominated(const MachineBasicBlock *Src,
59344a3780SDimitry Andric                                       const MachineBasicBlock *Dst,
60344a3780SDimitry Andric                                       const MachineBasicBlock *Header,
61344a3780SDimitry Andric                                       const MachineDominatorTree &MDT) {
62344a3780SDimitry Andric   assert(MDT.dominates(Header, Dst));
63344a3780SDimitry Andric   SmallVector<const MachineBasicBlock *, 8> WL;
64344a3780SDimitry Andric   SmallPtrSet<const MachineBasicBlock *, 8> Visited;
65344a3780SDimitry Andric   WL.push_back(Src);
66344a3780SDimitry Andric 
67344a3780SDimitry Andric   while (!WL.empty()) {
68344a3780SDimitry Andric     const auto *MBB = WL.pop_back_val();
69344a3780SDimitry Andric     if (MBB == Dst)
70344a3780SDimitry Andric       return true;
71344a3780SDimitry Andric     Visited.insert(MBB);
72344a3780SDimitry Andric     for (auto *Succ : MBB->successors())
73344a3780SDimitry Andric       if (!Visited.count(Succ) && MDT.dominates(Header, Succ))
74344a3780SDimitry Andric         WL.push_back(Succ);
75344a3780SDimitry Andric   }
76eb11fae6SDimitry Andric   return false;
77eb11fae6SDimitry Andric }
78eb11fae6SDimitry Andric 
recalculate(MachineFunction & MF,MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)79eb11fae6SDimitry Andric void WebAssemblyExceptionInfo::recalculate(
80344a3780SDimitry Andric     MachineFunction &MF, MachineDominatorTree &MDT,
81344a3780SDimitry Andric     const MachineDominanceFrontier &MDF) {
82eb11fae6SDimitry Andric   // Postorder traversal of the dominator tree.
83cfca06d7SDimitry Andric   SmallVector<std::unique_ptr<WebAssemblyException>, 8> Exceptions;
84e3b55780SDimitry Andric   for (auto *DomNode : post_order(&MDT)) {
85eb11fae6SDimitry Andric     MachineBasicBlock *EHPad = DomNode->getBlock();
86eb11fae6SDimitry Andric     if (!EHPad->isEHPad())
87eb11fae6SDimitry Andric       continue;
88cfca06d7SDimitry Andric     auto WE = std::make_unique<WebAssemblyException>(EHPad);
89cfca06d7SDimitry Andric     discoverAndMapException(WE.get(), MDT, MDF);
90cfca06d7SDimitry Andric     Exceptions.push_back(std::move(WE));
91eb11fae6SDimitry Andric   }
92eb11fae6SDimitry Andric 
93344a3780SDimitry Andric   // WasmEHFuncInfo contains a map of <catchpad, its next unwind destination>,
94344a3780SDimitry Andric   // which means, if an exception is not caught by the catchpad, it should end
95344a3780SDimitry Andric   // up in the next unwind destination stored in this data structure. (It is
96344a3780SDimitry Andric   // written as catchswitch's 'unwind' destination in ll files.) The below is an
97344a3780SDimitry Andric   // intuitive example of their relationship in C++ code:
98344a3780SDimitry Andric   // try {
99344a3780SDimitry Andric   //   try {
100344a3780SDimitry Andric   //   } catch (int) { // catchpad
101344a3780SDimitry Andric   //      ...          // this catch (int) { ... } is grouped as an exception
102344a3780SDimitry Andric   //   }
103344a3780SDimitry Andric   // } catch (...) {   // next unwind destination
104344a3780SDimitry Andric   // }
105344a3780SDimitry Andric   // (The example is try-catches for illustration purpose, but the unwind
106344a3780SDimitry Andric   // destination can be also a cleanuppad generated by destructor calls.) So the
107344a3780SDimitry Andric   // unwind destination is in the outside of the catchpad's exception.
108344a3780SDimitry Andric   //
109344a3780SDimitry Andric   // We group exceptions in this analysis simply by including all BBs dominated
110344a3780SDimitry Andric   // by an EH pad. But in case the EH pad's unwind destination does not have any
111344a3780SDimitry Andric   // children outside of the exception, that unwind destination ends up also
112344a3780SDimitry Andric   // being dominated by the EH pad and included in the exception, which is not
113344a3780SDimitry Andric   // semantically correct, because it unwinds/rethrows into an inner scope.
114344a3780SDimitry Andric   //
115344a3780SDimitry Andric   // Here we extract those unwind destinations from their (incorrect) parent
116344a3780SDimitry Andric   // exception. Note that the unwind destinations may not be an immediate
117344a3780SDimitry Andric   // children of the parent exception, so we have to traverse the parent chain.
118344a3780SDimitry Andric   //
119344a3780SDimitry Andric   // We should traverse BBs in the preorder of the dominator tree, because
120344a3780SDimitry Andric   // otherwise the result can be incorrect. For example, when there are three
121344a3780SDimitry Andric   // exceptions A, B, and C and A > B > C (> is subexception relationship here),
122344a3780SDimitry Andric   // and A's unwind destination is B and B's is C. When we visit B before A, we
123344a3780SDimitry Andric   // end up extracting C only out of B but not out of A.
124344a3780SDimitry Andric   const auto *EHInfo = MF.getWasmEHFuncInfo();
1257fa27ce4SDimitry Andric   assert(EHInfo);
126344a3780SDimitry Andric   SmallVector<std::pair<WebAssemblyException *, WebAssemblyException *>>
127344a3780SDimitry Andric       UnwindWEVec;
128344a3780SDimitry Andric   for (auto *DomNode : depth_first(&MDT)) {
129344a3780SDimitry Andric     MachineBasicBlock *EHPad = DomNode->getBlock();
130344a3780SDimitry Andric     if (!EHPad->isEHPad())
131344a3780SDimitry Andric       continue;
132344a3780SDimitry Andric     if (!EHInfo->hasUnwindDest(EHPad))
133344a3780SDimitry Andric       continue;
134344a3780SDimitry Andric     auto *UnwindDest = EHInfo->getUnwindDest(EHPad);
135344a3780SDimitry Andric     auto *SrcWE = getExceptionFor(EHPad);
136344a3780SDimitry Andric     auto *DstWE = getExceptionFor(UnwindDest);
137344a3780SDimitry Andric     if (SrcWE->contains(DstWE)) {
138344a3780SDimitry Andric       UnwindWEVec.push_back(std::make_pair(SrcWE, DstWE));
139344a3780SDimitry Andric       LLVM_DEBUG(dbgs() << "Unwind destination ExceptionInfo fix:\n  "
140344a3780SDimitry Andric                         << DstWE->getEHPad()->getNumber() << "."
141344a3780SDimitry Andric                         << DstWE->getEHPad()->getName()
142344a3780SDimitry Andric                         << "'s exception is taken out of "
143344a3780SDimitry Andric                         << SrcWE->getEHPad()->getNumber() << "."
144344a3780SDimitry Andric                         << SrcWE->getEHPad()->getName() << "'s exception\n");
145344a3780SDimitry Andric       DstWE->setParentException(SrcWE->getParentException());
146344a3780SDimitry Andric     }
147344a3780SDimitry Andric   }
148344a3780SDimitry Andric 
149344a3780SDimitry Andric   // After fixing subexception relationship between unwind destinations above,
150344a3780SDimitry Andric   // there can still be remaining discrepancies.
151344a3780SDimitry Andric   //
152344a3780SDimitry Andric   // For example, suppose Exception A is dominated by EHPad A and Exception B is
153344a3780SDimitry Andric   // dominated by EHPad B. EHPad A's unwind destination is EHPad B, but because
154344a3780SDimitry Andric   // EHPad B is dominated by EHPad A, the initial grouping makes Exception B a
155344a3780SDimitry Andric   // subexception of Exception A, and we fix it by taking Exception B out of
156344a3780SDimitry Andric   // Exception A above. But there can still be remaining BBs within Exception A
157344a3780SDimitry Andric   // that are reachable from Exception B. These BBs semantically don't belong
158344a3780SDimitry Andric   // to Exception A and were not a part of this 'catch' clause or cleanup code
159344a3780SDimitry Andric   // in the original code, but they just happened to be grouped within Exception
160344a3780SDimitry Andric   // A because they were dominated by EHPad A. We fix this case by taking those
161344a3780SDimitry Andric   // BBs out of the incorrect exception and all its subexceptions that it
162344a3780SDimitry Andric   // belongs to.
163344a3780SDimitry Andric   //
164344a3780SDimitry Andric   // 1. First, we take out remaining incorrect subexceptions. This part is
165344a3780SDimitry Andric   // easier, because we haven't added BBs to exceptions yet, we only need to
166344a3780SDimitry Andric   // change parent exception pointer.
167344a3780SDimitry Andric   for (auto *DomNode : depth_first(&MDT)) {
168344a3780SDimitry Andric     MachineBasicBlock *EHPad = DomNode->getBlock();
169344a3780SDimitry Andric     if (!EHPad->isEHPad())
170344a3780SDimitry Andric       continue;
171344a3780SDimitry Andric     auto *WE = getExceptionFor(EHPad);
172344a3780SDimitry Andric 
173344a3780SDimitry Andric     // For each source EHPad -> unwind destination EHPad
174344a3780SDimitry Andric     for (auto &P : UnwindWEVec) {
175344a3780SDimitry Andric       auto *SrcWE = P.first;
176344a3780SDimitry Andric       auto *DstWE = P.second;
177344a3780SDimitry Andric       // If WE (the current EH pad's exception) is still contained in SrcWE but
178344a3780SDimitry Andric       // reachable from DstWE that was taken out of SrcWE above, we have to take
179344a3780SDimitry Andric       // out WE out of SrcWE too.
180344a3780SDimitry Andric       if (WE != SrcWE && SrcWE->contains(WE) && !DstWE->contains(WE) &&
181344a3780SDimitry Andric           isReachableAmongDominated(DstWE->getEHPad(), EHPad, SrcWE->getEHPad(),
182344a3780SDimitry Andric                                     MDT)) {
183344a3780SDimitry Andric         LLVM_DEBUG(dbgs() << "Remaining reachable ExceptionInfo fix:\n  "
184344a3780SDimitry Andric                           << WE->getEHPad()->getNumber() << "."
185344a3780SDimitry Andric                           << WE->getEHPad()->getName()
186344a3780SDimitry Andric                           << "'s exception is taken out of "
187344a3780SDimitry Andric                           << SrcWE->getEHPad()->getNumber() << "."
188344a3780SDimitry Andric                           << SrcWE->getEHPad()->getName() << "'s exception\n");
189344a3780SDimitry Andric         WE->setParentException(SrcWE->getParentException());
190344a3780SDimitry Andric       }
191344a3780SDimitry Andric     }
192344a3780SDimitry Andric   }
193344a3780SDimitry Andric 
194344a3780SDimitry Andric   // Add BBs to exceptions' block set. This is a preparation to take out
195344a3780SDimitry Andric   // remaining incorect BBs from exceptions, because we need to iterate over BBs
196344a3780SDimitry Andric   // for each exception.
197344a3780SDimitry Andric   for (auto *DomNode : post_order(&MDT)) {
198344a3780SDimitry Andric     MachineBasicBlock *MBB = DomNode->getBlock();
199344a3780SDimitry Andric     WebAssemblyException *WE = getExceptionFor(MBB);
200344a3780SDimitry Andric     for (; WE; WE = WE->getParentException())
201344a3780SDimitry Andric       WE->addToBlocksSet(MBB);
202344a3780SDimitry Andric   }
203344a3780SDimitry Andric 
204344a3780SDimitry Andric   // 2. We take out remaining individual BBs out. Now we have added BBs to each
205344a3780SDimitry Andric   // exceptions' BlockSet, when we take a BB out of an exception, we need to fix
206344a3780SDimitry Andric   // those sets too.
207344a3780SDimitry Andric   for (auto &P : UnwindWEVec) {
208344a3780SDimitry Andric     auto *SrcWE = P.first;
209344a3780SDimitry Andric     auto *DstWE = P.second;
210344a3780SDimitry Andric 
211ac9a064cSDimitry Andric     SrcWE->getBlocksSet().remove_if([&](MachineBasicBlock *MBB){
212344a3780SDimitry Andric       if (MBB->isEHPad()) {
213344a3780SDimitry Andric         assert(!isReachableAmongDominated(DstWE->getEHPad(), MBB,
214344a3780SDimitry Andric                                           SrcWE->getEHPad(), MDT) &&
215344a3780SDimitry Andric                "We already handled EH pads above");
216ac9a064cSDimitry Andric         return false;
217344a3780SDimitry Andric       }
218344a3780SDimitry Andric       if (isReachableAmongDominated(DstWE->getEHPad(), MBB, SrcWE->getEHPad(),
219344a3780SDimitry Andric                                     MDT)) {
220344a3780SDimitry Andric         LLVM_DEBUG(dbgs() << "Remainder BB: " << MBB->getNumber() << "."
221344a3780SDimitry Andric                           << MBB->getName() << " is\n");
222344a3780SDimitry Andric         WebAssemblyException *InnerWE = getExceptionFor(MBB);
223344a3780SDimitry Andric         while (InnerWE != SrcWE) {
224344a3780SDimitry Andric           LLVM_DEBUG(dbgs()
225344a3780SDimitry Andric                      << "  removed from " << InnerWE->getEHPad()->getNumber()
226344a3780SDimitry Andric                      << "." << InnerWE->getEHPad()->getName()
227344a3780SDimitry Andric                      << "'s exception\n");
228344a3780SDimitry Andric           InnerWE->removeFromBlocksSet(MBB);
229344a3780SDimitry Andric           InnerWE = InnerWE->getParentException();
230344a3780SDimitry Andric         }
231344a3780SDimitry Andric         LLVM_DEBUG(dbgs() << "  removed from " << SrcWE->getEHPad()->getNumber()
232344a3780SDimitry Andric                           << "." << SrcWE->getEHPad()->getName()
233344a3780SDimitry Andric                           << "'s exception\n");
234344a3780SDimitry Andric         changeExceptionFor(MBB, SrcWE->getParentException());
235344a3780SDimitry Andric         if (SrcWE->getParentException())
236344a3780SDimitry Andric           SrcWE->getParentException()->addToBlocksSet(MBB);
237ac9a064cSDimitry Andric         return true;
238344a3780SDimitry Andric       }
239ac9a064cSDimitry Andric       return false;
240ac9a064cSDimitry Andric     });
241344a3780SDimitry Andric   }
242344a3780SDimitry Andric 
243344a3780SDimitry Andric   // Add BBs to exceptions' block vector
244e3b55780SDimitry Andric   for (auto *DomNode : post_order(&MDT)) {
245eb11fae6SDimitry Andric     MachineBasicBlock *MBB = DomNode->getBlock();
246eb11fae6SDimitry Andric     WebAssemblyException *WE = getExceptionFor(MBB);
247eb11fae6SDimitry Andric     for (; WE; WE = WE->getParentException())
248344a3780SDimitry Andric       WE->addToBlocksVector(MBB);
249eb11fae6SDimitry Andric   }
250eb11fae6SDimitry Andric 
251cfca06d7SDimitry Andric   SmallVector<WebAssemblyException*, 8> ExceptionPointers;
252cfca06d7SDimitry Andric   ExceptionPointers.reserve(Exceptions.size());
253cfca06d7SDimitry Andric 
254eb11fae6SDimitry Andric   // Add subexceptions to exceptions
255cfca06d7SDimitry Andric   for (auto &WE : Exceptions) {
256cfca06d7SDimitry Andric     ExceptionPointers.push_back(WE.get());
257eb11fae6SDimitry Andric     if (WE->getParentException())
258cfca06d7SDimitry Andric       WE->getParentException()->getSubExceptions().push_back(std::move(WE));
259eb11fae6SDimitry Andric     else
260cfca06d7SDimitry Andric       addTopLevelException(std::move(WE));
261eb11fae6SDimitry Andric   }
262eb11fae6SDimitry Andric 
263eb11fae6SDimitry Andric   // For convenience, Blocks and SubExceptions are inserted in postorder.
264eb11fae6SDimitry Andric   // Reverse the lists.
265cfca06d7SDimitry Andric   for (auto *WE : ExceptionPointers) {
266eb11fae6SDimitry Andric     WE->reverseBlock();
267eb11fae6SDimitry Andric     std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end());
268eb11fae6SDimitry Andric   }
269eb11fae6SDimitry Andric }
270eb11fae6SDimitry Andric 
releaseMemory()271eb11fae6SDimitry Andric void WebAssemblyExceptionInfo::releaseMemory() {
272eb11fae6SDimitry Andric   BBMap.clear();
273eb11fae6SDimitry Andric   TopLevelExceptions.clear();
274eb11fae6SDimitry Andric }
275eb11fae6SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const276eb11fae6SDimitry Andric void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const {
277eb11fae6SDimitry Andric   AU.setPreservesAll();
278ac9a064cSDimitry Andric   AU.addRequired<MachineDominatorTreeWrapperPass>();
279eb11fae6SDimitry Andric   AU.addRequired<MachineDominanceFrontier>();
280eb11fae6SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
281eb11fae6SDimitry Andric }
282eb11fae6SDimitry Andric 
discoverAndMapException(WebAssemblyException * WE,const MachineDominatorTree & MDT,const MachineDominanceFrontier & MDF)283eb11fae6SDimitry Andric void WebAssemblyExceptionInfo::discoverAndMapException(
284eb11fae6SDimitry Andric     WebAssemblyException *WE, const MachineDominatorTree &MDT,
285eb11fae6SDimitry Andric     const MachineDominanceFrontier &MDF) {
286eb11fae6SDimitry Andric   unsigned NumBlocks = 0;
287eb11fae6SDimitry Andric   unsigned NumSubExceptions = 0;
288eb11fae6SDimitry Andric 
289eb11fae6SDimitry Andric   // Map blocks that belong to a catchpad / cleanuppad
290eb11fae6SDimitry Andric   MachineBasicBlock *EHPad = WE->getEHPad();
291eb11fae6SDimitry Andric   SmallVector<MachineBasicBlock *, 8> WL;
292eb11fae6SDimitry Andric   WL.push_back(EHPad);
293eb11fae6SDimitry Andric   while (!WL.empty()) {
294eb11fae6SDimitry Andric     MachineBasicBlock *MBB = WL.pop_back_val();
295eb11fae6SDimitry Andric 
296eb11fae6SDimitry Andric     // Find its outermost discovered exception. If this is a discovered block,
297eb11fae6SDimitry Andric     // check if it is already discovered to be a subexception of this exception.
298eb11fae6SDimitry Andric     WebAssemblyException *SubE = getOutermostException(MBB);
299eb11fae6SDimitry Andric     if (SubE) {
300eb11fae6SDimitry Andric       if (SubE != WE) {
301eb11fae6SDimitry Andric         // Discover a subexception of this exception.
302eb11fae6SDimitry Andric         SubE->setParentException(WE);
303eb11fae6SDimitry Andric         ++NumSubExceptions;
304eb11fae6SDimitry Andric         NumBlocks += SubE->getBlocksVector().capacity();
305eb11fae6SDimitry Andric         // All blocks that belong to this subexception have been already
306eb11fae6SDimitry Andric         // discovered. Skip all of them. Add the subexception's landing pad's
307eb11fae6SDimitry Andric         // dominance frontier to the worklist.
308eb11fae6SDimitry Andric         for (auto &Frontier : MDF.find(SubE->getEHPad())->second)
309eb11fae6SDimitry Andric           if (MDT.dominates(EHPad, Frontier))
310eb11fae6SDimitry Andric             WL.push_back(Frontier);
311eb11fae6SDimitry Andric       }
312eb11fae6SDimitry Andric       continue;
313eb11fae6SDimitry Andric     }
314eb11fae6SDimitry Andric 
315eb11fae6SDimitry Andric     // This is an undiscovered block. Map it to the current exception.
316eb11fae6SDimitry Andric     changeExceptionFor(MBB, WE);
317eb11fae6SDimitry Andric     ++NumBlocks;
318eb11fae6SDimitry Andric 
319eb11fae6SDimitry Andric     // Add successors dominated by the current BB to the worklist.
320eb11fae6SDimitry Andric     for (auto *Succ : MBB->successors())
321eb11fae6SDimitry Andric       if (MDT.dominates(EHPad, Succ))
322eb11fae6SDimitry Andric         WL.push_back(Succ);
323eb11fae6SDimitry Andric   }
324eb11fae6SDimitry Andric 
325eb11fae6SDimitry Andric   WE->getSubExceptions().reserve(NumSubExceptions);
326eb11fae6SDimitry Andric   WE->reserveBlocks(NumBlocks);
327eb11fae6SDimitry Andric }
328eb11fae6SDimitry Andric 
329eb11fae6SDimitry Andric WebAssemblyException *
getOutermostException(MachineBasicBlock * MBB) const330eb11fae6SDimitry Andric WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const {
331eb11fae6SDimitry Andric   WebAssemblyException *WE = getExceptionFor(MBB);
332eb11fae6SDimitry Andric   if (WE) {
333eb11fae6SDimitry Andric     while (WebAssemblyException *Parent = WE->getParentException())
334eb11fae6SDimitry Andric       WE = Parent;
335eb11fae6SDimitry Andric   }
336eb11fae6SDimitry Andric   return WE;
337eb11fae6SDimitry Andric }
338eb11fae6SDimitry Andric 
print(raw_ostream & OS,unsigned Depth) const339eb11fae6SDimitry Andric void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const {
340eb11fae6SDimitry Andric   OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth()
341eb11fae6SDimitry Andric                        << " containing: ";
342eb11fae6SDimitry Andric 
343eb11fae6SDimitry Andric   for (unsigned I = 0; I < getBlocks().size(); ++I) {
344eb11fae6SDimitry Andric     MachineBasicBlock *MBB = getBlocks()[I];
345eb11fae6SDimitry Andric     if (I)
346eb11fae6SDimitry Andric       OS << ", ";
347eb11fae6SDimitry Andric     OS << "%bb." << MBB->getNumber();
348eb11fae6SDimitry Andric     if (const auto *BB = MBB->getBasicBlock())
349eb11fae6SDimitry Andric       if (BB->hasName())
350eb11fae6SDimitry Andric         OS << "." << BB->getName();
351eb11fae6SDimitry Andric 
352eb11fae6SDimitry Andric     if (getEHPad() == MBB)
353eb11fae6SDimitry Andric       OS << " (landing-pad)";
354eb11fae6SDimitry Andric   }
355eb11fae6SDimitry Andric   OS << "\n";
356eb11fae6SDimitry Andric 
357eb11fae6SDimitry Andric   for (auto &SubE : SubExceptions)
358eb11fae6SDimitry Andric     SubE->print(OS, Depth + 2);
359eb11fae6SDimitry Andric }
360eb11fae6SDimitry Andric 
361eb11fae6SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const362eb11fae6SDimitry Andric LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); }
363eb11fae6SDimitry Andric #endif
364eb11fae6SDimitry Andric 
operator <<(raw_ostream & OS,const WebAssemblyException & WE)365eb11fae6SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) {
366eb11fae6SDimitry Andric   WE.print(OS);
367eb11fae6SDimitry Andric   return OS;
368eb11fae6SDimitry Andric }
369eb11fae6SDimitry Andric 
print(raw_ostream & OS,const Module *) const370eb11fae6SDimitry Andric void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const {
371cfca06d7SDimitry Andric   for (auto &WE : TopLevelExceptions)
372eb11fae6SDimitry Andric     WE->print(OS);
373eb11fae6SDimitry Andric }
374