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(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 318