Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//- Dominators.h - Implementation of dominators tree for Clang CFG -*- 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
// This file implements the dominators tree functionality for Clang CFGs.
10
//
11
//===----------------------------------------------------------------------===//
12
 
13
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
14
#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
15
 
16
#include "clang/Analysis/AnalysisDeclContext.h"
17
#include "clang/Analysis/CFG.h"
18
#include "llvm/ADT/DepthFirstIterator.h"
19
#include "llvm/ADT/GraphTraits.h"
20
#include "llvm/ADT/iterator.h"
21
#include "llvm/Support/GenericIteratedDominanceFrontier.h"
22
#include "llvm/Support/GenericDomTree.h"
23
#include "llvm/Support/GenericDomTreeConstruction.h"
24
#include "llvm/Support/raw_ostream.h"
25
 
26
// FIXME: There is no good reason for the domtree to require a print method
27
// which accepts an LLVM Module, so remove this (and the method's argument that
28
// needs it) when that is fixed.
29
 
30
namespace llvm {
31
 
32
class Module;
33
 
34
} // namespace llvm
35
 
36
namespace clang {
37
 
38
using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>;
39
 
40
/// Dominator tree builder for Clang's CFG based on llvm::DominatorTreeBase.
41
template <bool IsPostDom>
42
class CFGDominatorTreeImpl : public ManagedAnalysis {
43
  virtual void anchor();
44
 
45
public:
46
  using DominatorTreeBase = llvm::DominatorTreeBase<CFGBlock, IsPostDom>;
47
 
48
  CFGDominatorTreeImpl() = default;
49
 
50
  CFGDominatorTreeImpl(CFG *cfg) {
51
    buildDominatorTree(cfg);
52
  }
53
 
54
  ~CFGDominatorTreeImpl() override = default;
55
 
56
  DominatorTreeBase &getBase() { return DT; }
57
 
58
  CFG *getCFG() { return cfg; }
59
 
60
  /// \returns the root CFGBlock of the dominators tree.
61
  CFGBlock *getRoot() const {
62
    return DT.getRoot();
63
  }
64
 
65
  /// \returns the root DomTreeNode, which is the wrapper for CFGBlock.
66
  DomTreeNode *getRootNode() {
67
    return DT.getRootNode();
68
  }
69
 
70
  /// Compares two dominator trees.
71
  /// \returns false if the other dominator tree matches this dominator tree,
72
  /// false otherwise.
73
  bool compare(CFGDominatorTreeImpl &Other) const {
74
    DomTreeNode *R = getRootNode();
75
    DomTreeNode *OtherR = Other.getRootNode();
76
 
77
    if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
78
      return true;
79
 
80
    if (DT.compare(Other.getBase()))
81
      return true;
82
 
83
    return false;
84
  }
85
 
86
  /// Builds the dominator tree for a given CFG.
87
  void buildDominatorTree(CFG *cfg) {
88
    assert(cfg);
89
    this->cfg = cfg;
90
    DT.recalculate(*cfg);
91
  }
92
 
93
  /// Dumps immediate dominators for each block.
94
  void dump() {
95
    llvm::errs() << "Immediate " << (IsPostDom ? "post " : "")
96
                 << "dominance tree (Node#,IDom#):\n";
97
    for (CFG::const_iterator I = cfg->begin(),
98
        E = cfg->end(); I != E; ++I) {
99
 
100
      assert(*I &&
101
             "LLVM's Dominator tree builder uses nullpointers to signify the "
102
             "virtual root!");
103
 
104
      DomTreeNode *IDom = DT.getNode(*I)->getIDom();
105
      if (IDom && IDom->getBlock())
106
        llvm::errs() << "(" << (*I)->getBlockID()
107
                     << ","
108
                     << IDom->getBlock()->getBlockID()
109
                     << ")\n";
110
      else {
111
        bool IsEntryBlock = *I == &(*I)->getParent()->getEntry();
112
        bool IsExitBlock = *I == &(*I)->getParent()->getExit();
113
 
114
        bool IsDomTreeRoot = !IDom && !IsPostDom && IsEntryBlock;
115
        bool IsPostDomTreeRoot =
116
            IDom && !IDom->getBlock() && IsPostDom && IsExitBlock;
117
 
118
        assert((IsDomTreeRoot || IsPostDomTreeRoot) &&
119
               "If the immediate dominator node is nullptr, the CFG block "
120
               "should be the exit point (since it's the root of the dominator "
121
               "tree), or if the CFG block it refers to is a nullpointer, it "
122
               "must be the entry block (since it's the root of the post "
123
               "dominator tree)");
124
 
125
        (void)IsDomTreeRoot;
126
        (void)IsPostDomTreeRoot;
127
 
128
        llvm::errs() << "(" << (*I)->getBlockID()
129
                     << "," << (*I)->getBlockID() << ")\n";
130
      }
131
    }
132
  }
133
 
134
  /// Tests whether \p A dominates \p B.
135
  /// Note a block always dominates itself.
136
  bool dominates(const CFGBlock *A, const CFGBlock *B) const {
137
    return DT.dominates(A, B);
138
  }
139
 
140
  /// Tests whether \p A properly dominates \p B.
141
  /// \returns false if \p A is the same block as \p B, otherwise whether A
142
  /// dominates B.
143
  bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const {
144
    return DT.properlyDominates(A, B);
145
  }
146
 
147
  /// \returns the nearest common dominator CFG block for CFG block \p A and \p
148
  /// B. If there is no such block then return NULL.
149
  CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
150
    return DT.findNearestCommonDominator(A, B);
151
  }
152
 
153
  const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
154
                                             const CFGBlock *B) {
155
    return DT.findNearestCommonDominator(A, B);
156
  }
