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
<std::unique_ptr
<WebAssemblyException
>> SubExceptions
;
47 std::vector
<MachineBasicBlock
*> Blocks
;
48 SmallPtrSet
<MachineBasicBlock
*, 8> BlockSet
;
51 WebAssemblyException(MachineBasicBlock
*EHPad
) : EHPad(EHPad
) {}
52 WebAssemblyException(const WebAssemblyException
&) = delete;
53 const WebAssemblyException
&operator=(const WebAssemblyException
&) = delete;
55 MachineBasicBlock
*getEHPad() const { return EHPad
; }
56 MachineBasicBlock
*getHeader() const { return EHPad
; }
57 WebAssemblyException
*getParentException() const { return ParentException
; }
58 void setParentException(WebAssemblyException
*WE
) { ParentException
= WE
; }
60 bool contains(const WebAssemblyException
*WE
) const {
65 return contains(WE
->getParentException());
67 bool contains(const MachineBasicBlock
*MBB
) const {
68 return BlockSet
.count(MBB
);
71 void addToBlocksSet(MachineBasicBlock
*MBB
) { BlockSet
.insert(MBB
); }
72 void removeFromBlocksSet(MachineBasicBlock
*MBB
) { BlockSet
.erase(MBB
); }
73 void addToBlocksVector(MachineBasicBlock
*MBB
) { Blocks
.push_back(MBB
); }
74 void addBlock(MachineBasicBlock
*MBB
) {
75 Blocks
.push_back(MBB
);
78 ArrayRef
<MachineBasicBlock
*> getBlocks() const { return Blocks
; }
79 using block_iterator
= typename ArrayRef
<MachineBasicBlock
*>::const_iterator
;
80 block_iterator
block_begin() const { return getBlocks().begin(); }
81 block_iterator
block_end() const { return getBlocks().end(); }
82 inline iterator_range
<block_iterator
> blocks() const {
83 return make_range(block_begin(), block_end());
85 unsigned getNumBlocks() const { return Blocks
.size(); }
86 std::vector
<MachineBasicBlock
*> &getBlocksVector() { return Blocks
; }
87 SmallPtrSetImpl
<MachineBasicBlock
*> &getBlocksSet() { return BlockSet
; }
89 const std::vector
<std::unique_ptr
<WebAssemblyException
>> &
90 getSubExceptions() const {
93 std::vector
<std::unique_ptr
<WebAssemblyException
>> &getSubExceptions() {
96 void addSubException(std::unique_ptr
<WebAssemblyException
> E
) {
97 SubExceptions
.push_back(std::move(E
));
99 using iterator
= typename
decltype(SubExceptions
)::const_iterator
;
100 iterator
begin() const { return SubExceptions
.begin(); }
101 iterator
end() const { return SubExceptions
.end(); }
103 void reserveBlocks(unsigned Size
) { Blocks
.reserve(Size
); }
104 void reverseBlock(unsigned From
= 0) {
105 std::reverse(Blocks
.begin() + From
, Blocks
.end());
108 // Return the nesting level. An outermost one has depth 1.
109 unsigned getExceptionDepth() const {
111 for (const WebAssemblyException
*CurException
= ParentException
;
112 CurException
; CurException
= CurException
->ParentException
)
117 void print(raw_ostream
&OS
, unsigned Depth
= 0) const;
121 raw_ostream
&operator<<(raw_ostream
&OS
, const WebAssemblyException
&WE
);
123 class WebAssemblyExceptionInfo final
: public MachineFunctionPass
{
124 // Mapping of basic blocks to the innermost exception they occur in
125 DenseMap
<const MachineBasicBlock
*, WebAssemblyException
*> BBMap
;
126 std::vector
<std::unique_ptr
<WebAssemblyException
>> TopLevelExceptions
;
128 void discoverAndMapException(WebAssemblyException
*WE
,
129 const MachineDominatorTree
&MDT
,
130 const MachineDominanceFrontier
&MDF
);
131 WebAssemblyException
*getOutermostException(MachineBasicBlock
*MBB
) const;
135 WebAssemblyExceptionInfo() : MachineFunctionPass(ID
) {
136 initializeWebAssemblyExceptionInfoPass(*PassRegistry::getPassRegistry());
138 ~WebAssemblyExceptionInfo() override
{ releaseMemory(); }
139 WebAssemblyExceptionInfo(const WebAssemblyExceptionInfo
&) = delete;
140 WebAssemblyExceptionInfo
&
141 operator=(const WebAssemblyExceptionInfo
&) = delete;
143 bool runOnMachineFunction(MachineFunction
&) override
;
144 void releaseMemory() override
;
145 void recalculate(MachineFunction
&MF
, MachineDominatorTree
&MDT
,
146 const MachineDominanceFrontier
&MDF
);
147 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
149 bool empty() const { return TopLevelExceptions
.empty(); }
151 // Return the innermost exception that MBB lives in. If the block is not in an
152 // exception, null is returned.
153 WebAssemblyException
*getExceptionFor(const MachineBasicBlock
*MBB
) const {
154 return BBMap
.lookup(MBB
);
157 void changeExceptionFor(const MachineBasicBlock
*MBB
,
158 WebAssemblyException
*WE
) {
166 void addTopLevelException(std::unique_ptr
<WebAssemblyException
> WE
) {
167 assert(!WE
->getParentException() && "Not a top level exception!");
168 TopLevelExceptions
.push_back(std::move(WE
));
171 void print(raw_ostream
&OS
, const Module
*M
= nullptr) const override
;
174 } // end namespace llvm