13 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H 14 #define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_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" 41 template <
bool IsPostDom>
43 virtual void anchor();
51 buildDominatorTree(cfg);
67 return DT.getRootNode();
77 if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
80 if (DT.compare(Other.
getBase()))
95 llvm::errs() <<
"Immediate " << (IsPostDom ?
"post " :
"")
96 <<
"dominance tree (Node#,IDom#):\n";
98 E = cfg->end(); I != E; ++I) {
101 "LLVM's Dominator tree builder uses nullpointers to signify the " 105 if (IDom && IDom->getBlock())
106 llvm::errs() <<
"(" << (*I)->getBlockID()
108 << IDom->getBlock()->getBlockID()
111 bool IsEntryBlock = *I == &(*I)->getParent()->getEntry();
112 bool IsExitBlock = *I == &(*I)->getParent()->getExit();
114 bool IsDomTreeRoot = !IDom && !IsPostDom && IsEntryBlock;
115 bool IsPostDomTreeRoot =
116 IDom && !IDom->getBlock() && IsPostDom && IsExitBlock;
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 " 126 (void)IsPostDomTreeRoot;
128 llvm::errs() <<
"(" << (*I)->getBlockID()
129 <<
"," << (*I)->getBlockID() <<
")\n";
137 return DT.dominates(A, B);
144 return DT.properlyDominates(A, B);
150 return DT.findNearestCommonDominator(A, B);
155 return DT.findNearestCommonDominator(A, B);
161 DT.changeImmediateDominator(N, NewIDom);
166 return DT.isReachableFromEntry(A);
175 virtual void print(raw_ostream &OS,
const llvm::Module* M=
nullptr)
const {
193 namespace IDFCalculatorDetail {
196 template <
bool IsPostDom>
197 struct ChildrenGetterTy<
clang::CFGBlock, IsPostDom> {
202 using OrderedNodeTy =
203 typename IDFCalculatorBase<clang::CFGBlock, IsPostDom>::OrderedNodeTy;
205 auto Children = children<OrderedNodeTy>(N);
206 ChildrenTy Ret{Children.begin(), Children.end()};
207 Ret.erase(
std::remove(Ret.begin(), Ret.end(),
nullptr), Ret.end());
218 using IDFCalculator = llvm::IDFCalculatorBase<
CFGBlock,
true>;
220 using CFGBlockSet = llvm::SmallPtrSet<CFGBlock *, 4>;
223 IDFCalculator IDFCalc;
225 llvm::DenseMap<CFGBlock *, CFGBlockVector> ControlDepenencyMap;
229 : PostDomTree(cfg), IDFCalc(PostDomTree.getBase()) {}
235 auto It = ControlDepenencyMap.find(A);
236 if (It == ControlDepenencyMap.end()) {
237 CFGBlockSet DefiningBlock = {A};
238 IDFCalc.setDefiningBlocks(DefiningBlock);
241 IDFCalc.calculate(ControlDependencies);
243 It = ControlDepenencyMap.insert({A, ControlDependencies}).first;
246 assert(It != ControlDepenencyMap.end());
252 return llvm::is_contained(getControlDependencies(A), B);
258 llvm::errs() <<
"Control dependencies (Node#,Dependency#):\n";
259 for (CFGBlock *BB : *cfg) {
262 "LLVM's Dominator tree builder uses nullpointers to signify the " 265 for (CFGBlock *isControlDependency : getControlDependencies(BB))
266 llvm::errs() <<
"(" << BB->getBlockID()
268 << isControlDependency->getBlockID()
285 namespace DomTreeBuilder {
288 SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
293 inline ClangCFGDomChildrenGetter::ResultTy ClangCFGDomChildrenGetter::Get(
295 auto RChildren = reverse(children<NodePtr>(N));
296 ResultTy Ret(RChildren.begin(), RChildren.end());
297 Ret.erase(
std::remove(Ret.begin(), Ret.end(),
nullptr), Ret.end());
302 SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
307 inline ClangCFGDomReverseChildrenGetter::ResultTy
308 ClangCFGDomReverseChildrenGetter::Get(
310 auto IChildren = inverse_children<NodePtr>(N);
311 ResultTy Ret(IChildren.begin(), IChildren.end());
312 Ret.erase(
std::remove(Ret.begin(), Ret.end(),
nullptr), Ret.end());
317 SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
322 inline ClangCFGPostDomChildrenGetter::ResultTy
323 ClangCFGPostDomChildrenGetter::Get(
325 auto RChildren = reverse(children<NodePtr>(N));
326 ResultTy Ret(RChildren.begin(), RChildren.end());
327 Ret.erase(
std::remove(Ret.begin(), Ret.end(),
nullptr), Ret.end());
332 SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
337 inline ClangCFGPostDomReverseChildrenGetter::ResultTy
338 ClangCFGPostDomReverseChildrenGetter::Get(
340 auto IChildren = inverse_children<NodePtr>(N);
341 ResultTy Ret(IChildren.begin(), IChildren.end());
342 Ret.erase(
std::remove(Ret.begin(), Ret.end(),
nullptr), Ret.end());
361 llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>;
379 return nodes_iterator(df_begin(getEntryNode(N)));
383 return nodes_iterator(df_end(getEntryNode(N)));
389 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H ::clang::DomTreeNode::iterator ChildIteratorType
The base class of a hierarchy of objects representing analyses tied to AnalysisDeclContext.
static nodes_iterator nodes_end(::clang::DomTreeNode *N)
bool isReachableFromEntry(const CFGBlock *A)
Tests whether A is reachable from the entry block.
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
const CFGBlock * findNearestCommonDominator(const CFGBlock *A, const CFGBlock *B)
CFGDominatorTreeImpl< false > CFGDomTree
static nodes_iterator nodes_end(clang::CFGDomTree *N)
bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const
Tests whether A properly dominates B.
llvm::pointer_iterator< df_iterator<::clang::DomTreeNode * > > nodes_iterator
DomTreeNode * getRootNode()
static nodes_iterator nodes_begin(::clang::DomTreeNode *N)
bool compare(CFGDominatorTreeImpl &Other) const
Compares two dominator trees.
static ChildIteratorType child_begin(NodeRef N)
CFGBlockListTy::const_iterator const_iterator
Represents a single basic block in a source-level CFG.
static ChildIteratorType child_end(NodeRef N)
llvm::DomTreeNodeBase< CFGBlock > DomTreeNode
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isControlDependent(CFGBlock *A, CFGBlock *B)
Whether A is control dependent on B.
Dominator tree builder for Clang's CFG based on llvm::DominatorTreeBase.
SemiNCAInfo< clang::CFGDomTree::DominatorTreeBase >::ChildrenGetter< false > ClangCFGDomChildrenGetter
LLVM_DUMP_METHOD void dump()
void dump()
Dumps immediate dominators for each block.
llvm::DominatorTreeBase< CFGBlock, IsPostDom > DominatorTreeBase
void buildDominatorTree(CFG *cfg)
Builds the dominator tree for a given CFG.
CFGBlock * findNearestCommonDominator(CFGBlock *A, CFGBlock *B)
SemiNCAInfo< clang::CFGDomTree::DominatorTreeBase >::ChildrenGetter< true > ClangCFGDomReverseChildrenGetter
virtual void print(raw_ostream &OS, const llvm::Module *M=nullptr) const
Converts the dominator tree to human readable form.
DominatorTreeBase & getBase()
static NodeRef getEntryNode(NodeRef N)
CFGBlock * getRoot() const
::clang::DomTreeNode * NodeRef
Dataflow Directional Tag Classes.
ControlDependencyCalculator(CFG *cfg)
static nodes_iterator nodes_begin(clang::CFGDomTree *N)
SemiNCAInfo< clang::CFGPostDomTree::DominatorTreeBase >::ChildrenGetter< true > ClangCFGPostDomReverseChildrenGetter
virtual void releaseMemory()
Releases the memory held by the dominator tree.
SemiNCAInfo< clang::CFGPostDomTree::DominatorTreeBase >::ChildrenGetter< false > ClangCFGPostDomChildrenGetter
void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom)
Update the dominator tree information when a node's immediate dominator changes.
typename GraphTraits< clang::CFGBlock >::NodeRef NodeRef
bool dominates(const CFGBlock *A, const CFGBlock *B) const
Tests whether A dominates B.
CFGDominatorTreeImpl(CFG *cfg)
const CFGPostDomTree & getCFGPostDomTree() const
static NodeRef getEntryNode(clang::CFGDomTree *DT)
const CFGBlockVector & getControlDependencies(CFGBlock *A)