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