1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
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/GenericDomTree.h" |
22 | #include "llvm/Support/GenericDomTreeConstruction.h" |
23 | #include "llvm/Support/raw_ostream.h" |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | namespace llvm { |
30 | |
31 | class Module; |
32 | |
33 | } |
34 | |
35 | namespace clang { |
36 | |
37 | using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>; |
38 | |
39 | |
40 | |
41 | |
42 | class DominatorTree : public ManagedAnalysis { |
43 | virtual void anchor(); |
44 | |
45 | public: |
46 | llvm::DomTreeBase<CFGBlock> *DT; |
47 | |
48 | DominatorTree() { |
49 | DT = new llvm::DomTreeBase<CFGBlock>(); |
50 | } |
51 | |
52 | ~DominatorTree() override { delete DT; } |
53 | |
54 | llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; } |
55 | |
56 | |
57 | CFGBlock *getRoot() const { |
58 | return DT->getRoot(); |
59 | } |
60 | |
61 | |
62 | |
63 | DomTreeNode *getRootNode() const { |
64 | return DT->getRootNode(); |
65 | } |
66 | |
67 | |
68 | |
69 | |
70 | bool compare(DominatorTree &Other) const { |
71 | DomTreeNode *R = getRootNode(); |
72 | DomTreeNode *OtherR = Other.getRootNode(); |
73 | |
74 | if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) |
75 | return true; |
76 | |
77 | if (DT->compare(Other.getBase())) |
78 | return true; |
79 | |
80 | return false; |
81 | } |
82 | |
83 | |
84 | |
85 | void buildDominatorTree(AnalysisDeclContext &AC) { |
86 | cfg = AC.getCFG(); |
87 | DT->recalculate(*cfg); |
88 | } |
89 | |
90 | |
91 | |
92 | void dump() { |
93 | llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; |
94 | for (CFG::const_iterator I = cfg->begin(), |
95 | E = cfg->end(); I != E; ++I) { |
96 | if(DT->getNode(*I)->getIDom()) |
97 | llvm::errs() << "(" << (*I)->getBlockID() |
98 | << "," |
99 | << DT->getNode(*I)->getIDom()->getBlock()->getBlockID() |
100 | << ")\n"; |
101 | else llvm::errs() << "(" << (*I)->getBlockID() |
102 | << "," << (*I)->getBlockID() << ")\n"; |
103 | } |
104 | } |
105 | |
106 | |
107 | |
108 | |
109 | bool dominates(const CFGBlock *A, const CFGBlock *B) const { |
110 | return DT->dominates(A, B); |
111 | } |
112 | |
113 | |
114 | |
115 | bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const { |
116 | return DT->properlyDominates(A, B); |
117 | } |
118 | |
119 | |
120 | |
121 | CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { |
122 | return DT->findNearestCommonDominator(A, B); |
123 | } |
124 | |
125 | const CFGBlock *findNearestCommonDominator(const CFGBlock *A, |
126 | const CFGBlock *B) { |
127 | return DT->findNearestCommonDominator(A, B); |
128 | } |
129 | |
130 | |
131 | |
132 | void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { |
133 | DT->changeImmediateDominator(N, NewIDom); |
134 | } |
135 | |
136 | |
137 | |
138 | bool isReachableFromEntry(const CFGBlock *A) { |
139 | return DT->isReachableFromEntry(A); |
140 | } |
141 | |
142 | |
143 | virtual void releaseMemory() { |
144 | DT->releaseMemory(); |
145 | } |
146 | |
147 | |
148 | virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const { |
149 | DT->print(OS); |
150 | } |
151 | |
152 | private: |
153 | CFG *cfg; |
154 | }; |
155 | |
156 | } |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | namespace llvm { |
163 | |
164 | template <> struct GraphTraits< ::clang::DomTreeNode* > { |
165 | using NodeRef = ::clang::DomTreeNode *; |
166 | using ChildIteratorType = ::clang::DomTreeNode::iterator; |
167 | |
168 | static NodeRef getEntryNode(NodeRef N) { return N; } |
169 | static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } |
170 | static ChildIteratorType child_end(NodeRef N) { return N->end(); } |
171 | |
172 | using nodes_iterator = |
173 | llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>; |
174 | |
175 | static nodes_iterator nodes_begin(::clang::DomTreeNode *N) { |
176 | return nodes_iterator(df_begin(getEntryNode(N))); |
177 | } |
178 | |
179 | static nodes_iterator nodes_end(::clang::DomTreeNode *N) { |
180 | return nodes_iterator(df_end(getEntryNode(N))); |
181 | } |
182 | }; |
183 | |
184 | template <> struct GraphTraits< ::clang::DominatorTree* > |
185 | : public GraphTraits< ::clang::DomTreeNode* > { |
186 | static NodeRef getEntryNode(::clang::DominatorTree *DT) { |
187 | return DT->getRootNode(); |
188 | } |
189 | |
190 | static nodes_iterator nodes_begin(::clang::DominatorTree *N) { |
191 | return nodes_iterator(df_begin(getEntryNode(N))); |
192 | } |
193 | |
194 | static nodes_iterator nodes_end(::clang::DominatorTree *N) { |
195 | return nodes_iterator(df_end(getEntryNode(N))); |
196 | } |
197 | }; |
198 | |
199 | } |
200 | |
201 | #endif |
202 | |