Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h
Line
Count
Source (jump to first uncovered line)
1
//===-- WebAssemblyExceptionInfo.h - WebAssembly Exception Info -*- C++ -*-===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
///
9
/// \file
10
/// \brief This file implements WebAssemblyException information analysis.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H
15
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H
16
17
#include "WebAssembly.h"
18
#include "llvm/ADT/SetVector.h"
19
#include "llvm/CodeGen/MachineFunctionPass.h"
20
21
namespace llvm {
22
23
class MachineDominatorTree;
24
class MachineDominanceFrontier;
25
26
// WebAssembly instructions for exception handling are structured as follows:
27
//   try
28
//     instructions*
29
//   catch             ----|
30
//     instructions*       | -> A WebAssemblyException consists of this region
31
//   end               ----|
32
//
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.
39
//
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;
44
45
  WebAssemblyException *ParentException = nullptr;
46
  std::vector<WebAssemblyException *> SubExceptions;
47
  std::vector<MachineBasicBlock *> Blocks;
48
  SmallPtrSet<const MachineBasicBlock *, 8> BlockSet;
49
50
public:
51
79
  WebAssemblyException(MachineBasicBlock *EHPad) : EHPad(EHPad) {}
52
79
  ~WebAssemblyException() { DeleteContainerPointers(SubExceptions); }
53
  WebAssemblyException(const WebAssemblyException &) = delete;
54
  const WebAssemblyException &operator=(const WebAssemblyException &) = delete;
55
56
125
  MachineBasicBlock *getEHPad() const { return EHPad; }
57
493
  MachineBasicBlock *getHeader() const { return EHPad; }
58
499
  WebAssemblyException *getParentException() const { return ParentException; }
59
27
  void setParentException(WebAssemblyException *WE) { ParentException = WE; }
60
61
0
  bool contains(const WebAssemblyException *WE) const {
62
0
    if (WE == this)
63
0
      return true;
64
0
    if (!WE)
65
0
      return false;
66
0
    return contains(WE->getParentException());
67
0
  }
68
329
  bool contains(const MachineBasicBlock *MBB) const {
69
329
    return BlockSet.count(MBB);
70
329
  }
71
72
335
  void addBlock(MachineBasicBlock *MBB) {
73
335
    Blocks.push_back(MBB);
74
335
    BlockSet.insert(MBB);
75
335
  }
76
142
  ArrayRef<MachineBasicBlock *> getBlocks() const { return Blocks; }
77
  using block_iterator = typename ArrayRef<MachineBasicBlock *>::const_iterator;
78
71
  block_iterator block_begin() const { return getBlocks().begin(); }
79
71
  block_iterator block_end() const { return getBlocks().end(); }
80
71
  inline iterator_range<block_iterator> blocks() const {
81
71
    return make_range(block_begin(), block_end());
82
71
  }
83
88
  unsigned getNumBlocks() const { return Blocks.size(); }
84
27
  std::vector<MachineBasicBlock *> &getBlocksVector() { return Blocks; }
85
86
0
  const std::vector<WebAssemblyException *> &getSubExceptions() const {
87
0
    return SubExceptions;
88
0
  }
89
264
  std::vector<WebAssemblyException *> &getSubExceptions() {
90
264
    return SubExceptions;
91
264
  }
92
0
  void addSubException(WebAssemblyException *E) { SubExceptions.push_back(E); }
93
  using iterator = typename std::vector<WebAssemblyException *>::const_iterator;
94
0
  iterator begin() const { return SubExceptions.begin(); }
95
0
  iterator end() const { return SubExceptions.end(); }
96
97
79
  void reserveBlocks(unsigned Size) { Blocks.reserve(Size); }
98
79
  void reverseBlock(unsigned From = 0) {
99
79
    std::reverse(Blocks.begin() + From, Blocks.end());
100
79
  }
101
102
  // Return the nesting level. An outermost one has depth 1.
103
8
  unsigned getExceptionDepth() const {
104
8
    unsigned D = 1;
105
8
    for (const WebAssemblyException *CurException = ParentException;
106
16
         CurException; 
CurException = CurException->ParentException8
)
107
8
      ++D;
108
8
    return D;
109
8
  }
110
111
  void print(raw_ostream &OS, unsigned Depth = 0) const;
112
  void dump() const;
113
};
114
115
raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE);
116
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;
121
122
  void discoverAndMapException(WebAssemblyException *WE,
123
                               const MachineDominatorTree &MDT,
124
                               const MachineDominanceFrontier &MDF);
125
  WebAssemblyException *getOutermostException(MachineBasicBlock *MBB) const;
126
127
public:
128
  static char ID;
129
431
  WebAssemblyExceptionInfo() : MachineFunctionPass(ID) {
130
431
    initializeWebAssemblyExceptionInfoPass(*PassRegistry::getPassRegistry());
131
431
  }
132
423
  ~WebAssemblyExceptionInfo() override { releaseMemory(); }
133
  WebAssemblyExceptionInfo(const WebAssemblyExceptionInfo &) = delete;
134
  WebAssemblyExceptionInfo &
135
  operator=(const WebAssemblyExceptionInfo &) = delete;
136
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;
142
143
0
  bool empty() const { return TopLevelExceptions.empty(); }
144
145
  // Return the innermost exception that MBB lives in. If the block is not in an
146
  // exception, null is returned.
147
10.9k
  WebAssemblyException *getExceptionFor(const MachineBasicBlock *MBB) const {
148
10.9k
    return BBMap.lookup(MBB);
149
10.9k
  }
150
151
247
  void changeExceptionFor(MachineBasicBlock *MBB, WebAssemblyException *WE) {
152
247
    if (!WE) {
153
0
      BBMap.erase(MBB);
154
0
      return;
155
0
    }
156
247
    BBMap[MBB] = WE;
157
247
  }
158
159
52
  void addTopLevelException(WebAssemblyException *WE) {
160
52
    assert(!WE->getParentException() && "Not a top level exception!");
161
52
    TopLevelExceptions.push_back(WE);
162
52
  }
163
164
  void print(raw_ostream &OS, const Module *M = nullptr) const override;
165
};
166
167
} // end namespace llvm
168
169
#endif