157
 
158
  /// Update the dominator tree information when a node's immediate dominator
159
  /// changes.
160
  void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
161
    DT.changeImmediateDominator(N, NewIDom);
162
  }
163
 
164
  /// Tests whether \p A is reachable from the entry block.
165
  bool isReachableFromEntry(const CFGBlock *A) {
166
    return DT.isReachableFromEntry(A);
167
  }
168
 
169
  /// Releases the memory held by the dominator tree.
170
  virtual void releaseMemory() { DT.reset(); }
171
 
172
  /// Converts the dominator tree to human readable form.
173
  virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
174
    DT.print(OS);
175
  }
176
 
177
private:
178
  CFG *cfg;
179
  DominatorTreeBase DT;
180
};
181
 
182
using CFGDomTree = CFGDominatorTreeImpl</*IsPostDom*/ false>;
183
using CFGPostDomTree = CFGDominatorTreeImpl</*IsPostDom*/ true>;
184
 
185
template<> void CFGDominatorTreeImpl<true>::anchor();
186
template<> void CFGDominatorTreeImpl<false>::anchor();
187
 
188
} // end of namespace clang
189
 
190
namespace llvm {
191
namespace IDFCalculatorDetail {
192
 
193
/// Specialize ChildrenGetterTy to skip nullpointer successors.
194
template <bool IsPostDom>
195
struct ChildrenGetterTy<clang::CFGBlock, IsPostDom> {
196
  using NodeRef = typename GraphTraits<clang::CFGBlock *>::NodeRef;
197
  using ChildrenTy = SmallVector<NodeRef, 8>;
198
 
199
  ChildrenTy get(const NodeRef &N) {
200
    using OrderedNodeTy =
201
        typename IDFCalculatorBase<clang::CFGBlock, IsPostDom>::OrderedNodeTy;
202
 
203
    auto Children = children<OrderedNodeTy>(N);
204
    ChildrenTy Ret{Children.begin(), Children.end()};
205
    llvm::erase_value(Ret, nullptr);
206
    return Ret;
207
  }
208
};
209
 
210
} // end of namespace IDFCalculatorDetail
211
} // end of namespace llvm
212
 
