Static Value-Flow Analysis
TCT.cpp
Go to the documentation of this file.
1 //===- TCT.cpp -- Thread creation tree-------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-> <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 /*
25  * TCT.cpp
26  *
27  * Created on: Jun 24, 2015
28  * Author: Yulei Sui, Peng Di
29  */
30 
31 #include "Util/Options.h"
32 #include "MTA/TCT.h"
33 #include "MTA/MTA.h"
34 
35 #include <string>
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
46 {
47  assert(inst && "null value instruction!!");
48 
51  worklist.push(inst);
52 
53  while(!worklist.empty())
54  {
55  const ICFGNode* inst = worklist.pop();
56  insts.insert(inst);
57  PTACallGraphNode* cgnode = tcg->getCallGraphNode(inst->getFun());
58  for(PTACallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
59  {
60  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
61  ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
62  {
63  if(insts.insert(*cit).second)
64  worklist.push(*cit);
65  }
66  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
67  ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
68  {
69  if(insts.insert(*cit).second)
70  worklist.push(*cit);
71  }
72  }
73  }
74 
75  for(const ICFGNode* i : insts)
76  {
77  if(i->getFun()->hasLoopInfo(i->getBB()))
78  return true;
79  }
80 
81 
82  return false;
83 }
84 
90 bool TCT::isInRecursion(const ICFGNode* inst) const
91 {
92  const SVFFunction* f = inst->getFun();
95  worklist.push(f);
96 
97  while(!worklist.empty())
98  {
99  const SVFFunction* svffun = worklist.pop();
100  visits.insert(svffun);
101  if(tcgSCC->isInCycle(tcg->getCallGraphNode(svffun)->getId()))
102  return true;
103 
104  const PTACallGraphNode* cgnode = tcg->getCallGraphNode(svffun);
105 
106  for(PTACallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
107  {
108  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
109  ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
110  {
111  const SVFFunction* caller = (*cit)->getFun();
112  if(visits.find(caller)==visits.end())
113  worklist.push(caller);
114  }
115  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
116  ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
117  {
118  const SVFFunction* caller = (*cit)->getFun();
119  if(visits.find(caller)==visits.end())
120  worklist.push(caller);
121  }
122  }
123  }
124 
125  return false;
126 
127 }
128 
133 {
134  for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->forksitesBegin(), eit = tcg->forksitesEnd(); it != eit; ++it)
135  {
136  const SVFFunction* svfun = (*it)->getParent()->getParent();
137  markRelProcs(svfun);
138 
139  for(ThreadCallGraph::ForkEdgeSet::const_iterator nit = tcg->getForkEdgeBegin(*it), neit = tcg->getForkEdgeEnd(*it); nit!=neit; nit++)
140  {
141  const PTACallGraphNode* forkeeNode = (*nit)->getDstNode();
142  candidateFuncSet.insert(forkeeNode->getFunction());
143  }
144 
145  }
146 
147  for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it != eit; ++it)
148  {
149  const SVFFunction* svfun = (*it)->getParent()->getParent();
150  markRelProcs(svfun);
151  }
152 
153  if(candidateFuncSet.empty())
154  writeWrnMsg("We didn't recognize any fork site, this is single thread program?");
155 }
156 
160 void TCT::markRelProcs(const SVFFunction* svffun)
161 {
162  PTACallGraphNode* cgnode = tcg->getCallGraphNode(svffun);
164  PTACGNodeSet visited;
165  worklist.push(cgnode);
166  visited.insert(cgnode);
167  while(!worklist.empty())
168  {
169  const PTACallGraphNode* node = worklist.pop();
170  candidateFuncSet.insert(node->getFunction());
171  for(PTACallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit!=neit; nit++)
172  {
173  const PTACallGraphNode* srcNode = (*nit)->getSrcNode();
174  if(visited.find(srcNode)==visited.end())
175  {
176  visited.insert(srcNode);
177  worklist.push(srcNode);
178  }
179  }
180  }
181 }
182 
187 {
188  PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
189  for (const auto& item: *svfirCallGraph)
190  {
191  const SVFFunction* fun = item.second->getFunction();
192  if (SVFUtil::isExtCall(fun))
193  continue;
194  PTACallGraphNode* node = tcg->getCallGraphNode(fun);
195  if (!node->hasIncomingEdge())
196  {
197  entryFuncSet.insert(fun);
198  }
199  }
200  assert(!entryFuncSet.empty() && "Can't find any function in module!");
201 }
202 
207 {
208  if (this->nodeNum == 0 )
209  return;
210 
211  FIFOWorkList<TCTNode*> worklist;
212  worklist.push(getTCTNode(0));
213 
214  while(!worklist.empty())
215  {
216  TCTNode* node = worklist.pop();
217  const CxtThread &ct = node->getCxtThread();
218 
219  if(ct.isIncycle() || ct.isInloop())
220  {
221  node->setMultiforked(true);
222  }
223  else
224  {
225  for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getInEdges().begin(), eit = node->getInEdges().end(); it != eit;
226  ++it)
227  {
228  if ((*it)->getSrcNode()->isMultiforked())
229  node->setMultiforked(true);
230  }
231  }
232  for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getOutEdges().begin(), eit = node->getOutEdges().end(); it != eit;
233  ++it)
234  {
235  worklist.push((*it)->getDstNode());
236  }
237  }
238 }
239 
240 
245 {
246  const SVFFunction* callee = cgEdge->getDstNode()->getFunction();
247 
248  CallStrCxt cxt(ctp.getContext());
249  CallStrCxt oldCxt = cxt;
250  const CallICFGNode* callNode = cs;
251  pushCxt(cxt,callNode,callee);
252 
254  {
255  CxtThreadProc newctp(ctp.getTid(),cxt,callee);
256  if(pushToCTPWorkList(newctp))
257  {
258  DBOUT(DMTA,outs() << "TCT Process CallRet old ctp --"; ctp.dump());
259  DBOUT(DMTA,outs() << "TCT Process CallRet new ctp --"; newctp.dump());
260  }
261  }
262 
263  else if(cgEdge->getEdgeKind() == PTACallGraphEdge::TDForkEdge)
264  {
266  TCTNode* spawneeNode = getOrCreateTCTNode(cxt,callNode, oldCxt, callee);
267  CxtThreadProc newctp(spawneeNode->getId(),cxt,callee);
268 
269  if(pushToCTPWorkList(newctp))
270  {
272  if(addTCTEdge(this->getGNode(ctp.getTid()), spawneeNode))
273  {
274  DBOUT(DMTA,outs() << "Add TCT Edge from thread " << ctp.getTid() << " ";
275  this->getGNode(ctp.getTid())->getCxtThread().dump();
276  outs() << " to thread " << spawneeNode->getId() << " ";
277  spawneeNode->getCxtThread().dump();
278  outs() << "\n" );
279  }
280  DBOUT(DMTA,outs() << "TCT Process Fork old ctp --"; ctp.dump());
281  DBOUT(DMTA,outs() << "TCT Process Fork new ctp --"; newctp.dump());
282  }
283  }
284 }
285 
290 bool TCT::isJoinMustExecutedInLoop(const LoopBBs& lp,const ICFGNode* join)
291 {
292  assert(!lp.empty() && "this is not a loop, empty basic block");
293  const SVFFunction* svffun = join->getFun();
294  const SVFBasicBlock* loopheadbb = svffun->getLoopHeader(lp);
295  const SVFBasicBlock* joinbb = join->getBB();
296  assert(loopheadbb->getParent()==joinbb->getParent() && "should inside same function");
297 
298  for (const SVFBasicBlock* svf_scc_bb : loopheadbb->getSuccessors())
299  {
300  if(svffun->loopContainsBB(lp,svf_scc_bb))
301  {
302  if(svffun->dominate(joinbb,svf_scc_bb)==false)
303  return false;
304  }
305  }
306 
307  return true;
308 }
309 
315 {
316  for(ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it!=eit; ++it)
317  {
318  const ICFGNode* join = *it;
319  const SVFFunction* svffun = join->getFun();
320  const SVFBasicBlock* svfbb = join->getBB();
321 
322  if(svffun->hasLoopInfo(svfbb))
323  {
324  const LoopBBs& lp = svffun->getLoopInfo(svfbb);
325  if(!lp.empty() && isJoinMustExecutedInLoop(lp,join))
326  {
327  joinSiteToLoopMap[join] = lp;
328  }
329  }
330 
331  if(isInRecursion(join))
332  inRecurJoinSites.insert(join);
333  }
334 }
335 
340 {
341  for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
342  {
343  if(bb->getParent()->getLoopHeader(it->second) == bb)
344  return true;
345  }
346 
347  return false;
348 }
349 
354 {
355  for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
356  {
357  std::vector<const SVFBasicBlock*> exitbbs;
358  it->first->getFun()->getExitBlocksOfLoop(it->first->getBB(),exitbbs);
359  while(!exitbbs.empty())
360  {
361  const SVFBasicBlock* eb = exitbbs.back();
362  exitbbs.pop_back();
363  if(eb == bb)
364  return true;
365  }
366  }
367 
368  return false;
369 }
370 
375 {
376  const SVFFunction* fun = bb->getParent();
377  return fun->getLoopInfo(bb);
378 }
379 
384 {
385 
386  markRelProcs();
387 
388  collectLoopInfoForJoin();
389 
390  // the fork site of main function is initialized with nullptr.
391  // the context of main is initialized with empty
392  // start routine is empty
393 
394  collectEntryFunInCallGraph();
395  for (FunSet::iterator it=entryFuncSet.begin(), eit=entryFuncSet.end(); it!=eit; ++it)
396  {
397  if (!isCandidateFun(*it))
398  continue;
399  CallStrCxt cxt;
400  TCTNode* mainTCTNode = getOrCreateTCTNode(cxt, nullptr, cxt, *it);
401  CxtThreadProc t(mainTCTNode->getId(), cxt, *it);
402  pushToCTPWorkList(t);
403  }
404 
405  while(!ctpList.empty())
406  {
407  CxtThreadProc ctp = popFromCTPWorkList();
408  PTACallGraphNode* cgNode = tcg->getCallGraphNode(ctp.getProc());
409  if(isCandidateFun(cgNode->getFunction()) == false)
410  continue;
411 
412  for(PTACallGraphNode::const_iterator nit = cgNode->OutEdgeBegin(), neit = cgNode->OutEdgeEnd(); nit!=neit; nit++)
413  {
414  const PTACallGraphEdge* cgEdge = (*nit);
415 
416  for(PTACallGraphEdge::CallInstSet::const_iterator cit = cgEdge->directCallsBegin(),
417  ecit = cgEdge->directCallsEnd(); cit!=ecit; ++cit)
418  {
419  DBOUT(DMTA,outs() << "\nTCT handling direct call:" << **cit << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
420  handleCallRelation(ctp,cgEdge,*cit);
421  }
422  for(PTACallGraphEdge::CallInstSet::const_iterator ind = cgEdge->indirectCallsBegin(),
423  eind = cgEdge->indirectCallsEnd(); ind!=eind; ++ind)
424  {
425  DBOUT(DMTA,outs() << "\nTCT handling indirect call:" << **ind << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
426  handleCallRelation(ctp,cgEdge,*ind);
427  }
428  }
429  }
430 
431  collectMultiForkedThreads();
432 
433  if (Options::TCTDotGraph())
434  {
435  print();
436  dump("tct");
437  }
438 
439 }
440 
444 void TCT::pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const SVFFunction* callee)
445 {
446 
447  const SVFFunction* caller = call->getFun();
448  CallSiteID csId = tcg->getCallSiteID(call, callee);
449 
451  if(isCandidateFun(caller) == false)
452  return;
453 
454  if(inSameCallGraphSCC(tcg->getCallGraphNode(caller),tcg->getCallGraphNode(callee))==false)
455  {
456  pushCxt(cxt,csId);
457  DBOUT(DMTA,dumpCxt(cxt));
458  }
459 }
460 
461 
465 bool TCT::matchCxt(CallStrCxt& cxt, const CallICFGNode* call, const SVFFunction* callee)
466 {
467 
468  const SVFFunction* caller = call->getFun();
469  CallSiteID csId = tcg->getCallSiteID(call, callee);
470 
472  if(isCandidateFun(caller) == false)
473  return true;
474 
476  if(cxt.empty())
477  return true;
478 
479  if(inSameCallGraphSCC(tcg->getCallGraphNode(caller),tcg->getCallGraphNode(callee))==false)
480  {
481  if(cxt.back() == csId)
482  cxt.pop_back();
483  else
484  return false;
485  DBOUT(DMTA,dumpCxt(cxt));
486  }
487 
488  return true;
489 }
490 
491 
496 {
497  std::string str;
498  std::stringstream rawstr(str);
499  rawstr << "[:";
500  for(CallStrCxt::const_iterator it = cxt.begin(), eit = cxt.end(); it!=eit; ++it)
501  {
502  rawstr << " ' "<< *it << " ' ";
503  rawstr << (tcg->getCallSite(*it))->valueOnlyToString();
504  rawstr << " call " << tcg->getCallSite(*it)->getCaller()->getName() << "-->" << tcg->getCalleeOfCallSite(*it)->getName() << ", \n";
505  }
506  rawstr << " ]";
507  outs() << "max cxt = " << cxt.size() << rawstr.str() << "\n";
508 }
509 
513 void TCT::dump(const std::string& filename)
514 {
515  if (Options::TCTDotGraph())
516  GraphPrinter::WriteGraphToFile(outs(), filename, this);
517 }
518 
522 void TCT::print() const
523 {
524  for(TCT::const_iterator it = this->begin(), eit = this->end(); it!=eit; ++it)
525  {
526  outs() << "TID " << it->first << "\t";
527  it->second->getCxtThread().dump();
528  }
529 }
530 
535 {
536  TCTEdge edge(src, dst, kind);
537  TCTEdge* outEdge = src->hasOutgoingEdge(&edge);
538  TCTEdge* inEdge = dst->hasIncomingEdge(&edge);
539  if (outEdge && inEdge)
540  {
541  assert(outEdge == inEdge && "edges not match");
542  return outEdge;
543  }
544  else
545  return nullptr;
546 }
547 
552 {
553  for (TCTEdge::ThreadCreateEdgeSet::const_iterator iter = src->OutEdgeBegin(); iter != src->OutEdgeEnd(); ++iter)
554  {
555  TCTEdge* edge = (*iter);
556  if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
557  return edge;
558  }
559  return nullptr;
560 }
561 namespace SVF
562 {
563 
567 template<>
569 {
570 
571  typedef TCTNode NodeType;
573  DOTGraphTraits(bool isSimple = false) :
574  DefaultDOTGraphTraits(isSimple)
575  {
576  }
577 
579  static std::string getGraphName(TCT *graph)
580  {
581  return "Thread Create Tree";
582  }
584  static std::string getNodeLabel(TCTNode *node, TCT *graph)
585  {
586  return std::to_string(node->getId());
587  }
588 
590  {
591  std::string attr;
592  if (node->isInloop())
593  {
594  attr.append(" style=filled fillcolor=red");
595  }
596  else if (node->isIncycle())
597  {
598  attr.append(" style=filled fillcolor=yellow");
599  }
600  return attr;
601  }
602 
603  template<class EdgeIter>
604  static std::string getEdgeAttributes(TCTNode *node, EdgeIter EI, TCT *csThreadTree)
605  {
606 
607  TCTEdge* edge = csThreadTree->getGraphEdge(node, *EI, TCTEdge::ThreadCreateEdge);
608  (void)edge; // Suppress warning of unused variable under release build
609  assert(edge && "No edge found!!");
611  return "color=black";
612  }
613 };
614 } // End namespace llvm
615 
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define DMTA
Definition: SVFType.h:505
static unsigned char * print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks)
Definition: cJSON.cpp:1189
cJSON * item
Definition: cJSON.h:222
const char *const string
Definition: cJSON.h:172
const CallStrCxt & getContext() const
Return current context.
Definition: CxtStmt.h:332
const SVFFunction * getProc() const
Return current procedure.
Definition: CxtStmt.h:327
NodeID getTid() const
Return current thread id.
Definition: CxtStmt.h:412
void dump() const
Dump CxtThreadProc.
Definition: CxtStmt.h:449
bool isInloop() const
Definition: CxtStmt.h:264
bool isIncycle() const
Definition: CxtStmt.h:272
void dump() const
Dump CxtThread.
Definition: CxtStmt.h:279
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
GEdgeKind getEdgeKind() const
Definition: GenericGraph.h:89
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeType * getDstNode() const
Definition: GenericGraph.h:101
IDToNodeMapTy::const_iterator const_iterator
Definition: GenericGraph.h:607
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
Definition: GenericGraph.h:442
bool hasOutgoingEdge() const
Definition: GenericGraph.h:446
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
GEdgeSetTy::iterator iterator
Definition: GenericGraph.h:405
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
iterator InEdgeBegin()
Definition: GenericGraph.h:462
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
iterator InEdgeEnd()
Definition: GenericGraph.h:466
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
Definition: GraphPrinter.h:56
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition: ICFGNode.h:76
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition: ICFGNode.h:82
static const Option< bool > TCTDotGraph
Definition: Options.h:166
CallInstSet::const_iterator indirectCallsEnd() const
Definition: PTACallGraph.h:135
CallInstSet::const_iterator directCallsBegin() const
Iterators for direct and indirect callsites.
Definition: PTACallGraph.h:122
CallInstSet::const_iterator directCallsEnd() const
Definition: PTACallGraph.h:126
CallInstSet::const_iterator indirectCallsBegin() const
Definition: PTACallGraph.h:131
const SVFFunction * getFunction() const
Get function of this call node.
Definition: PTACallGraph.h:198
PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator
Definition: PTACallGraph.h:180
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const std::vector< const SVFBasicBlock * > & getSuccessors() const
Definition: SVFValue.h:606
const ICFGNode * back() const
Definition: SVFValue.h:600
const SVFFunction * getParent() const
Definition: SVFValue.h:584
bool dominate(const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const
Definition: SVFValue.h:505
bool loopContainsBB(const BBList &lp, const SVFBasicBlock *bb) const
Definition: SVFValue.h:485
const SVFBasicBlock * getLoopHeader(const BBList &lp) const
Definition: SVFValue.h:480
bool hasLoopInfo(const SVFBasicBlock *bb) const
Definition: SVFValue.h:470
const LoopBBs & getLoopInfo(const SVFBasicBlock *bb) const
Definition: SVFValue.h:475
PTACallGraph * getCallGraph()
Definition: SVFIR.h:192
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
@ ThreadCreateEdge
Definition: TCT.h:55
void setMultiforked(bool value)
Definition: TCT.h:116
const CxtThread & getCxtThread() const
Get CxtThread.
Definition: TCT.h:101
bool isIncycle() const
Definition: TCT.h:112
bool isInloop() const
inloop, incycle attributes
Definition: TCT.h:108
Definition: TCT.h:154
bool isInRecursion(const ICFGNode *inst) const
Whether an instruction is in a recursion.
Definition: TCT.cpp:90
void collectLoopInfoForJoin()
Handle join site in loop.
Definition: TCT.cpp:314
void collectEntryFunInCallGraph()
Get entry functions that are neither called by other functions nor extern functions.
Definition: TCT.cpp:186
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition: TCT.cpp:444
const LoopBBs & getLoop(const ICFGNode *inst)
Get loop for an instruction.
void dump(const std::string &filename)
Dump the graph.
Definition: TCT.cpp:513
TCTEdge * getGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind)
Get call graph edge via nodes.
Definition: TCT.cpp:551
bool isInLoopInstruction(const ICFGNode *inst)
Multi-forked threads.
Definition: TCT.cpp:45
bool isJoinMustExecutedInLoop(const LoopBBs &lp, const ICFGNode *join)
Return true if a join instruction must be executed inside a loop.
Definition: TCT.cpp:290
void markRelProcs()
Mark relevant procedures that are backward reachable from any fork/join site.
Definition: TCT.cpp:132
void handleCallRelation(CxtThreadProc &ctp, const PTACallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
Definition: TCT.cpp:244
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition: TCT.cpp:465
void dumpCxt(CallStrCxt &cxt)
Dump calling context.
Definition: TCT.cpp:495
bool isLoopHeaderOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is a loop head of a inloop join site.
Definition: TCT.cpp:339
void build()
Build TCT.
Definition: TCT.cpp:383
void print() const
Print TCT information.
Definition: TCT.cpp:522
void collectMultiForkedThreads()
Definition: TCT.cpp:206
TCTEdge * hasGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind) const
Whether we have already created this call graph edge.
Definition: TCT.cpp:534
bool isLoopExitOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is an exit of a inloop join site.
Definition: TCT.cpp:353
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition: TCT.h:157
Set< const PTACallGraphNode * > PTACGNodeSet
Definition: TCT.h:163
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
void dump(const SparseBitVector< ElementSize > &LHS, std::ostream &out)
std::vector< u32_t > CallStrCxt
Definition: GeneralType.h:122
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96
static std::string getEdgeAttributes(TCTNode *node, EdgeIter EI, TCT *csThreadTree)
Definition: TCT.cpp:604
NodeType::iterator ChildIteratorType
Definition: TCT.cpp:572
static std::string getGraphName(TCT *graph)
Return name of the graph.
Definition: TCT.cpp:579
static std::string getNodeAttributes(TCTNode *node, TCT *tct)
Definition: TCT.cpp:589
static std::string getNodeLabel(TCTNode *node, TCT *graph)
Return function name;.
Definition: TCT.cpp:584
DOTGraphTraits(bool isSimple=false)
Definition: TCT.cpp:573