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