1 //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// \brief This file implements WebAssemblyException information analysis.
12 //===----------------------------------------------------------------------===//
14 #include "WebAssemblyExceptionInfo.h"
15 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16 #include "WebAssemblyUtilities.h"
17 #include "llvm/ADT/PostOrderIterator.h"
18 #include "llvm/CodeGen/MachineDominanceFrontier.h"
19 #include "llvm/CodeGen/MachineDominators.h"
23 #define DEBUG_TYPE "wasm-exception-info"
25 char WebAssemblyExceptionInfo::ID
= 0;
27 INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo
, DEBUG_TYPE
,
28 "WebAssembly Exception Information", true, true)
29 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree
)
30 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier
)
31 INITIALIZE_PASS_END(WebAssemblyExceptionInfo
, DEBUG_TYPE
,
32 "WebAssembly Exception Information", true, true)
34 bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction
&MF
) {
35 LLVM_DEBUG(dbgs() << "********** Exception Info Calculation **********\n"
36 "********** Function: "
37 << MF
.getName() << '\n');
39 auto &MDT
= getAnalysis
<MachineDominatorTree
>();
40 auto &MDF
= getAnalysis
<MachineDominanceFrontier
>();
41 recalculate(MDT
, MDF
);
45 void WebAssemblyExceptionInfo::recalculate(
46 MachineDominatorTree
&MDT
, const MachineDominanceFrontier
&MDF
) {
47 // Postorder traversal of the dominator tree.
48 SmallVector
<WebAssemblyException
*, 8> Exceptions
;
49 for (auto DomNode
: post_order(&MDT
)) {
50 MachineBasicBlock
*EHPad
= DomNode
->getBlock();
51 if (!EHPad
->isEHPad())
53 auto *WE
= new WebAssemblyException(EHPad
);
54 discoverAndMapException(WE
, MDT
, MDF
);
55 Exceptions
.push_back(WE
);
58 // Add BBs to exceptions
59 for (auto DomNode
: post_order(&MDT
)) {
60 MachineBasicBlock
*MBB
= DomNode
->getBlock();
61 WebAssemblyException
*WE
= getExceptionFor(MBB
);
62 for (; WE
; WE
= WE
->getParentException())
66 // Add subexceptions to exceptions
67 for (auto *WE
: Exceptions
) {
68 if (WE
->getParentException())
69 WE
->getParentException()->getSubExceptions().push_back(WE
);
71 addTopLevelException(WE
);
74 // For convenience, Blocks and SubExceptions are inserted in postorder.
76 for (auto *WE
: Exceptions
) {
78 std::reverse(WE
->getSubExceptions().begin(), WE
->getSubExceptions().end());
82 void WebAssemblyExceptionInfo::releaseMemory() {
84 DeleteContainerPointers(TopLevelExceptions
);
85 TopLevelExceptions
.clear();
88 void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage
&AU
) const {
90 AU
.addRequired
<MachineDominatorTree
>();
91 AU
.addRequired
<MachineDominanceFrontier
>();
92 MachineFunctionPass::getAnalysisUsage(AU
);
95 void WebAssemblyExceptionInfo::discoverAndMapException(
96 WebAssemblyException
*WE
, const MachineDominatorTree
&MDT
,
97 const MachineDominanceFrontier
&MDF
) {
98 unsigned NumBlocks
= 0;
99 unsigned NumSubExceptions
= 0;
101 // Map blocks that belong to a catchpad / cleanuppad
102 MachineBasicBlock
*EHPad
= WE
->getEHPad();
103 SmallVector
<MachineBasicBlock
*, 8> WL
;
105 while (!WL
.empty()) {
106 MachineBasicBlock
*MBB
= WL
.pop_back_val();
108 // Find its outermost discovered exception. If this is a discovered block,
109 // check if it is already discovered to be a subexception of this exception.
110 WebAssemblyException
*SubE
= getOutermostException(MBB
);
113 // Discover a subexception of this exception.
114 SubE
->setParentException(WE
);
116 NumBlocks
+= SubE
->getBlocksVector().capacity();
117 // All blocks that belong to this subexception have been already
118 // discovered. Skip all of them. Add the subexception's landing pad's
119 // dominance frontier to the worklist.
120 for (auto &Frontier
: MDF
.find(SubE
->getEHPad())->second
)
121 if (MDT
.dominates(EHPad
, Frontier
))
122 WL
.push_back(Frontier
);
127 // This is an undiscovered block. Map it to the current exception.
128 changeExceptionFor(MBB
, WE
);
131 // Add successors dominated by the current BB to the worklist.
132 for (auto *Succ
: MBB
->successors())
133 if (MDT
.dominates(EHPad
, Succ
))
137 WE
->getSubExceptions().reserve(NumSubExceptions
);
138 WE
->reserveBlocks(NumBlocks
);
141 WebAssemblyException
*
142 WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock
*MBB
) const {
143 WebAssemblyException
*WE
= getExceptionFor(MBB
);
145 while (WebAssemblyException
*Parent
= WE
->getParentException())
151 void WebAssemblyException::print(raw_ostream
&OS
, unsigned Depth
) const {
152 OS
.indent(Depth
* 2) << "Exception at depth " << getExceptionDepth()
155 for (unsigned I
= 0; I
< getBlocks().size(); ++I
) {
156 MachineBasicBlock
*MBB
= getBlocks()[I
];
159 OS
<< "%bb." << MBB
->getNumber();
160 if (const auto *BB
= MBB
->getBasicBlock())
162 OS
<< "." << BB
->getName();
164 if (getEHPad() == MBB
)
165 OS
<< " (landing-pad)";
169 for (auto &SubE
: SubExceptions
)
170 SubE
->print(OS
, Depth
+ 2);
173 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
174 LLVM_DUMP_METHOD
void WebAssemblyException::dump() const { print(dbgs()); }
177 raw_ostream
&operator<<(raw_ostream
&OS
, const WebAssemblyException
&WE
) {
182 void WebAssemblyExceptionInfo::print(raw_ostream
&OS
, const Module
*) const {
183 for (auto *WE
: TopLevelExceptions
)