213
namespace clang {
214
 
215
class ControlDependencyCalculator : public ManagedAnalysis {
216
  using IDFCalculator = llvm::IDFCalculatorBase<CFGBlock, /*IsPostDom=*/true>;
217
  using CFGBlockVector = llvm::SmallVector<CFGBlock *, 4>;
218
  using CFGBlockSet = llvm::SmallPtrSet<CFGBlock *, 4>;
219
 
220
  CFGPostDomTree PostDomTree;
221
  IDFCalculator IDFCalc;
222
 
223
  llvm::DenseMap<CFGBlock *, CFGBlockVector> ControlDepenencyMap;
224
 
225
public:
226
  ControlDependencyCalculator(CFG *cfg)
227
    : PostDomTree(cfg), IDFCalc(PostDomTree.getBase()) {}
228
 
229
  const CFGPostDomTree &getCFGPostDomTree() const { return PostDomTree; }
230
 
231
  // Lazily retrieves the set of control dependencies to \p A.
232
  const CFGBlockVector &getControlDependencies(CFGBlock *A) {
233
    auto It = ControlDepenencyMap.find(A);
234
    if (It == ControlDepenencyMap.end()) {
235
      CFGBlockSet DefiningBlock = {A};
236
      IDFCalc.setDefiningBlocks(DefiningBlock);
237
 
238
      CFGBlockVector ControlDependencies;
239
      IDFCalc.calculate(ControlDependencies);
240
 
241
      It = ControlDepenencyMap.insert({A, ControlDependencies}).first;
242
    }
243
 
244
    assert(It != ControlDepenencyMap.end());
245
    return It->second;
246
  }
247
 
248
  /// Whether \p A is control dependent on \p B.
249
  bool isControlDependent(CFGBlock *A, CFGBlock *B) {
250
    return llvm::is_contained(getControlDependencies(A), B);
251
  }
252
 
253
  // Dumps immediate control dependencies for each block.
254
  LLVM_DUMP_METHOD void dump() {
255
    CFG *cfg = PostDomTree.getCFG();
256
    llvm::errs() << "Control dependencies (Node#,Dependency#):\n";
257
    for (CFGBlock *BB : *cfg) {
258
 
259
      assert(BB &&
260
             "LLVM's Dominator tree builder uses nullpointers to signify the "
261
             "virtual root!");
262
 
263
      for (CFGBlock *isControlDependency : getControlDependencies(BB))
264
        llvm::errs() << "(" << BB->getBlockID()
265
                     << ","
266
                     << isControlDependency->getBlockID()
267
                     << ")\n";
268
    }
269
  }
270
};
271
 
272
} // namespace clang
273
 
274
namespace llvm {
275
 
276
//===-------------------------------------
277
/// DominatorTree GraphTraits specialization so the DominatorTree can be
278
/// iterable by generic graph iterators.
279
///
280
template <> struct GraphTraits<clang::DomTreeNode *> {
281
  using NodeRef = ::clang::DomTreeNode *;
282
  using ChildIteratorType = ::clang::DomTreeNode::const_iterator;
283
 
284
  static NodeRef getEntryNode(NodeRef N) { return N; }
285
  static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
286
  static ChildIteratorType child_end(NodeRef N) { return N->end(); }
287
 
288
  using nodes_iterator =
289
      llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>;
290
 
291
  static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
292
    return nodes_iterator(df_begin(getEntryNode(N)));
293
  }
294
 
295
  static nodes_iterator nodes_end(::clang::DomTreeNode *N) {
296
    return nodes_iterator(df_end(getEntryNode(N)));
297
  }
298
};
299
 
300
template <> struct GraphTraits<clang::CFGDomTree *>
301
    : public GraphTraits<clang::DomTreeNode *> {
302
  static NodeRef getEntryNode(clang::CFGDomTree *DT) {
303
    return DT->getRootNode();
304
  }
305
 
306
  static nodes_iterator nodes_begin(clang::CFGDomTree *N) {
307
    return nodes_iterator(df_begin(getEntryNode(N)));
308
  }
309
 
310
  static nodes_iterator nodes_end(clang::CFGDomTree *N) {
311
    return nodes_iterator(df_end(getEntryNode(N)));
312
  }
313
};
314
 
315
} // namespace llvm
316
 
317
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H