1 //===-- WebAssemblyExceptionInfo.h - WebAssembly Exception Info -*- C++ -*-===//
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 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H
15 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H
17 #include "WebAssembly.h"
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
23 class MachineDominatorTree
;
24 class MachineDominanceFrontier
;
26 // WebAssembly instructions for exception handling are structured as follows:
30 // instructions* | -> A WebAssemblyException consists of this region
33 // A WebAssemblyException object contains BBs that belong to a 'catch' part of
34 // the try-catch-end structure to be created later. 'try' and 'end' markers
35 // are not present at this stage and will be generated in CFGStackify pass.
36 // Because CFGSort requires all the BBs within a catch part to be sorted
37 // together as it does for loops, this pass calculates the nesting structure of
38 // catch part of exceptions in a function.
40 // An exception catch part is defined as a BB with catch instruction and all
41 // other BBs dominated by this BB.
42 class WebAssemblyException
{
43 MachineBasicBlock
*EHPad
= nullptr;
45 WebAssemblyException
*ParentException
= nullptr;
46 std::vector
<WebAssemblyException
*> SubExceptions
;
47 std::vector
<MachineBasicBlock
*> Blocks
;
48 SmallPtrSet
<const MachineBasicBlock
*, 8> BlockSet
;
51 WebAssemblyException(MachineBasicBlock
*EHPad
) : EHPad(EHPad
) {}
52 ~WebAssemblyException() { DeleteContainerPointers(SubExceptions
); }
53 WebAssemblyException(const WebAssemblyException
&) = delete;
54 const WebAssemblyException
&operator=(const WebAssemblyException
&) = delete;
56 MachineBasicBlock
*getEHPad() const { return EHPad
; }
57 MachineBasicBlock
*getHeader() const { return EHPad
; }
58 WebAssemblyException
*getParentException() const { return ParentException
; }
59 void setParentException(WebAssemblyException
*WE
) { ParentException
= WE
; }
61 bool contains(const WebAssemblyException
*WE
) const {
66 return contains(WE
->getParentException());
68 bool contains(const MachineBasicBlock
*MBB
) const {
69 return BlockSet
.count(MBB
);
72 void addBlock(MachineBasicBlock
*MBB
) {
73 Blocks
.push_back(MBB
);
76 ArrayRef
<MachineBasicBlock
*> getBlocks() const { return Blocks
; }
77 using block_iterator
= typename ArrayRef
<MachineBasicBlock
*>::const_iterator
;
78 block_iterator
block_begin() const { return getBlocks().begin(); }
79 block_iterator
block_end() const { return getBlocks().end(); }
80 inline iterator_range
<block_iterator
> blocks() const {
81 return make_range(block_begin(), block_end());
83 unsigned getNumBlocks() const { return Blocks
.size(); }
84 std::vector
<MachineBasicBlock
*> &getBlocksVector() { return Blocks
; }
86 const std::vector
<WebAssemblyException
*> &getSubExceptions() const {
89 std::vector
<WebAssemblyException
*> &getSubExceptions() {
92 void addSubException(WebAssemblyException
*E
) { SubExceptions
.push_back(E
); }
93 using iterator
= typename
std::vector
<WebAssemblyException
*>::const_iterator
;
94 iterator
begin() const { return SubExceptions
.begin(); }
95 iterator
end() const { return SubExceptions
.end(); }
97 void reserveBlocks(unsigned Size
) { Blocks
.reserve(Size
); }
98 void reverseBlock(unsigned From
= 0) {
99 std::reverse(Blocks
.begin() + From
, Blocks
.end());
102 // Return the nesting level. An outermost one has depth 1.
103 unsigned getExceptionDepth() const {
105 for (const WebAssemblyException
*CurException
= ParentException
;
106 CurException
; CurException
= CurException
->ParentException
)
111 void print(raw_ostream
&OS
, unsigned Depth
= 0) const;
115 raw_ostream
&operator<<(raw_ostream
&OS
, const WebAssemblyException
&WE
);
117 class WebAssemblyExceptionInfo final
: public MachineFunctionPass
{
118 // Mapping of basic blocks to the innermost exception they occur in
119 DenseMap
<const MachineBasicBlock
*, WebAssemblyException
*> BBMap
;
120 std::vector
<WebAssemblyException
*> TopLevelExceptions
;
122 void discoverAndMapException(WebAssemblyException
*WE
,
123 const MachineDominatorTree
&MDT
,
124 const MachineDominanceFrontier
&MDF
);
125 WebAssemblyException
*getOutermostException(MachineBasicBlock
*MBB
) const;
129 WebAssemblyExceptionInfo() : MachineFunctionPass(ID
) {
130 initializeWebAssemblyExceptionInfoPass(*PassRegistry::getPassRegistry());
132 ~WebAssemblyExceptionInfo() override
{ releaseMemory(); }
133 WebAssemblyExceptionInfo(const WebAssemblyExceptionInfo
&) = delete;
134 WebAssemblyExceptionInfo
&
135 operator=(const WebAssemblyExceptionInfo
&) = delete;
137 bool runOnMachineFunction(MachineFunction
&) override
;
138 void releaseMemory() override
;
139 void recalculate(MachineDominatorTree
&MDT
,
140 const MachineDominanceFrontier
&MDF
);
141 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
143 bool empty() const { return TopLevelExceptions
.empty(); }
145 // Return the innermost exception that MBB lives in. If the block is not in an
146 // exception, null is returned.
147 WebAssemblyException
*getExceptionFor(const MachineBasicBlock
*MBB
) const {
148 return BBMap
.lookup(MBB
);
151 void changeExceptionFor(MachineBasicBlock
*MBB
, WebAssemblyException
*WE
) {
159 void addTopLevelException(WebAssemblyException
*WE
) {
160 assert(!WE
->getParentException() && "Not a top level exception!");
161 TopLevelExceptions
.push_back(WE
);
164 void print(raw_ostream
&OS
, const Module
*M
= nullptr) const override
;
167 } // end namespace llvm