Static Value-Flow Analysis
MHP.cpp
Go to the documentation of this file.
1 //===- MHP.cpp -- May-happen-in-parallel analysis-------------//
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  * MHP.cpp
25  *
26  * Created on: Jan 21, 2014
27  * Author: Yulei Sui, Peng Di
28  */
29 
30 #include "Util/Options.h"
31 #include "MTA/MHP.h"
32 #include "MTA/MTA.h"
33 #include "MTA/LockAnalysis.h"
34 #include "Util/SVFUtil.h"
35 #include "Util/PTAStat.h"
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
40 
44 MHP::MHP(TCT* t) : tcg(t->getThreadCallGraph()), tct(t), numOfTotalQueries(0), numOfMHPQueries(0),
45  interleavingTime(0), interleavingQueriesTime(0)
46 {
47  fja = new ForkJoinAnalysis(tct);
49 }
50 
55 {
56  delete fja;
57 }
58 
63 {
64  DBOUT(DGENERAL, outs() << pasMsg("MHP interleaving analysis\n"));
65  DBOUT(DMTA, outs() << pasMsg("MHP interleaving analysis\n"));
66  DOTIMESTAT(double interleavingStart = PTAStat::getClk(true));
68  DOTIMESTAT(double interleavingEnd = PTAStat::getClk(true));
69  DOTIMESTAT(interleavingTime += (interleavingEnd - interleavingStart) / TIMEINTERVAL);
70 }
71 
76 {
77  for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
78  {
79  const CxtThread& ct = tpair.second->getCxtThread();
80  NodeID rootTid = tpair.first;
81  const SVFFunction* routine = tct->getStartRoutineOfCxtThread(ct);
82  const ICFGNode* svfInst = routine->getEntryBlock()->front();
83  CxtThreadStmt rootcts(rootTid, ct.getContext(), svfInst);
84 
85  addInterleavingThread(rootcts, rootTid);
86  updateAncestorThreads(rootTid);
87  updateSiblingThreads(rootTid);
88 
89  while (!cxtStmtList.empty())
90  {
92  const ICFGNode* curInst = cts.getStmt();
93  DBOUT(DMTA, outs() << "-----\nMHP analysis root thread: " << rootTid << " ");
94  DBOUT(DMTA, cts.dump());
95  DBOUT(DMTA, outs() << "current thread interleaving: < ");
97  DBOUT(DMTA, outs() << " >\n-----\n");
98 
100  if (!tct->isCandidateFun(curInst->getFun()))
101  {
103  }
105  else
106  {
107  if (isTDFork(curInst))
108  {
109  handleFork(cts, rootTid);
110  }
111  else if (isTDJoin(curInst))
112  {
113  handleJoin(cts, rootTid);
114  }
115  else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
116  {
117  handleCall(cts, rootTid);
119  if (!tct->isCandidateFun(getCallee(SVFUtil::cast<CallICFGNode>(curInst), callees)))
120  handleIntra(cts);
121  }
122  else if (isRetInstNode(curInst))
123  {
124  handleRet(cts);
125  }
126  else
127  {
128  handleIntra(cts);
129  }
130  }
131  }
132  }
133 
136 
139 }
140 
145 {
146  SVFModule* module = tct->getSVFModule();
147  for (const SVFFunction* fun : module->getFunctionSet())
148  {
149  if (!tct->isCandidateFun(fun) && !isExtCall(fun))
150  {
151  const ICFGNode* entryNode = fun->getEntryBlock()->front();
152 
153  if (!hasThreadStmtSet(entryNode))
154  continue;
155 
156  const CxtThreadStmtSet& tsSet = getThreadStmtSet(entryNode);
157 
158  for (const CxtThreadStmt& cts : tsSet)
159  {
160  const CallStrCxt& curCxt = cts.getContext();
161 
162  for (const SVFBasicBlock* svfbb : fun->getBasicBlockList())
163  {
164  for (const ICFGNode* curNode : svfbb->getICFGNodeList())
165  {
166  if (curNode == entryNode)
167  continue;
168  CxtThreadStmt newCts(cts.getTid(), curCxt, curNode);
170  instToTSMap[curNode].insert(newCts);
171  }
172  }
173  }
174  }
175  }
176 }
177 
182 {
183  const ICFGNode* curInst = cts.getStmt();
184  const SVFFunction* curfun = curInst->getFun();
185  assert((curInst == curfun->getEntryBlock()->front()) && "curInst is not the entry of non candidate function.");
186  const CallStrCxt& curCxt = cts.getContext();
187  PTACallGraphNode* node = tcg->getCallGraphNode(curfun);
188  for (PTACallGraphNode::const_iterator nit = node->OutEdgeBegin(), neit = node->OutEdgeEnd(); nit != neit; nit++)
189  {
190  const SVFFunction* callee = (*nit)->getDstNode()->getFunction();
191  if (!isExtCall(callee))
192  {
193  const ICFGNode* calleeInst = callee->getEntryBlock()->front();
194  CxtThreadStmt newCts(cts.getTid(), curCxt, calleeInst);
195  addInterleavingThread(newCts, cts);
196  }
197  }
198 }
199 
203 void MHP::handleFork(const CxtThreadStmt& cts, NodeID rootTid)
204 {
205 
206  const ICFGNode* call = cts.getStmt();
207  const CallStrCxt& curCxt = cts.getContext();
208 
209  assert(isTDFork(call));
210  const CallICFGNode* cbn = cast<CallICFGNode>(call);
212  {
213 
214  for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = tcg->getForkEdgeBegin(cbn),
215  ecgIt = tcg->getForkEdgeEnd(cbn);
216  cgIt != ecgIt; ++cgIt)
217  {
218  const SVFFunction* svfroutine = (*cgIt)->getDstNode()->getFunction();
219  CallStrCxt newCxt = curCxt;
220  pushCxt(newCxt, cbn, svfroutine);
221  const ICFGNode* stmt = svfroutine->getEntryBlock()->front();
222  CxtThread ct(newCxt, call);
223  CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
224  addInterleavingThread(newcts, cts);
225  }
226  }
227  handleIntra(cts);
228 }
229 
233 void MHP::handleJoin(const CxtThreadStmt& cts, NodeID rootTid)
234 {
235 
236  const CallStrCxt& curCxt = cts.getContext();
237 
238  assert(isTDJoin(cts.getStmt()));
239 
240  const CallICFGNode* call = SVFUtil::cast<CallICFGNode>(cts.getStmt());
241 
242  NodeBS joinedTids = getDirAndIndJoinedTid(curCxt, call);
243  if (!joinedTids.empty())
244  {
245  if (fja->hasJoinLoop(call))
246  {
247  std::vector<const SVFBasicBlock*> exitbbs;
248  call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
249  while (!exitbbs.empty())
250  {
251  const SVFBasicBlock* eb = exitbbs.back();
252  exitbbs.pop_back();
253  const ICFGNode* svfEntryInst = eb->front();
254  CxtThreadStmt newCts(cts.getTid(), curCxt, svfEntryInst);
255  addInterleavingThread(newCts, cts);
256  if (hasJoinInSymmetricLoop(curCxt, call))
257  rmInterleavingThread(newCts, joinedTids, call);
258  }
259  }
260  else
261  {
262  rmInterleavingThread(cts, joinedTids, call);
263  DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << " for thread " << rootTid << "\n");
264  }
265  }
268  else
269  {
270  if (fja->hasJoinLoop(call))
271  {
272  std::vector<const SVFBasicBlock*> exitbbs;
273  call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
274  while (!exitbbs.empty())
275  {
276  const SVFBasicBlock* eb = exitbbs.back();
277  exitbbs.pop_back();
278  const ICFGNode* svfEntryInst = eb->front();
279  CxtThreadStmt newCts(cts.getTid(), cts.getContext(), svfEntryInst);
280  addInterleavingThread(newCts, cts);
281  }
282  }
283  }
284  handleIntra(cts);
285 }
286 
290 void MHP::handleCall(const CxtThreadStmt& cts, NodeID rootTid)
291 {
292 
293  const ICFGNode* call = cts.getStmt();
294  const CallStrCxt& curCxt = cts.getContext();
295  const CallICFGNode* cbn = cast<CallICFGNode>(call);
297  {
298  for (PTACallGraph::CallGraphEdgeSet::const_iterator cgIt = tcg->getCallEdgeBegin(cbn),
299  ecgIt = tcg->getCallEdgeEnd(cbn);
300  cgIt != ecgIt; ++cgIt)
301  {
302 
303  const SVFFunction* svfcallee = (*cgIt)->getDstNode()->getFunction();
304  if (isExtCall(svfcallee))
305  continue;
306  CallStrCxt newCxt = curCxt;
307  const CallICFGNode* callicfgnode = SVFUtil::cast<CallICFGNode>(call);
308  pushCxt(newCxt, callicfgnode, svfcallee);
309  const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
310  CxtThreadStmt newCts(cts.getTid(), newCxt, svfEntryInst);
311  addInterleavingThread(newCts, cts);
312  }
313  }
314 }
315 
320 {
321  PTACallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
322  for (PTACallGraphEdge* edge : curFunNode->getInEdges())
323  {
324  if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
325  continue;
326  for (PTACallGraphEdge::CallInstSet::const_iterator cit = (edge)->directCallsBegin(),
327  ecit = (edge)->directCallsEnd();
328  cit != ecit; ++cit)
329  {
330  CallStrCxt newCxt = cts.getContext();
331  if (matchCxt(newCxt, *cit, curFunNode->getFunction()))
332  {
333  for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
334  {
335  if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
336  {
337  CxtThreadStmt newCts(cts.getTid(), newCxt, outEdge->getDstNode());
338  addInterleavingThread(newCts, cts);
339  }
340  }
341  }
342  }
343  for (PTACallGraphEdge::CallInstSet::const_iterator cit = (edge)->indirectCallsBegin(),
344  ecit = (edge)->indirectCallsEnd();
345  cit != ecit; ++cit)
346  {
347  CallStrCxt newCxt = cts.getContext();
348  if (matchCxt(newCxt, *cit, curFunNode->getFunction()))
349  {
350  for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
351  {
352  if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
353  {
354  CxtThreadStmt newCts(cts.getTid(), newCxt, outEdge->getDstNode());
355  addInterleavingThread(newCts, cts);
356  }
357  }
358  }
359  }
360  }
361 }
362 
367 {
368 
369  for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
370  {
371  if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
372  {
373  CxtThreadStmt newCts(cts.getTid(), cts.getContext(), outEdge->getDstNode());
374  addInterleavingThread(newCts, cts);
375  }
376  }
377 }
378 
383 {
384  NodeBS tds = tct->getAncestorThread(curTid);
385  DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
386  DBOUT(DMTA, dumpSet(tds));
387  DBOUT(DMTA, outs() << "\n");
388  tds.set(curTid);
389 
390  for (const unsigned i : tds)
391  {
392  const CxtThread& ct = tct->getTCTNode(i)->getCxtThread();
393  if (const ICFGNode* forkInst = ct.getThread())
394  {
395  CallStrCxt forkSiteCxt = tct->getCxtOfCxtThread(ct);
396  for(const ICFGEdge* outEdge : forkInst->getOutEdges())
397  {
398  if(outEdge->getDstNode()->getFun() == forkInst->getFun())
399  {
400  CxtThreadStmt cts(tct->getParentThread(i), forkSiteCxt, outEdge->getDstNode());
401  addInterleavingThread(cts, curTid);
402  }
403  }
404  }
405  }
406 }
407 
419 {
420  NodeBS tds = tct->getAncestorThread(curTid);
421  tds.set(curTid);
422  for (const unsigned tid : tds)
423  {
424  NodeBS siblingTds = tct->getSiblingThread(tid);
425  for (const unsigned stid : siblingTds)
426  {
427  if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
428  continue;
429 
430  const CxtThread& ct = tct->getTCTNode(stid)->getCxtThread();
431  const SVFFunction* routine = tct->getStartRoutineOfCxtThread(ct);
432  const ICFGNode* stmt = routine->getEntryBlock()->front();
433  CxtThreadStmt cts(stid, ct.getContext(), stmt);
434  addInterleavingThread(cts, curTid);
435  }
436 
437  DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
438  DBOUT(DMTA, dumpSet(siblingTds));
439  DBOUT(DMTA, outs() << "\n");
440  }
441 }
442 
446 bool MHP::isRecurFullJoin(NodeID parentTid, NodeID curTid)
447 {
448  if (parentTid == curTid)
449  return true;
450 
451  const TCTNode* curNode = tct->getTCTNode(curTid);
453  worklist.push(curNode);
454  while (!worklist.empty())
455  {
456  const TCTNode* node = worklist.pop();
457  for (TCTEdge* edge : node->getInEdges())
458  {
459  NodeID srcID = edge->getSrcID();
460  if (fja->isFullJoin(srcID, node->getId()))
461  {
462  if (srcID == parentTid)
463  return true;
464  else
465  worklist.push(edge->getSrcNode());
466  }
467  else
468  {
469  return false;
470  }
471  }
472  }
473  return false;
474 }
475 
481 bool MHP::isMustJoin(NodeID curTid, const ICFGNode* joinsite)
482 {
483  const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
484  assert(call && isTDJoin(call) && "not a join site!");
485  return !isMultiForkedThread(curTid) && !tct->isJoinSiteInRecursion(call);
486 }
487 
492 {
493  CxtStmt cs(cxt, call);
494  return fja->getDirAndIndJoinedTid(cs);
495 }
496 
500 bool MHP::hasJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
501 {
502  CxtStmt cs(cxt, call);
503  return fja->hasJoinInSymmetricLoop(cs);
504 }
505 
507 const MHP::LoopBBs& MHP::getJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
508 {
509  CxtStmt cs(cxt, call);
510  return fja->getJoinInSymmetricLoop(cs);
511 }
512 
516 bool MHP::isHBPair(NodeID tid1, NodeID tid2)
517 {
518  return fja->isHBPair(tid1, tid2);
519 }
520 
522 {
523  PTACallGraphNode* cgnode = tcg->getCallGraphNode(fun);
525  TCT::PTACGNodeSet visited;
526  worklist.push(cgnode);
527  visited.insert(cgnode);
528  while (!worklist.empty())
529  {
530  const PTACallGraphNode* node = worklist.pop();
531  if ("main" == node->getFunction()->getName())
532  return true;
533  for (PTACallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
534  {
535  const PTACallGraphNode* srcNode = (*nit)->getSrcNode();
536  if (visited.find(srcNode) == visited.end())
537  {
538  visited.insert(srcNode);
539  worklist.push(srcNode);
540  }
541  }
542  }
543  return false;
544 }
545 
557 {
558 
560  if (!hasThreadStmtSet(i1) || !hasThreadStmtSet(i2))
561  return false;
562 
563  const CxtThreadStmtSet& tsSet1 = getThreadStmtSet(i1);
564  const CxtThreadStmtSet& tsSet2 = getThreadStmtSet(i2);
565  for (const CxtThreadStmt& ts1 : tsSet1)
566  {
567  NodeBS l1 = getInterleavingThreads(ts1);
568  for (const CxtThreadStmt& ts2 : tsSet2)
569  {
570  NodeBS l2 = getInterleavingThreads(ts2);
571  if (ts1.getTid() != ts2.getTid())
572  {
573  if (l1.test(ts2.getTid()) && l2.test(ts1.getTid()))
574  {
575  numOfMHPQueries++;
576  return true;
577  }
578  }
579  else
580  {
581  if (isMultiForkedThread(ts1.getTid()))
582  {
583  numOfMHPQueries++;
584  return true;
585  }
586  }
587  }
588  }
589  return false;
590 }
591 
593 {
594  if (!tct->isCandidateFun(i1->getFun()) && !tct->isCandidateFun(i2->getFun()))
595  {
596  FuncPair funpair = std::make_pair(i1->getFun(), i2->getFun());
597  FuncPairToBool::const_iterator it = nonCandidateFuncMHPRelMap.find(funpair);
598  if (it == nonCandidateFuncMHPRelMap.end())
599  {
600  bool mhp = mayHappenInParallelInst(i1, i2);
601  nonCandidateFuncMHPRelMap[funpair] = mhp;
602  return mhp;
603  }
604  else
605  {
606  if (it->second)
607  numOfMHPQueries++;
608  return it->second;
609  }
610  }
611  return mayHappenInParallelInst(i1, i2);
612 }
613 
614 bool MHP::mayHappenInParallel(const ICFGNode* i1, const ICFGNode* i2)
615 {
617 
618  DOTIMESTAT(double queryStart = PTAStat::getClk(true));
619  bool mhp = mayHappenInParallelCache(i1, i2);
620  DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
621  DOTIMESTAT(interleavingQueriesTime += (queryEnd - queryStart) / TIMEINTERVAL);
622 
623  return mhp;
624 }
625 
627 {
628  if (!hasThreadStmtSet(i1) || !hasThreadStmtSet(i2))
629  return true;
630 
631  const CxtThreadStmtSet& tsSet1 = getThreadStmtSet(i1);
632  const CxtThreadStmtSet& tsSet2 = getThreadStmtSet(i2);
633  for (const CxtThreadStmt&ts1 : tsSet1)
634  {
635  for (const CxtThreadStmt& ts2 : tsSet2)
636  {
637  if (ts1.getTid() != ts2.getTid() || isMultiForkedThread(ts1.getTid()))
638  return false;
639  }
640  }
641  return true;
642 }
643 
648 {
649  for (const auto& pair : threadStmtToTheadInterLeav)
650  {
651  outs() << "( t" << pair.first.getTid()
652  << pair.first.getStmt()->toString() << " ) ==> [";
653  for (unsigned i : pair.second)
654  {
655  outs() << " " << i << " ";
656  }
657  outs() << "]\n";
658  }
659 }
660 
668 {
669  // typedef Set<const ICFGNode*> CallInstSet;
670  // typedef Map<const SVFFunction*, CallInstSet> FunToFJSites;
671  // FunToFJSites funToFJSites;
672 
673  // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->forksitesBegin(),
674  // eit = tct->getThreadCallGraph()->forksitesEnd();
675  // it != eit; ++it)
676  // {
677  // const ICFGNode* fork = *it;
678  // funToFJSites[fork->getFun()].insert(fork);
679  // }
680 
681  // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->joinsitesBegin(),
682  // eit = tct->getThreadCallGraph()->joinsitesEnd();
683  // it != eit; ++it)
684  // {
685  // const ICFGNode* join = *it;
686  // funToFJSites[join->getFun()].insert(join);
687  // }
688 
689  // for(FunToFJSites::const_iterator it = funToFJSites.begin(), eit = funToFJSites.end(); it!=eit; ++it)
690  // {
691  // // ScalarEvolution* SE = MTA::getSE(it->first);
692  // for(CallInstSet::const_iterator sit = it->second.begin(), esit = it->second.end(); sit!=esit; ++sit)
693  // {
694  // const SVFInstruction* callInst = *sit;
695  // if(tct->getThreadCallGraph()->isForksite(getCBN(callInst)))
696  // {
697  // // const SVFValue* forkSiteTidPtr = getForkedThread(callInst);
698  // // const SCEV *forkSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(forkSiteTidPtr));
699  // // const SCEV *baseForkTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(forkSiteTidPtr)));
700  // // forkSiteTidPtrSCEV = getSCEVMinusExpr(forkSiteTidPtrSCEV, baseForkTidPtrSCEV, SE);
701  // // PTASCEV scev(forkSiteTidPtr,nullptr,nullptr);
702  // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
703  // }
704  // else
705  // {
706  // // const SVFValue* joinSiteTidPtr = getJoinedThread(callInst);
707  // //const SCEV *joinSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(joinSiteTidPtr));
708  // //const SCEV *baseJoinTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(joinSiteTidPtr)));
709  // //joinSiteTidPtrSCEV = getSCEVMinusExpr(joinSiteTidPtrSCEV, baseJoinTidPtrSCEV, SE);
710 
711  // // PTASCEV scev(joinSiteTidPtr,nullptr,nullptr);
712  // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
713  // }
714  // }
715  // }
716 }
717 
722 {
723  for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
724  {
725  const CxtThread& ct = tpair.second->getCxtThread();
726  const NodeID rootTid = tpair.first;
727  clearFlagMap();
728  if (const ICFGNode* forkInst = ct.getThread())
729  {
730  CallStrCxt forkSiteCxt = tct->getCxtOfCxtThread(ct);
731  const ICFGNode* exitInst = getExitInstOfParentRoutineFun(rootTid);
732 
733  for(const ICFGEdge* outEdge : forkInst->getOutEdges())
734  {
735  if(outEdge->getDstNode()->getFun() == forkInst->getFun())
736  {
737  CxtStmt newCts(forkSiteCxt, outEdge->getDstNode());
738  markCxtStmtFlag(newCts, TDAlive);
739  }
740  }
741 
742  while (!cxtStmtList.empty())
743  {
744  CxtStmt cts = popFromCTSWorkList();
745  const ICFGNode* curInst = cts.getStmt();
746  DBOUT(DMTA, outs() << "-----\nForkJoinAnalysis root thread: " << tpair.first << " ");
747  DBOUT(DMTA, cts.dump());
748  DBOUT(DMTA, outs() << "-----\n");
750  if (isTDFork(curInst))
751  {
752  handleFork(cts, rootTid);
753  }
754  else if (isTDJoin(curInst))
755  {
756  handleJoin(cts, rootTid);
757  }
758  else if (tct->isCallSite(curInst) && tct->isCandidateFun(getCallee(curInst, callees)))
759  {
760 
761  handleCall(cts, rootTid);
762  }
763  else if (isRetInstNode(curInst))
764  {
765  handleRet(cts);
766  }
767  else
768  {
769  handleIntra(cts);
770  }
771 
772  if (curInst == exitInst)
773  {
774  if (getMarkedFlag(cts) != TDAlive)
775  addToFullJoin(tct->getParentThread(rootTid), rootTid);
776  else
777  addToPartial(tct->getParentThread(rootTid), rootTid);
778  }
779  }
780  }
781  }
782 }
783 
785 void ForkJoinAnalysis::handleFork(const CxtStmt& cts, NodeID rootTid)
786 {
787  const ICFGNode* call = cts.getStmt();
788  const CallStrCxt& curCxt = cts.getContext();
789 
790  assert(isTDFork(call));
791  const CallICFGNode* cbn = cast<CallICFGNode>(call);
792  if (getTCG()->hasThreadForkEdge(cbn))
793  {
794  for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = getTCG()->getForkEdgeBegin(cbn),
795  ecgIt = getTCG()->getForkEdgeEnd(cbn);
796  cgIt != ecgIt; ++cgIt)
797  {
798  const SVFFunction* callee = (*cgIt)->getDstNode()->getFunction();
799  CallStrCxt newCxt = curCxt;
800  pushCxt(newCxt, cbn, callee);
801  CxtThread ct(newCxt, call);
802  if (getMarkedFlag(cts) != TDAlive)
803  addToHBPair(rootTid, tct->getTCTNode(ct)->getId());
804  else
805  addToHPPair(rootTid, tct->getTCTNode(ct)->getId());
806  }
807  }
808  handleIntra(cts);
809 }
810 
812 void ForkJoinAnalysis::handleJoin(const CxtStmt& cts, NodeID rootTid)
813 {
814  const ICFGNode* call = cts.getStmt();
815  const CallStrCxt& curCxt = cts.getContext();
816 
817  assert(isTDJoin(call));
818  const CallICFGNode* cbn = cast<CallICFGNode>(call);
819  if (getTCG()->hasCallGraphEdge(cbn))
820  {
821  const ICFGNode* forkSite = tct->getTCTNode(rootTid)->getCxtThread().getThread();
822  const ICFGNode* joinSite = cts.getStmt();
823 
824  if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite), SVFUtil::cast<CallICFGNode>(joinSite)))
825  {
826  if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite)))
827  {
828  LoopBBs& joinLoop = getJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite));
829  std::vector<const SVFBasicBlock *> exitbbs;
830  joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
831  while (!exitbbs.empty())
832  {
833  const SVFBasicBlock* eb = exitbbs.back();
834  exitbbs.pop_back();
835  const ICFGNode* svfEntryInst = eb->front();
836  CxtStmt newCts(curCxt, svfEntryInst);
837  addDirectlyJoinTID(cts, rootTid);
838  if (isSameSCEV(forkSite, joinSite))
839  {
840  markCxtStmtFlag(newCts, TDDead);
841  addSymmetricLoopJoin(cts, joinLoop);
842  }
843  else
844  markCxtStmtFlag(cts, TDAlive);
845  }
846  }
847  else
848  {
849  markCxtStmtFlag(cts, TDDead);
850  addDirectlyJoinTID(cts, rootTid);
851  DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << "for thread " << rootTid << "\n");
852  }
853  }
856  else
857  {
858  if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite)))
859  {
860  std::vector<const SVFBasicBlock*> exitbbs;
861  joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
862  while (!exitbbs.empty())
863  {
864  const SVFBasicBlock* eb = exitbbs.back();
865  exitbbs.pop_back();
866  const ICFGNode* svfEntryInst = eb->front();
867  CxtStmt newCts(curCxt, svfEntryInst);
868  markCxtStmtFlag(newCts, cts);
869  }
870  }
871  }
872  }
873  handleIntra(cts);
874 }
875 
877 void ForkJoinAnalysis::handleCall(const CxtStmt& cts, NodeID rootTid)
878 {
879 
880  const ICFGNode* call = cts.getStmt();
881  const CallStrCxt& curCxt = cts.getContext();
882  const CallICFGNode* cbn = SVFUtil::cast<CallICFGNode>(call);
883  if (getTCG()->hasCallGraphEdge(cbn))
884  {
885  for (PTACallGraph::CallGraphEdgeSet::const_iterator cgIt = getTCG()->getCallEdgeBegin(cbn),
886  ecgIt = getTCG()->getCallEdgeEnd(cbn);
887  cgIt != ecgIt; ++cgIt)
888  {
889  const SVFFunction* svfcallee = (*cgIt)->getDstNode()->getFunction();
890  if (isExtCall(svfcallee))
891  continue;
892  CallStrCxt newCxt = curCxt;
893  pushCxt(newCxt, cbn, svfcallee);
894  const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
895  CxtStmt newCts(newCxt, svfEntryInst);
896  markCxtStmtFlag(newCts, cts);
897  }
898  }
899 }
900 
903 {
904  const ICFGNode* curInst = cts.getStmt();
905  const CallStrCxt& curCxt = cts.getContext();
906 
907  PTACallGraphNode* curFunNode = getTCG()->getCallGraphNode(curInst->getFun());
908  for (PTACallGraphEdge* edge : curFunNode->getInEdges())
909  {
910  if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
911  continue;
912  for (PTACallGraphEdge::CallInstSet::const_iterator cit = edge->directCallsBegin(),
913  ecit = edge->directCallsEnd();
914  cit != ecit; ++cit)
915  {
916  CallStrCxt newCxt = curCxt;
917  const ICFGNode* curNode = (*cit);
918  if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
919  {
920  for(const ICFGEdge* outEdge : curNode->getOutEdges())
921  {
922  if(outEdge->getDstNode()->getFun() == curNode->getFun())
923  {
924  CxtStmt newCts(newCxt, outEdge->getDstNode());
925  markCxtStmtFlag(newCts, cts);
926  }
927  }
928  }
929  }
930  for (PTACallGraphEdge::CallInstSet::const_iterator cit = edge->indirectCallsBegin(),
931  ecit = edge->indirectCallsEnd();
932  cit != ecit; ++cit)
933  {
934  CallStrCxt newCxt = curCxt;
935  const ICFGNode* curNode = (*cit);
936 
937  if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
938  {
939  for(const ICFGEdge* outEdge : curNode->getOutEdges())
940  {
941  if(outEdge->getDstNode()->getFun() == curNode->getFun())
942  {
943  CxtStmt newCts(newCxt, outEdge->getDstNode());
944  markCxtStmtFlag(newCts, cts);
945  }
946  }
947  }
948  }
949  }
950 }
951 
954 {
955 
956  const ICFGNode* curInst = cts.getStmt();
957  const CallStrCxt& curCxt = cts.getContext();
958 
959  for(const ICFGEdge* outEdge : curInst->getOutEdges())
960  {
961  if(outEdge->getDstNode()->getFun() == curInst->getFun())
962  {
963  CxtStmt newCts(curCxt, outEdge->getDstNode());
964  markCxtStmtFlag(newCts, cts);
965  }
966  }
967 }
968 
975 {
976 
977  CxtStmtToTIDMap::const_iterator it = dirAndIndJoinMap.find(cs);
978  if (it != dirAndIndJoinMap.end())
979  return it->second;
980 
981  const NodeBS& directJoinTids = getDirectlyJoinedTid(cs);
982  NodeBS allJoinTids = directJoinTids;
983 
984  FIFOWorkList<NodeID> worklist;
985  for (unsigned id : directJoinTids)
986  {
987  worklist.push(id);
988  }
989 
990  while (!worklist.empty())
991  {
992  NodeID tid = worklist.pop();
993  TCTNode* node = tct->getTCTNode(tid);
994  for (TCT::ThreadCreateEdgeSet::const_iterator it = tct->getChildrenBegin(node), eit = tct->getChildrenEnd(node); it != eit; ++it)
995  {
996  NodeID childTid = (*it)->getDstID();
997  if (isFullJoin(tid, childTid))
998  {
999  allJoinTids.set(childTid);
1000  worklist.push(childTid);
1001  }
1002  }
1003  }
1004 
1005  dirAndIndJoinMap[cs] = allJoinTids;
1006 
1007  return allJoinTids;
1008 }
1009 
1010 // static bool accessSameArrayIndex(const GetElementPtrInst* ptr1, const GetElementPtrInst* ptr2)
1011 // {
1012 
1013 // std::vector<u32_t> ptr1vec;
1014 // for (gep_type_iterator gi = gep_type_begin(*ptr1), ge = gep_type_end(*ptr1);
1015 // gi != ge; ++gi)
1016 // {
1017 // if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1018 // {
1019 // s32_t idx = ci->getSExtValue();
1020 // ptr1vec.push_back(idx);
1021 // }
1022 // else
1023 // return false;
1024 // }
1025 
1026 // std::vector<u32_t> ptr2vec;
1027 // for (gep_type_iterator gi = gep_type_begin(*ptr2), ge = gep_type_end(*ptr2);
1028 // gi != ge; ++gi)
1029 // {
1030 // if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1031 // {
1032 // s32_t idx = ci->getSExtValue();
1033 // ptr2vec.push_back(idx);
1034 // }
1035 // else
1036 // return false;
1037 // }
1038 
1039 // return ptr1vec==ptr2vec;
1040 // }
1041 
1049 bool ForkJoinAnalysis::isSameSCEV(const ICFGNode* forkSite, const ICFGNode* joinSite)
1050 {
1051 
1052  // const PTASCEV& forkse = fkjnToPTASCEVMap[forkSite];
1053  // const PTASCEV& joinse = fkjnToPTASCEVMap[joinSite];
1054 
1055  // //if(sameLoopTripCount(forkSite,joinSite) == false)
1056  // // return false;
1057 
1058  // if(forkse.inloop && joinse.inloop)
1059  // return forkse.start==joinse.start && forkse.step == joinse.step && forkse.tripcount <= joinse.tripcount;
1060  // else if(SVFUtil::isa<GetElementPtrInst>(forkse.ptr) && SVFUtil::isa<GetElementPtrInst>(joinse.ptr))
1061  // return accessSameArrayIndex(SVFUtil::cast<GetElementPtrInst>(forkse.ptr),SVFUtil::cast<GetElementPtrInst>(joinse.ptr));
1062  // else if(SVFUtil::isa<GetElementPtrInst, GetElementPtrInst>(joinse.ptr))
1063  // return false;
1064  // else
1065  // return true;
1066 
1067  return false;
1068 }
1069 
1073 bool ForkJoinAnalysis::sameLoopTripCount(const ICFGNode* forkSite, const ICFGNode* joinSite)
1074 {
1075 
1076  // ScalarEvolution* forkSE = getSE(forkSite);
1077  // ScalarEvolution* joinSE = getSE(joinSite);
1078 
1079  // if(tct->hasLoop(forkSite) == false || tct->hasLoop(joinSite) == false)
1080  // return false;
1081 
1082  // // Get loops
1083  // const LoopBBs& forkSiteLoop = tct->getLoop(forkSite);
1084  // const LoopBBs& joinSiteLoop = tct->getLoop(joinSite);
1085 
1086  // const SCEV* forkLoopCountScev = forkSE->getBackedgeTakenCount(forkSiteLoop);
1087  // const SCEV* joinLoopCountScev = joinSE->getBackedgeTakenCount(joinSiteLoop);
1088 
1089  // if(forkLoopCountScev!=forkSE->getCouldNotCompute())
1090  // {
1091  // if(forkLoopCountScev==joinLoopCountScev)
1092  // {
1093  // return true;
1094  // }
1095  // }
1096  return false;
1097 }
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define TIMEINTERVAL
Definition: SVFType.h:512
#define DMTA
Definition: SVFType.h:505
#define DGENERAL
Definition: SVFType.h:490
#define DOTIMESTAT(X)
Definition: SVFType.h:486
const std::string toString() const override
Definition: ICFG.cpp:131
const CallStrCxt & getContext() const
Return current context.
Definition: CxtStmt.h:58
void dump() const
Dump CxtStmt.
Definition: CxtStmt.h:110
const ICFGNode * getStmt() const
Return current statement.
Definition: CxtStmt.h:63
NodeID getTid() const
Return current context.
Definition: CxtStmt.h:140
void dump() const
Dump CxtThreadStmt.
Definition: CxtStmt.h:176
const ICFGNode * getThread() const
Return forksite.
Definition: CxtStmt.h:211
const CallStrCxt & getContext() const
Return context of the thread.
Definition: CxtStmt.h:206
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
void addToFullJoin(NodeID tid1, NodeID tid2)
full join and partial join
Definition: MHP.h:517
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
Definition: MHP.h:389
void addToHPPair(NodeID tid1, NodeID tid2)
Definition: MHP.h:504
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition: MHP.h:285
void analyzeForkJoinPair()
Definition: MHP.cpp:721
bool hasJoinLoop(const CallICFGNode *inst)
Definition: MHP.h:354
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
Definition: MHP.h:528
void handleRet(const CxtStmt &cts)
Handle return.
Definition: MHP.cpp:902
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
Definition: MHP.cpp:974
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition: MHP.h:458
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
Definition: MHP.h:350
CxtStmt popFromCTSWorkList()
Definition: MHP.h:445
void addToHBPair(NodeID tid1, NodeID tid2)
Definition: MHP.h:509
const ICFGNode * getExitInstOfParentRoutineFun(NodeID tid) const
Get exit instruction of the start routine function of tid's parent thread.
Definition: MHP.h:341
void addToPartial(NodeID tid1, NodeID tid2)
Definition: MHP.h:521
void collectSCEVInfo()
functions
Definition: MHP.cpp:667
void clearFlagMap()
Clear flags.
Definition: MHP.h:432
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition: MHP.h:453
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
Definition: MHP.h:306
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
Definition: MHP.h:326
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
Definition: MHP.h:496
ThreadCallGraph * getTCG() const
ThreadCallGraph.
Definition: MHP.h:491
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition: MHP.h:314
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition: MHP.h:464
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
Definition: MHP.h:333
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
Definition: MHP.h:536
void handleCall(const CxtStmt &cts, NodeID rootTid)
Handle call.
Definition: MHP.cpp:877
bool hasJoinInSymmetricLoop(const CxtStmt &cs) const
Definition: MHP.h:320
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
Definition: MHP.cpp:1073
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition: MHP.h:470
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
Definition: MHP.h:401
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
Definition: MHP.h:534
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
Definition: MHP.h:382
void handleIntra(const CxtStmt &cts)
Handle intra.
Definition: MHP.cpp:953
void handleFork(const CxtStmt &cts, NodeID rootTid)
Handle fork.
Definition: MHP.cpp:785
const PTACallGraph::FunctionSet & getCallee(const ICFGNode *inst, PTACallGraph::FunctionSet &callees)
Definition: MHP.h:485
void handleJoin(const CxtStmt &cts, NodeID rootTid)
Handle join.
Definition: MHP.cpp:812
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
Definition: MHP.cpp:1049
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
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
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
virtual const std::string toString() const
Definition: ICFG.cpp:61
void analyze()
Start analysis here.
Definition: MHP.cpp:62
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition: MHP.h:255
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition: MHP.cpp:446
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
Definition: MHP.h:200
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
Definition: MHP.h:172
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition: MHP.cpp:592
TCT * tct
TCT.
Definition: MHP.h:253
FuncPairToBool nonCandidateFuncMHPRelMap
Definition: MHP.h:258
void printInterleaving()
Print interleaving results.
Definition: MHP.cpp:647
void updateSiblingThreads(NodeID tid)
Definition: MHP.cpp:418
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
Definition: MHP.h:109
u32_t numOfTotalQueries
Total number of queries.
Definition: MHP.h:262
Set< CxtThreadStmt > CxtThreadStmtSet
Definition: MHP.h:51
void handleNonCandidateFun(const CxtThreadStmt &cts)
Handle non-candidate function.
Definition: MHP.cpp:181
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition: MHP.h:54
void handleJoin(const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition: MHP.cpp:233
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition: MHP.h:205
ThreadCallGraph * tcg
TCG.
Definition: MHP.h:252
void addInterleavingThread(const CxtThreadStmt &tgr, NodeID tid)
Add/Remove interleaving thread for statement inst.
Definition: MHP.h:155
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
Definition: MHP.h:97
InstToThreadStmtSetMap instToTSMap
Map a statement to its thread interleavings.
Definition: MHP.h:257
virtual ~MHP()
Destructor.
Definition: MHP.cpp:54
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
Definition: MHP.cpp:516
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition: MHP.h:228
void handleRet(const CxtThreadStmt &cts)
Handle return.
Definition: MHP.cpp:319
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
Definition: MHP.cpp:626
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition: MHP.h:210
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition: MHP.cpp:614
void handleFork(const CxtThreadStmt &cts, NodeID rootTid)
Handle fork.
Definition: MHP.cpp:203
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition: MHP.cpp:507
bool isConnectedfromMain(const SVFFunction *fun)
Whether the function is connected from main function in thread call graph.
Definition: MHP.cpp:521
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition: MHP.h:254
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition: MHP.cpp:500
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition: MHP.h:115
double interleavingQueriesTime
Definition: MHP.h:265
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
Definition: MHP.h:263
void updateNonCandidateFunInterleaving()
Definition: MHP.cpp:144
MHP(TCT *t)
Constructor.
Definition: MHP.cpp:44
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Definition: MHP.cpp:481
double interleavingTime
Definition: MHP.h:264
std::pair< const SVFFunction *, const SVFFunction * > FuncPair
Definition: MHP.h:58
CxtThreadStmt popFromCTSWorkList()
Definition: MHP.h:221
void analyzeInterleaving()
Analyze thread interleaving.
Definition: MHP.cpp:75
NodeBS getDirAndIndJoinedTid(const CallStrCxt &cxt, const ICFGNode *call)
Return thread id(s) which are directly or indirectly joined at this join site.
Definition: MHP.cpp:491
void updateAncestorThreads(NodeID tid)
Update Ancestor and sibling threads.
Definition: MHP.cpp:382
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition: MHP.cpp:556
void handleIntra(const CxtThreadStmt &cts)
Handle intra.
Definition: MHP.cpp:366
void handleCall(const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
Definition: MHP.cpp:290
ThreadStmtToThreadInterleav threadStmtToTheadInterLeav
Definition: MHP.h:256
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition: MHP.h:234
const PTACallGraph::FunctionSet & getCallee(const CallICFGNode *inst, PTACallGraph::FunctionSet &callees)
Definition: MHP.h:126
static const Option< bool > PrintInterLev
Definition: Options.h:159
const SVFFunction * getFunction() const
Get function of this call node.
Definition: PTACallGraph.h:198
PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator
Definition: PTACallGraph.h:180
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
Definition: PTACallGraph.h:434
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
Definition: PTACallGraph.h:427
Set< const SVFFunction * > FunctionSet
Definition: PTACallGraph.h:251
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
Definition: PTACallGraph.h:339
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
Definition: PTACallGraph.h:423
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const ICFGNode * front() const
Definition: SVFValue.h:594
const ICFGNode * back() const
Definition: SVFValue.h:600
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
Definition: SVFValue.h:465
const SVFBasicBlock * getEntryBlock() const
Definition: SVFValue.h:409
const FunctionSetType & getFunctionSet() const
Definition: SVFModule.h:199
static double getClk(bool mark=false)
Definition: SVFStat.cpp:47
const std::string & getName() const
Definition: SVFValue.h:243
bool test(unsigned Idx) const
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get CxtThread.
Definition: TCT.h:101
Definition: TCT.h:154
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition: TCT.h:196
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
Definition: TCT.h:428
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition: TCT.h:271
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
Definition: TCT.h:217
NodeID getParentThread(NodeID tid) const
Get parent thread.
Definition: TCT.h:320
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
Definition: TCT.h:350
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition: TCT.h:206
bool isCandidateFun(const PTACallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition: TCT.h:291
SVFModule * getSVFModule() const
Get SVFFModule.
Definition: TCT.h:190
const CallStrCxt & getCxtOfCxtThread(const CxtThread &ct) const
get the context of a thread at its spawning site (fork site)
Definition: TCT.h:369
const SVFFunction * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
Definition: TCT.h:377
const NodeBS getAncestorThread(NodeID tid) const
Get all ancestor threads.
Definition: TCT.h:329
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition: TCT.h:264
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
Definition: TCT.h:221
Set< const PTACallGraphNode * > PTACGNodeSet
Definition: TCT.h:163
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
bool isRetInstNode(const ICFGNode *node)
Definition: SVFUtil.cpp:388
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition: SVFUtil.cpp:147
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55
std::vector< u32_t > CallStrCxt
Definition: GeneralType.h:122