Static Value-Flow Analysis
ThreadCallGraph.h
Go to the documentation of this file.
1 //===- ThreadCallGraph.h -- Call graph considering thread fork/join-----------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2017> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * ThreadCallGraph.h
25  *
26  * Created on: Jul 7, 2014
27  * Authors: Peng Di, Yulei Sui, Ding Ye
28  */
29 
30 #ifndef RCG_H_
31 #define RCG_H_
32 
33 #include "Graphs/PTACallGraph.h"
34 
35 namespace SVF
36 {
37 
38 class SVFModule;
39 class ThreadAPI;
40 class PointerAnalysis;
45 {
46 
47 public:
51  {
52  }
54  virtual ~ThreadForkEdge()
55  {
56  }
57 
59 
60  static inline bool classof(const ThreadForkEdge*)
61  {
62  return true;
63  }
64  static inline bool classof(const PTACallGraphEdge*edge)
65  {
66  return edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge;
67  }
69 
70  virtual const std::string toString() const
71  {
72  std::string str;
73  std::stringstream rawstr(str);
74  rawstr << "ThreadForkEdge ";
75  rawstr << "CallSiteID: " << getCallSiteID();
76  rawstr << " srcNodeID " << getSrcID() << " (fun: " << getSrcNode()->getFunction()->getName() << ")";
77  rawstr << " dstNodeID " << getDstID() << " (fun: " << getDstNode()->getFunction()->getName() << ")";
78  return rawstr.str();
79  }
80 
82 };
83 
88 {
89 
90 public:
94  {
95  }
97  virtual ~ThreadJoinEdge()
98  {
99  }
100 
101  static inline bool classof(const ThreadJoinEdge*)
102  {
103  return true;
104  }
105  static inline bool classof(const PTACallGraphEdge*edge)
106  {
107  return edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge;
108  }
109 
110  virtual const std::string toString() const
111  {
112  std::string str;
113  std::stringstream rawstr(str);
114  rawstr << "ThreadJoinEdge ";
115  rawstr << "CallSiteID: " << getCallSiteID();
116  rawstr << " srcNodeID " << getSrcID() << " (fun: " << getSrcNode()->getFunction()->getName() << ")";
117  rawstr << " dstNodeID " << getDstID() << " (fun: " << getDstNode()->getFunction()->getName() << ")";
118  return rawstr.str();
119  }
120 
122 };
123 
128 {
129 
130 public:
134  {
135  }
137  virtual ~HareParForEdge()
138  {
139  }
140 
142 
143  static inline bool classof(const HareParForEdge*)
144  {
145  return true;
146  }
147  static inline bool classof(const PTACallGraphEdge*edge)
148  {
150  }
152 
154 };
155 
156 
161 {
162 
163 public:
173 
175  ThreadCallGraph(const PTACallGraph& cg);
176 
178 
181  {
182  }
183 
185 
186  static inline bool classof(const ThreadCallGraph *)
187  {
188  return true;
189  }
190  static inline bool classof(const PTACallGraph*g)
191  {
192  return g->getKind() == PTACallGraph::ThdCallGraph;
193  }
195 
197  void updateCallGraph(PointerAnalysis* pta);
199  void updateJoinEdge(PointerAnalysis* pta);
200 
201 
203 
204  inline bool hasThreadForkEdge(const CallICFGNode* cs) const
206  {
207  return callinstToThreadForkEdgesMap.find(cs) !=
209  }
210  inline ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode* cs) const
211  {
212  CallInstToForkEdgesMap::const_iterator it = callinstToThreadForkEdgesMap.find(cs);
213  assert(it != callinstToThreadForkEdgesMap.end() && "call instruction not found");
214  return it->second.begin();
215  }
216  inline ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode* cs) const
217  {
218  CallInstToForkEdgesMap::const_iterator it = callinstToThreadForkEdgesMap.find(cs);
219  assert(it != callinstToThreadForkEdgesMap.end() && "call instruction not found");
220  return it->second.end();
221  }
222 
224 
225  inline bool hasThreadJoinEdge(const CallICFGNode* cs) const
227  {
229  }
230  inline JoinEdgeSet::const_iterator getJoinEdgeBegin(const CallICFGNode* cs) const
231  {
232  CallInstToJoinEdgesMap::const_iterator it = callinstToThreadJoinEdgesMap.find(cs);
233  assert(it != callinstToThreadJoinEdgesMap.end() && "call instruction does not have a valid callee");
234  return it->second.begin();
235  }
236  inline JoinEdgeSet::const_iterator getJoinEdgeEnd(const CallICFGNode* cs) const
237  {
238  CallInstToJoinEdgesMap::const_iterator it = callinstToThreadJoinEdgesMap.find(cs);
239  assert(it != callinstToThreadJoinEdgesMap.end() && "call instruction does not have a valid callee");
240  return it->second.end();
241  }
242  inline void getJoinSites(const PTACallGraphNode* routine, InstSet& csSet)
243  {
244  for(CallInstToJoinEdgesMap::const_iterator it = callinstToThreadJoinEdgesMap.begin(), eit = callinstToThreadJoinEdgesMap.end(); it!=eit; ++it)
245  {
246  for(JoinEdgeSet::const_iterator jit = it->second.begin(), ejit = it->second.end(); jit!=ejit; ++jit)
247  {
248  if((*jit)->getDstNode() == routine)
249  {
250  csSet.insert(it->first);
251  }
252  }
253  }
254  }
256 
259  inline bool isForksite(const CallICFGNode* csInst)
260  {
261  return forksites.find(csInst) != forksites.end();
262  }
263  inline bool isJoinsite(const CallICFGNode* csInst)
264  {
265  return joinsites.find(csInst) != joinsites.end();
266  }
267  inline bool isParForSite(const CallICFGNode* csInst)
268  {
269  return parForSites.find(csInst) != parForSites.end();
270  }
272 
274 
275  inline CallSiteSet::const_iterator forksitesBegin() const
276  {
277  return forksites.begin();
278  }
279  inline CallSiteSet::const_iterator forksitesEnd() const
280  {
281  return forksites.end();
282  }
284 
286 
287  inline CallSiteSet::const_iterator joinsitesBegin() const
288  {
289  return joinsites.begin();
290  }
291  inline CallSiteSet::const_iterator joinsitesEnd() const
292  {
293  return joinsites.end();
294  }
296 
298 
299  inline CallSiteSet::const_iterator parForSitesBegin() const
300  {
301  return parForSites.begin();
302  }
303  inline CallSiteSet::const_iterator parForSitesEnd() const
304  {
305  return parForSites.end();
306  }
308 
310 
311  inline u32_t getNumOfForksite() const
312  {
313  return forksites.size();
314  }
315  inline u32_t getNumOfJoinsite() const
316  {
317  return joinsites.size();
318  }
319  inline u32_t getNumOfParForSite() const
320  {
321  return parForSites.size();
322  }
324 
326  inline ThreadAPI* getThreadAPI() const
327  {
328  return tdAPI;
329  }
330 
332 
333  inline bool addForksite(const CallICFGNode* cs)
334  {
336  return forksites.insert(cs).second;
337  }
338  inline bool addJoinsite(const CallICFGNode* cs)
339  {
341  return joinsites.insert(cs).second;
342  }
343  inline bool addParForSite(const CallICFGNode* cs)
344  {
346  return parForSites.insert(cs).second;
347  }
349 
351 
352  bool addDirectForkEdge(const CallICFGNode* cs);
353  bool addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* callee);
355 
357 
358  void addDirectJoinEdge(const CallICFGNode* cs,const CallSiteSet& forksite);
360 
361 
364  {
365  if(edge!=nullptr)
366  {
367  callinstToThreadForkEdgesMap[cs].insert(edge);
368  callinstToCallGraphEdgesMap[cs].insert(edge);
369  }
370  }
371 
374  {
375  if(edge!=nullptr)
376  {
377  callinstToThreadJoinEdgesMap[cs].insert(edge);
378  callinstToCallGraphEdgesMap[cs].insert(edge);
379  }
380  }
381 
384  {
385  if(edge!=nullptr)
386  {
387  callinstToHareParForEdgesMap[cs].insert(edge);
388  callinstToCallGraphEdgesMap[cs].insert(edge);
389  }
390  }
391 
393  inline ThreadJoinEdge* hasThreadJoinEdge(const CallICFGNode* call, PTACallGraphNode* joinFunNode, PTACallGraphNode* threadRoutineFunNode, CallSiteID csId) const
394  {
395  ThreadJoinEdge joinEdge(joinFunNode,threadRoutineFunNode, csId);
396  CallInstToJoinEdgesMap::const_iterator it = callinstToThreadJoinEdgesMap.find(call);
397  if(it != callinstToThreadJoinEdgesMap.end())
398  {
399  JoinEdgeSet::const_iterator jit = it->second.find(&joinEdge);
400  if(jit!=it->second.end())
401  return *jit;
402  }
403  return nullptr;
404  }
405 
406 private:
414 };
415 
416 } // End namespace SVF
417 
418 #endif /* RCG_H_ */
const char *const string
Definition: cJSON.h:172
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
GEdgeKind getEdgeKind() const
Definition: GenericGraph.h:89
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeID getSrcID() const
get methods of the components
Definition: GenericGraph.h:81
NodeType * getDstNode() const
Definition: GenericGraph.h:101
OrderedSet< EdgeType *, typename EdgeType::equalGEdge > GEdgeSetTy
Edge kind.
Definition: GenericGraph.h:402
HareParForEdge(PTACallGraphNode *s, PTACallGraphNode *d, CallSiteID csId)
Constructor.
virtual ~HareParForEdge()
Destructor.
static bool classof(const HareParForEdge *)
ClassOf.
GenericNode< PTACallGraphNode, HareParForEdge >::GEdgeSetTy ParForEdgeSet
static bool classof(const PTACallGraphEdge *edge)
CallSiteID getCallSiteID() const
Get direct and indirect calls.
Definition: PTACallGraph.h:83
CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap
Map a call instruction to its corresponding call edges.
Definition: PTACallGraph.h:272
CGEK getKind() const
Return type of this callgraph.
Definition: PTACallGraph.h:297
bool isForksite(const CallICFGNode *csInst)
CallSiteSet::const_iterator forksitesEnd() const
bool addIndirectForkEdge(const CallICFGNode *cs, const SVFFunction *callee)
CallSiteSet::const_iterator parForSitesBegin() const
hare_parallel_for sites iterators
bool addDirectForkEdge(const CallICFGNode *cs)
Add direct/indirect thread fork edges.
Set< CallSiteSet * > CtxSet
CallSiteSet::const_iterator forksitesBegin() const
Fork sites iterators.
CallInstToParForEdgesMap callinstToHareParForEdgesMap
Map a call instruction to its corresponding hare_parallel_for edges.
void updateJoinEdge(PointerAnalysis *pta)
Update join edge using pointer analysis results.
static bool classof(const ThreadCallGraph *)
ClassOf.
CallSiteSet::const_iterator joinsitesEnd() const
CallSiteSet::const_iterator parForSitesEnd() const
bool addForksite(const CallICFGNode *cs)
Add fork sites which directly or indirectly create a thread.
Set< const CallICFGNode * > InstSet
static bool classof(const PTACallGraph *g)
bool hasThreadJoinEdge(const CallICFGNode *cs) const
Get call graph edge via call instruction.
bool addParForSite(const CallICFGNode *cs)
CallSiteSet forksites
all thread fork sites
CallSiteSet parForSites
all parallel for sites
void addThreadJoinEdgeSetMap(const CallICFGNode *cs, ThreadJoinEdge *edge)
map call instruction to its PTACallGraphEdge map
u32_t getNumOfJoinsite() const
bool addJoinsite(const CallICFGNode *cs)
virtual ~ThreadCallGraph()
Destructor.
CallInstToForkEdgesMap callinstToThreadForkEdgesMap
Map a call instruction to its corresponding fork edges.
JoinEdgeSet::const_iterator getJoinEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
void addDirectJoinEdge(const CallICFGNode *cs, const CallSiteSet &forksite)
Add thread join edges.
bool hasThreadForkEdge(const CallICFGNode *cs) const
Get call graph edge via call instruction.
ThreadJoinEdge * hasThreadJoinEdge(const CallICFGNode *call, PTACallGraphNode *joinFunNode, PTACallGraphNode *threadRoutineFunNode, CallSiteID csId) const
has thread join edge
CallSiteSet::const_iterator joinsitesBegin() const
Join sites iterators.
ThreadForkEdge::ForkEdgeSet ForkEdgeSet
u32_t getNumOfForksite() const
Num of fork/join sites.
void getJoinSites(const PTACallGraphNode *routine, InstSet &csSet)
ThreadJoinEdge::JoinEdgeSet JoinEdgeSet
ThreadCallGraph(const PTACallGraph &cg)
Constructor.
CallSiteSet joinsites
all thread fork sites
void addHareParForEdgeSetMap(const CallICFGNode *cs, HareParForEdge *edge)
map call instruction to its PTACallGraphEdge map
void addThreadForkEdgeSetMap(const CallICFGNode *cs, ThreadForkEdge *edge)
map call instruction to its PTACallGraphEdge map
Map< const CallICFGNode *, JoinEdgeSet > CallInstToJoinEdgesMap
Map< const CallICFGNode *, ParForEdgeSet > CallInstToParForEdgesMap
HareParForEdge::ParForEdgeSet ParForEdgeSet
bool isJoinsite(const CallICFGNode *csInst)
ThreadCallGraph(ThreadCallGraph &cg)=delete
u32_t getNumOfParForSite() const
ThreadAPI * getThreadAPI() const
Thread API.
bool isParForSite(const CallICFGNode *csInst)
void updateCallGraph(PointerAnalysis *pta)
Update call graph using pointer results.
Map< const CallICFGNode *, ForkEdgeSet > CallInstToForkEdgesMap
ThreadAPI * tdAPI
Thread API.
CallInstToJoinEdgesMap callinstToThreadJoinEdgesMap
Map a call instruction to its corresponding join edges.
JoinEdgeSet::const_iterator getJoinEdgeBegin(const CallICFGNode *cs) const
static bool classof(const ThreadForkEdge *)
ClassOf.
virtual ~ThreadForkEdge()
Destructor.
virtual const std::string toString() const
GenericNode< PTACallGraphNode, ThreadForkEdge >::GEdgeSetTy ForkEdgeSet
static bool classof(const PTACallGraphEdge *edge)
ThreadForkEdge(PTACallGraphNode *s, PTACallGraphNode *d, CallSiteID csId)
Constructor.
virtual ~ThreadJoinEdge()
Destructor.
static bool classof(const ThreadJoinEdge *)
virtual const std::string toString() const
ThreadJoinEdge(PTACallGraphNode *s, PTACallGraphNode *d, CallSiteID csId)
Constructor.
GenericNode< PTACallGraphNode, ThreadJoinEdge >::GEdgeSetTy JoinEdgeSet
static bool classof(const PTACallGraphEdge *edge)
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96