Static Value-Flow Analysis
Loading...
Searching...
No Matches
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 * May-happen-in-parallel analysis. One implementation runs on the whole program
30 * or a slice via the templated analyze(), which is parameterised on the two
31 * graphs it traverses (whole ICFG/CallGraph or their sliced views) and calls
32 * their GenericGraphTraits directly, as used by "Multi-Stage On-Demand Program Slicing for
33 * Modular Analysis of Multi-Threaded Programs" (ISSTA 2026).
34 */
35
36#include "Util/Options.h"
37#include "MTA/MHP.h"
38#include "MTA/MTA.h"
39#include "MTA/LockAnalysis.h"
40#include "MTA/MTASlicer.h"
41#include "Util/SVFUtil.h"
42#include "Util/PTAStat.h"
44#include "Graphs/SlicedGraphs.h"
45#include "SVFIR/SVFIR.h"
46#include "WPA/Andersen.h"
47
48using namespace SVF;
49using namespace SVFUtil;
50
54MHP::MHP(TCT* t) : tcg(t->getThreadCallGraph()), tct(t), numOfTotalQueries(0), numOfMHPQueries(0),
55 interleavingTime(0), interleavingQueriesTime(0)
56{
60}
61
66{
67 for (const auto& joinAndLoop : fja->getSymmetricLoopJoins())
68 {
70 for (const SVFBasicBlock* bb : joinAndLoop.second)
71 {
72 loopBlocks.insert(bb);
73 bbToSymJoins[bb].push_back(joinAndLoop.first);
74 }
75 }
76}
77
83{
85 const SVFBasicBlock* srcBB = cts.getStmt()->getBB();
86 const SVFBasicBlock* dstBB = dst->getBB();
87 if (srcBB == nullptr || dstBB == nullptr || srcBB == dstBB)
88 return flow;
89 BBToSymJoinsMap::const_iterator it = bbToSymJoins.find(srcBB);
90 if (it == bbToSymJoins.end())
91 return flow;
92 for (const CxtStmt& join : it->second)
93 {
94 if (join.getContext() != cts.getContext())
95 continue;
97 if (loopBlocks.find(dstBB) != loopBlocks.end())
98 continue; // edge stays inside the loop
99 if (!isMustJoin(cts.getTid(), join.getStmt()))
100 continue;
101 flow.intersectWithComplement(
102 getDirAndIndJoinedTid(join.getContext(), join.getStmt()));
103 }
104 return flow;
105}
106
111{
112 delete fja;
113}
114
115
119template<class ICFGGraph, class CGGraph>
121{
122 DBOUT(DGENERAL, outs() << pasMsg("MHP interleaving analysis\n"));
123 DBOUT(DMTA, outs() << pasMsg("MHP interleaving analysis\n"));
125 analyzeInterleaving(icfg, cg);
128}
129
133template<class ICFGGraph, class CGGraph>
135{
136 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
137 {
138 const CxtThread& ct = tpair.second->getCxtThread();
139 NodeID rootTid = tpair.first;
142 CxtThreadStmt rootcts(rootTid, ct.getContext(), svfInst);
143
147
148 while (!cxtStmtList.empty())
149 {
151 const ICFGNode* curInst = cts.getStmt();
152
153 DBOUT(DMTA, outs() << "-----\nMHP analysis root thread: " << rootTid << " ");
154 DBOUT(DMTA, cts.dump());
155 DBOUT(DMTA, outs() << "current thread interleaving: < ");
157 DBOUT(DMTA, outs() << " >\n-----\n");
158
160 if (!tct->isCandidateFun(curInst->getFun()))
161 {
163 }
165 else
166 {
167 if (isTDFork(curInst))
168 {
169 handleFork(icfg, cg, cts, rootTid);
170 }
171 else if (isTDJoin(curInst))
172 {
173 handleJoin(icfg, cg, cts, rootTid);
174 }
175 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
176 {
177 handleCall(icfg, cg, cts, rootTid);
178 }
179 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
180 {
181 handleRet(icfg, cg, cts);
182 }
183 else
184 {
185 handleIntra(icfg, cg, cts);
186 }
187 }
188 }
189 }
190
193
196}
197
201template<class ICFGGraph, class CGGraph>
203{
204 // Copy each non-candidate function entry's interleaving to the function's
205 // other nodes under the graph. Runs after the worklist has drained, so
206 // addInterleavingThread's push is inert.
208 {
209 const FunObjVar* fun = item.second->getFunction();
210 if (tct->isCandidateFun(fun) || isExtCall(fun))
211 continue;
212
215 continue;
216
218
219 std::vector<const ICFGNode*> funICFGNodes;
221
222 for (const CxtThreadStmt& cts : tsSet)
223 {
224 const CallStrCxt& curCxt = cts.getContext();
225 for (const ICFGNode* curNode : funICFGNodes)
226 {
227 if (curNode == entryNode)
228 continue;
231 }
232 }
233 }
234}
235
239template<class ICFGGraph, class CGGraph>
241{
242 const ICFGNode* curInst = cts.getStmt();
243 const FunObjVar* curfun = curInst->getFun();
244 assert((curInst == GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, curfun)) && "curInst is not the entry of non candidate function.");
245 const CallStrCxt& curCxt = cts.getContext();
247 for (CallGraphNode::const_iterator nit = node->OutEdgeBegin(), neit = node->OutEdgeEnd(); nit != neit; nit++)
248 {
249 const FunObjVar* callee = (*nit)->getDstNode()->getFunction();
250 if (!isExtCall(callee))
251 {
255 }
256 }
257}
258
262template<class ICFGGraph, class CGGraph>
264{
265
266 const ICFGNode* call = cts.getStmt();
267 const CallStrCxt& curCxt = cts.getContext();
268
269 assert(isTDFork(call));
270 const CallICFGNode* cbn = cast<CallICFGNode>(call);
272 {
273
274 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = tcg->getForkEdgeBegin(cbn),
276 cgIt != ecgIt; ++cgIt)
277 {
278 const FunObjVar* svfroutine = (*cgIt)->getDstNode()->getFunction();
282 CxtThread ct(newCxt, call);
283 CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
285 }
286 }
287 handleIntra(icfg, cg, cts);
288}
289
293template<class ICFGGraph, class CGGraph>
295{
296
297 const CallStrCxt& curCxt = cts.getContext();
298
299 assert(isTDJoin(cts.getStmt()));
300
301 const CallICFGNode* call = SVFUtil::cast<CallICFGNode>(cts.getStmt());
302
304 if (!joinedTids.empty())
305 {
306 if (fja->hasJoinLoop(call))
307 {
308 // Seed the loop exits with the flow along the exiting edge (see
309 // edgeFlow): the kill applies to the flow, not the exit's state.
311 if (hasJoinInSymmetricLoop(curCxt, call) && isMustJoin(cts.getTid(), call))
312 flow.intersectWithComplement(joinedTids);
313
314 std::vector<const SVFBasicBlock*> exitbbs;
315 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
316 while (!exitbbs.empty())
317 {
318 const SVFBasicBlock* eb = exitbbs.back();
319 exitbbs.pop_back();
320 // Seed the post-join interleaving at the loop-exit entry. The slicer
321 // retains these entries as anchors, so the seed always lands on a kept
322 // node (no runtime projection needed).
323 CxtThreadStmt newCts(cts.getTid(), curCxt, eb->front());
325 }
326 }
327 else
328 {
330 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << " for thread " << rootTid << "\n");
331 }
332 }
335 else
336 {
337 if (fja->hasJoinLoop(call))
338 {
339 std::vector<const SVFBasicBlock*> exitbbs;
340 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
341 while (!exitbbs.empty())
342 {
343 const SVFBasicBlock* eb = exitbbs.back();
344 exitbbs.pop_back();
345 // Seed at the loop-exit entry (a retained anchor; see above).
346 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), eb->front());
348 }
349 }
350 }
351 handleIntra(icfg, cg, cts);
352}
353
357template<class ICFGGraph, class CGGraph>
359{
360
361 const ICFGNode* call = cts.getStmt();
362 const CallStrCxt& curCxt = cts.getContext();
363 const CallICFGNode* cbn = cast<CallICFGNode>(call);
365 {
366 for (CallGraph::CallGraphEdgeSet::const_iterator cgIt = tcg->getCallEdgeBegin(cbn),
368 cgIt != ecgIt; ++cgIt)
369 {
370 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
371 if (isExtCall(svfcallee))
372 continue;
373
375 const CallICFGNode* callicfgnode = SVFUtil::cast<CallICFGNode>(call);
380
381 // Return-flow rendezvous: if the callee's exit already has state
382 // under newCxt, forward it now (handleRet cannot see late callsites).
383 if (tct->isCandidateFun(svfcallee) && svfcallee->hasBasicBlock())
384 {
385 const ICFGNode* exitInst = svfcallee->getExitBB()->back();
388 {
389 CxtThreadStmt retCts(cts.getTid(), curCxt, cbn->getRetICFGNode());
391 }
392 }
393 }
394 }
395
399 if (const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(call))
400 {
403 {
404 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), callSite->getRetICFGNode());
406 }
407 }
408 else
409 {
410 assert(false && "cts.getStmt() is not a CallICFGNode!");
411 }
412}
413
417template<class ICFGGraph, class CGGraph>
419{
420 CallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
421 std::vector<const CallGraphEdge*> inEdges;
423 for (const CallGraphEdge* edgeConst : inEdges)
424 {
425 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edgeConst))
426 continue;
427 // Need non-const for directCallsBegin/End
428 CallGraphEdge* edge = const_cast<CallGraphEdge*>(edgeConst);
429 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->directCallsBegin(),
430 ecit = (edge)->directCallsEnd();
431 cit != ecit; ++cit)
432 {
433 CallStrCxt newCxt = cts.getContext();
434 if (matchAndPopCxt(newCxt, *cit, curFunNode->getFunction()))
435 {
436 std::vector<const ICFGNode*> succ;
438 for (const ICFGNode* dst : succ)
439 {
440 if(dst->getFun() == (*cit)->getFun())
441 {
442 // Iterate over callSite's call string context and use as the successor's context
443 if (!hasThreadStmtSet(*cit))
444 continue;
446 {
447 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
448 // If new context is a suffix of the call site context
450 {
451 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
453 }
454 }
455 }
456 }
457 }
458 }
459 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->indirectCallsBegin(),
460 ecit = (edge)->indirectCallsEnd();
461 cit != ecit; ++cit)
462 {
463 CallStrCxt newCxt = cts.getContext();
464 if (matchAndPopCxt(newCxt, *cit, curFunNode->getFunction()))
465 {
466 std::vector<const ICFGNode*> succ;
468 for (const ICFGNode* dst : succ)
469 {
470 if(dst->getFun() == (*cit)->getFun())
471 {
472 // Iterate over callSite's call string context and use as the successor's context
473 if (!hasThreadStmtSet(*cit))
474 continue;
476 {
477 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
478 // If new context is a suffix of the call site context
480 {
481 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
483 }
484 }
485 }
486 }
487 }
488 }
489 }
490}
491
495template<class ICFGGraph, class CGGraph>
497{
498 const SVFBasicBlock* srcBB = cts.getStmt()->getBB();
499 const bool mayExitSymJoinLoop =
500 srcBB != nullptr && bbToSymJoins.find(srcBB) != bbToSymJoins.end();
501
502 std::vector<const ICFGNode*> succ;
504 for (const ICFGNode* dst : succ)
505 {
506 if(dst->getFun() == cts.getStmt()->getFun())
507 {
508 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), dst);
511 else
513 }
514 }
515}
516
520template<class ICFGGraph, class CGGraph>
522{
524 DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
526 DBOUT(DMTA, outs() << "\n");
528
529 for (const unsigned tid : ancestorAndSelfTids)
530 {
531 const CxtThread& ct = tct->getTCTNode(tid)->getCxtThread();
532 if (const ICFGNode* forkInst = ct.getThread())
533 {
534 // Mark the fork site's successors under the graph, so a sliced run
535 // marks kept successors (a marker on a removed node would strand).
536 std::vector<const ICFGNode*> succ;
538 for(const ICFGNode* dst : succ)
539 {
540 // Ensure dst node is in the same function as forkInst
541 if(dst->getFun() == forkInst->getFun())
542 {
543 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
544 {
545 CxtThreadStmt cts(forkSiteCxt.first, forkSiteCxt.second, dst);
547 }
548 }
549 }
550 }
551 }
552}
553
564template<class ICFGGraph, class CGGraph>
566{
569 for (const unsigned tid : ancestorAndSelfTids)
570 {
572 for (const unsigned stid : siblingTds)
573 {
574 if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
575 continue;
576
579 // The entry node under the graph: the same node the sibling thread's
580 // own propagation starts from (see analyzeInterleaving's root cts).
582 CxtThreadStmt cts(stid, ct.getContext(), stmt);
584 }
585
586 DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
588 DBOUT(DMTA, outs() << "\n");
589 }
590}
591
596{
597 if (parentTid == curTid)
598 return true;
599
602 worklist.push(curNode);
603 while (!worklist.empty())
604 {
605 const TCTNode* node = worklist.pop();
606 for (TCTEdge* edge : node->getInEdges())
607 {
608 NodeID srcID = edge->getSrcID();
609 if (fja->isFullJoin(srcID, node->getId()))
610 {
611 if (srcID == parentTid)
612 return true;
613 else
614 worklist.push(edge->getSrcNode());
615 }
616 else
617 {
618 return false;
619 }
620 }
621 }
622 return false;
623}
624
631{
632 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
633 assert(call && isTDJoin(call) && "not a join site!");
635}
636
641{
642 CxtStmt cs(cxt, call);
643 return fja->getDirAndIndJoinedTid(cs);
644}
645
649bool MHP::hasJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
650{
651 CxtStmt cs(cxt, call);
652 return fja->hasJoinInSymmetricLoop(cs);
653}
654
656const MHP::LoopBBs& MHP::getJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
657{
658 CxtStmt cs(cxt, call);
659 return fja->getJoinInSymmetricLoop(cs);
660}
661
666{
667 return fja->isHBPair(tid1, tid2);
668}
669
671{
674 TCT::PTACGNodeSet visited;
675 worklist.push(cgnode);
676 visited.insert(cgnode);
677 while (!worklist.empty())
678 {
679 const CallGraphNode* node = worklist.pop();
681 return true;
682 for (CallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
683 {
684 const CallGraphNode* srcNode = (*nit)->getSrcNode();
685 if (visited.find(srcNode) == visited.end())
686 {
687 visited.insert(srcNode);
688 worklist.push(srcNode);
689 }
690 }
691 }
692 return false;
693}
694
706{
707
710 return false;
711
714 for (const CxtThreadStmt& ts1 : tsSet1)
715 {
717 for (const CxtThreadStmt& ts2 : tsSet2)
718 {
720 if (ts1.getTid() != ts2.getTid())
721 {
722 if (l1.test(ts2.getTid()) && l2.test(ts1.getTid()))
723 {
725 return true;
726 }
727 }
728 else
729 {
730 if (isMultiForkedThread(ts1.getTid()))
731 {
733 return true;
734 }
735 }
736 }
737 }
738 return false;
739}
740
742{
743 if (!tct->isCandidateFun(i1->getFun()) && !tct->isCandidateFun(i2->getFun()))
744 {
745 FuncPair funpair = std::make_pair(i1->getFun(), i2->getFun());
746 FuncPairToBool::const_iterator it = nonCandidateFuncMHPRelMap.find(funpair);
747 if (it == nonCandidateFuncMHPRelMap.end())
748 {
749 bool mhp = mayHappenInParallelInst(i1, i2);
751 return mhp;
752 }
753 else
754 {
755 if (it->second)
757 return it->second;
758 }
759 }
761}
762
764{
766
767 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
768 bool mhp = mayHappenInParallelCache(i1, i2);
769 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
771
772 return mhp;
773}
774
776{
778 return true;
779
782 for (const CxtThreadStmt&ts1 : tsSet1)
783 {
784 for (const CxtThreadStmt& ts2 : tsSet2)
785 {
786 if (ts1.getTid() != ts2.getTid() || isMultiForkedThread(ts1.getTid()))
787 return false;
788 }
789 }
790 return true;
791}
792
797{
798 for (const auto& pair : threadStmtToThreadInterLeav)
799 {
800 outs() << "( t" << pair.first.getTid()
801 << pair.first.getStmt()->toString() << " ) ==> [";
802 for (unsigned i : pair.second)
803 {
804 outs() << " " << i << " ";
805 }
806 outs() << "]\n";
807 }
808}
809
817{
818 // typedef Set<const ICFGNode*> CallInstSet;
819 // typedef Map<const FunObjVar*, CallInstSet> FunToFJSites;
820 // FunToFJSites funToFJSites;
821
822 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->forksitesBegin(),
823 // eit = tct->getThreadCallGraph()->forksitesEnd();
824 // it != eit; ++it)
825 // {
826 // const ICFGNode* fork = *it;
827 // funToFJSites[fork->getFun()].insert(fork);
828 // }
829
830 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->joinsitesBegin(),
831 // eit = tct->getThreadCallGraph()->joinsitesEnd();
832 // it != eit; ++it)
833 // {
834 // const ICFGNode* join = *it;
835 // funToFJSites[join->getFun()].insert(join);
836 // }
837
838 // for(FunToFJSites::const_iterator it = funToFJSites.begin(), eit = funToFJSites.end(); it!=eit; ++it)
839 // {
840 // // ScalarEvolution* SE = MTA::getSE(it->first);
841 // for(CallInstSet::const_iterator sit = it->second.begin(), esit = it->second.end(); sit!=esit; ++sit)
842 // {
843 // const SVFInstruction* callInst = *sit;
844 // if(tct->getThreadCallGraph()->isForksite(getCBN(callInst)))
845 // {
846 // // const SVFValue* forkSiteTidPtr = getForkedThread(callInst);
847 // // const SCEV *forkSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(forkSiteTidPtr));
848 // // const SCEV *baseForkTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(forkSiteTidPtr)));
849 // // forkSiteTidPtrSCEV = getSCEVMinusExpr(forkSiteTidPtrSCEV, baseForkTidPtrSCEV, SE);
850 // // PTASCEV scev(forkSiteTidPtr,nullptr,nullptr);
851 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
852 // }
853 // else
854 // {
855 // // const SVFValue* joinSiteTidPtr = getJoinedThread(callInst);
856 // //const SCEV *joinSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(joinSiteTidPtr));
857 // //const SCEV *baseJoinTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(joinSiteTidPtr)));
858 // //joinSiteTidPtrSCEV = getSCEVMinusExpr(joinSiteTidPtrSCEV, baseJoinTidPtrSCEV, SE);
859
860 // // PTASCEV scev(joinSiteTidPtr,nullptr,nullptr);
861 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
862 // }
863 // }
864 // }
865}
866
871{
872 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
873 {
874 const CxtThread& ct = tpair.second->getCxtThread();
875 const NodeID rootTid = tpair.first;
876 clearFlagMap();
877 if (const ICFGNode* forkInst = ct.getThread())
878 {
880 for(const ICFGEdge* outEdge : forkInst->getOutEdges())
881 {
882 if(outEdge->getDstNode()->getFun() == forkInst->getFun())
883 {
884 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
885 {
886 CxtStmt newCts(forkSiteCxt.second, outEdge->getDstNode());
888 }
889 }
890 }
891
892 while (!cxtStmtList.empty())
893 {
895 const ICFGNode* curInst = cts.getStmt();
896 DBOUT(DMTA, outs() << "-----\nForkJoinAnalysis root thread: " << tpair.first << " ");
897 DBOUT(DMTA, cts.dump());
898 DBOUT(DMTA, outs() << "-----\n");
900 if (isTDFork(curInst))
901 {
903 }
904 else if (isTDJoin(curInst))
905 {
907 }
908 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
909 {
913 const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(curInst);
916 {
917 // Do not dive into non-candidate functions
918 CxtStmt newCts(cts.getContext(), callSite->getRetICFGNode());
920 }
921 else
922 {
924 }
925 }
926 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
927 {
928 handleRet(cts);
929 }
930 else
931 {
933 }
934
939 {
942 if (curInst == parentRoutine->getExitBB()->back())
943 {
944 if (getMarkedFlag(cts) != TDAlive)
946 else
948 }
949 }
950 }
951 }
952 }
953}
954
957{
958 const ICFGNode* call = cts.getStmt();
959 const CallStrCxt& curCxt = cts.getContext();
960
961 assert(isTDFork(call));
962 const CallICFGNode* cbn = cast<CallICFGNode>(call);
963 if (getTCG()->hasThreadForkEdge(cbn))
964 {
965 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = getTCG()->getForkEdgeBegin(cbn),
966 ecgIt = getTCG()->getForkEdgeEnd(cbn);
967 cgIt != ecgIt; ++cgIt)
968 {
969 const FunObjVar* callee = (*cgIt)->getDstNode()->getFunction();
972 CxtThread ct(newCxt, call);
973 if (getMarkedFlag(cts) != TDAlive)
975 else
977 }
978 }
980}
981
984{
985 const ICFGNode* call = cts.getStmt();
986 const CallStrCxt& curCxt = cts.getContext();
987
988 assert(isTDJoin(call));
989 const CallICFGNode* cbn = cast<CallICFGNode>(call);
990 if (getTCG()->hasCallGraphEdge(cbn))
991 {
993 const ICFGNode* joinSite = cts.getStmt();
994
995 if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite)))
996 {
997 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
998 SVFUtil::cast<CallICFGNode>(joinSite)) &&
1000 )
1001 {
1002 LoopBBs& joinLoop = getJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite));
1003 std::vector<const SVFBasicBlock *> exitbbs;
1004 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
1005 while (!exitbbs.empty())
1006 {
1007 const SVFBasicBlock* eb = exitbbs.back();
1008 exitbbs.pop_back();
1009 const ICFGNode* svfEntryInst = eb->front();
1013 {
1016 }
1017 else
1019 }
1020 }
1023 else
1024 {
1025 std::vector<const SVFBasicBlock*> exitbbs;
1026 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
1027 while (!exitbbs.empty())
1028 {
1029 const SVFBasicBlock* eb = exitbbs.back();
1030 exitbbs.pop_back();
1031 const ICFGNode* svfEntryInst = eb->front();
1034 }
1035 }
1036 }
1037 else
1038 {
1039 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
1040 SVFUtil::cast<CallICFGNode>(joinSite)))
1041 {
1044 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << "for thread " << rootTid << "\n");
1045 }
1046 }
1047 }
1049}
1050
1053{
1054
1055 const ICFGNode* call = cts.getStmt();
1056 const CallStrCxt& curCxt = cts.getContext();
1057 const CallICFGNode* cbn = SVFUtil::cast<CallICFGNode>(call);
1058 if (getTCG()->hasCallGraphEdge(cbn))
1059 {
1060 for (CallGraph::CallGraphEdgeSet::const_iterator cgIt = getTCG()->getCallEdgeBegin(cbn),
1061 ecgIt = getTCG()->getCallEdgeEnd(cbn);
1062 cgIt != ecgIt; ++cgIt)
1063 {
1064 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
1065 if (isExtCall(svfcallee))
1066 continue;
1069 const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
1072 }
1073 }
1074}
1075
1078{
1079 const ICFGNode* curInst = cts.getStmt();
1080 const CallStrCxt& curCxt = cts.getContext();
1081
1083 for (CallGraphEdge* edge : curFunNode->getInEdges())
1084 {
1085 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
1086 continue;
1087 for (CallGraphEdge::CallInstSet::const_iterator cit = edge->directCallsBegin(),
1088 ecit = edge->directCallsEnd();
1089 cit != ecit; ++cit)
1090 {
1092 const ICFGNode* curNode = (*cit);
1093 if (matchAndPopCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
1094 {
1095 for(const ICFGEdge* outEdge : curNode->getOutEdges())
1096 {
1097 if(outEdge->getDstNode()->getFun() == curNode->getFun())
1098 {
1099 // Iterate over callSite's call string context and use as the successor's context
1100 if (!hasCxtStmtsFromInst(*cit))
1101 continue;
1102 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
1103 {
1104 CallStrCxt callSiteCxt = cxtStmt.getContext();
1105 // If new context is a suffix of the call site context
1107 {
1108 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
1110 }
1111 }
1112 }
1113 }
1114 }
1115 }
1116 for (CallGraphEdge::CallInstSet::const_iterator cit = edge->indirectCallsBegin(),
1117 ecit = edge->indirectCallsEnd();
1118 cit != ecit; ++cit)
1119 {
1121 const ICFGNode* curNode = (*cit);
1122
1123 if (matchAndPopCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
1124 {
1125 for(const ICFGEdge* outEdge : curNode->getOutEdges())
1126 {
1127 if(outEdge->getDstNode()->getFun() == curNode->getFun())
1128 {
1129 // Iterate over callSite's call string context and use as the successor's context
1130 if (!hasCxtStmtsFromInst(*cit))
1131 continue;
1132 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
1133 {
1134 CallStrCxt callSiteCxt = cxtStmt.getContext();
1135 // If new context is a suffix of the call site context
1137 {
1138 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
1140 }
1141 }
1142 }
1143 }
1144 }
1145 }
1146 }
1147}
1148
1151{
1152
1153 const ICFGNode* curInst = cts.getStmt();
1154 const CallStrCxt& curCxt = cts.getContext();
1155
1156 for(const ICFGEdge* outEdge : curInst->getOutEdges())
1157 {
1158 if(outEdge->getDstNode()->getFun() == curInst->getFun())
1159 {
1160 CxtStmt newCts(curCxt, outEdge->getDstNode());
1162 }
1163 }
1164}
1165
1172{
1173
1174 CxtStmtToTIDMap::const_iterator it = dirAndIndJoinMap.find(cs);
1175 if (it != dirAndIndJoinMap.end())
1176 return it->second;
1177
1180
1181 FIFOWorkList<NodeID> worklist;
1182 for (unsigned id : directJoinTids)
1183 {
1184 worklist.push(id);
1185 }
1186
1187 while (!worklist.empty())
1188 {
1189 NodeID tid = worklist.pop();
1190 TCTNode* node = tct->getTCTNode(tid);
1191 for (TCT::ThreadCreateEdgeSet::const_iterator it = tct->getChildrenBegin(node), eit = tct->getChildrenEnd(node); it != eit; ++it)
1192 {
1193 NodeID childTid = (*it)->getDstID();
1194 if (isFullJoin(tid, childTid))
1195 {
1196 allJoinTids.set(childTid);
1197 worklist.push(childTid);
1198 }
1199 }
1200 }
1201
1203
1204 return allJoinTids;
1205}
1206
1207// static bool accessSameArrayIndex(const GetElementPtrInst* ptr1, const GetElementPtrInst* ptr2)
1208// {
1209
1210// std::vector<u32_t> ptr1vec;
1211// for (gep_type_iterator gi = gep_type_begin(*ptr1), ge = gep_type_end(*ptr1);
1212// gi != ge; ++gi)
1213// {
1214// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1215// {
1216// s32_t idx = ci->getSExtValue();
1217// ptr1vec.push_back(idx);
1218// }
1219// else
1220// return false;
1221// }
1222
1223// std::vector<u32_t> ptr2vec;
1224// for (gep_type_iterator gi = gep_type_begin(*ptr2), ge = gep_type_end(*ptr2);
1225// gi != ge; ++gi)
1226// {
1227// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1228// {
1229// s32_t idx = ci->getSExtValue();
1230// ptr2vec.push_back(idx);
1231// }
1232// else
1233// return false;
1234// }
1235
1236// return ptr1vec==ptr2vec;
1237// }
1238
1247{
1248
1249 // const PTASCEV& forkse = fkjnToPTASCEVMap[forkSite];
1250 // const PTASCEV& joinse = fkjnToPTASCEVMap[joinSite];
1251
1252 // //if(sameLoopTripCount(forkSite,joinSite) == false)
1253 // // return false;
1254
1255 // if(forkse.inloop && joinse.inloop)
1256 // return forkse.start==joinse.start && forkse.step == joinse.step && forkse.tripcount <= joinse.tripcount;
1257 // else if(SVFUtil::isa<GetElementPtrInst>(forkse.ptr) && SVFUtil::isa<GetElementPtrInst>(joinse.ptr))
1258 // return accessSameArrayIndex(SVFUtil::cast<GetElementPtrInst>(forkse.ptr),SVFUtil::cast<GetElementPtrInst>(joinse.ptr));
1259 // else if(SVFUtil::isa<GetElementPtrInst, GetElementPtrInst>(joinse.ptr))
1260 // return false;
1261 // else
1262 // return true;
1263
1264 return false;
1265}
1266
1271{
1272
1273 // ScalarEvolution* forkSE = getSE(forkSite);
1274 // ScalarEvolution* joinSE = getSE(joinSite);
1275
1276 // if(tct->hasLoop(forkSite) == false || tct->hasLoop(joinSite) == false)
1277 // return false;
1278
1279 // // Get loops
1280 // const LoopBBs& forkSiteLoop = tct->getLoop(forkSite);
1281 // const LoopBBs& joinSiteLoop = tct->getLoop(joinSite);
1282
1283 // const SCEV* forkLoopCountScev = forkSE->getBackedgeTakenCount(forkSiteLoop);
1284 // const SCEV* joinLoopCountScev = joinSE->getBackedgeTakenCount(joinSiteLoop);
1285
1286 // if(forkLoopCountScev!=forkSE->getCouldNotCompute())
1287 // {
1288 // if(forkLoopCountScev==joinLoopCountScev)
1289 // {
1290 // return true;
1291 // }
1292 // }
1293 return false;
1294}
1295
1302
1303// The two graphs the MHP analysis runs on; the algorithm above is written once
1304// and instantiated for both (all internal templates instantiate transitively).
1305template void MHP::analyze<ICFG*, CallGraph*>(ICFG*, CallGraph*);
1306template void MHP::analyze<const SlicedICFGView*, const SlicedThreadCallGraphView*>(const SlicedICFGView*, const SlicedThreadCallGraphView*);
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DMTA
Definition SVFType.h:597
#define DGENERAL
Definition SVFType.h:582
#define DOTIMESTAT(X)
Definition SVFType.h:578
cJSON * item
Definition cJSON.h:222
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
Definition CallGraph.h:445
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
Definition CallGraph.h:441
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
Definition CallGraph.h:452
const std::string toString() const override
Definition ICFG.cpp:129
const ICFGNode * getThread() const
Return forksite.
Definition CxtStmt.h:209
bool push(const Data &data)
Definition WorkList.h:180
bool empty() const
Definition WorkList.h:161
void addToFullJoin(NodeID tid1, NodeID tid2)
full join and partial join
Definition MHP.h:574
const SVFVar * getForkedThread(const CallICFGNode *call)
Get forked thread.
Definition MHP.h:533
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
Definition MHP.cpp:1296
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
Definition MHP.h:430
void addToHPPair(NodeID tid1, NodeID tid2)
Definition MHP.h:561
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:329
void analyzeForkJoinPair()
Definition MHP.cpp:870
bool hasJoinLoop(const CallICFGNode *inst)
Definition MHP.h:392
const CallGraph::FunctionSet & getCallee(const ICFGNode *inst, CallGraph::FunctionSet &callees)
Definition MHP.h:542
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
Definition MHP.h:597
void handleRet(const CxtStmt &cts)
Handle return.
Definition MHP.cpp:1077
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
Definition MHP.cpp:1171
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:509
CxtStmt popFromCTSWorkList()
Definition MHP.h:491
bool hasCxtStmtsFromInst(const ICFGNode *inst) const
Definition MHP.h:591
void addToHBPair(NodeID tid1, NodeID tid2)
Definition MHP.h:566
ThreadCallGraph * getTCG() const
ThreadCallGraph.
Definition MHP.h:548
void addToPartial(NodeID tid1, NodeID tid2)
Definition MHP.h:578
void collectSCEVInfo()
functions
Definition MHP.cpp:816
void clearFlagMap()
Clear flags.
Definition MHP.h:478
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
Definition MHP.h:373
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
Definition MHP.h:553
const SVFVar * getJoinedThread(const CallICFGNode *call)
Get joined thread.
Definition MHP.h:538
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
Definition MHP.h:388
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:501
const CxtStmtToLoopMap & getSymmetricLoopJoins() const
All SCEV-symmetric in-loop joins and their loop blocks.
Definition MHP.h:397
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:521
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:514
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
Definition MHP.h:380
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
Definition MHP.h:605
void handleCall(const CxtStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:1052
bool hasJoinInSymmetricLoop(const CxtStmt &cs) const
Definition MHP.h:367
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
Definition MHP.cpp:1270
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:527
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
Definition MHP.h:442
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
Definition MHP.h:603
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.h:361
ThreadAPI::ForkJoinAliasCache forkJoinAliasCache
Definition MHP.h:426
void handleIntra(const CxtStmt &cts)
Handle intra.
Definition MHP.cpp:1150
void handleFork(const CxtStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:956
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
Definition MHP.h:353
void handleJoin(const CxtStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:983
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
Definition MHP.cpp:1246
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
Get CxtStmtSet for an instruction.
Definition MHP.h:585
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
iterator OutEdgeEnd()
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:75
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:81
virtual const std::string toString() const
Definition ICFG.cpp:50
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition MHP.h:300
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition MHP.cpp:595
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
Definition MHP.h:233
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle return.
Definition MHP.cpp:418
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
Definition MHP.h:205
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:741
void analyze(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:120
TCT * tct
TCT.
Definition MHP.h:298
BBToSymJoinsMap bbToSymJoins
Map a statement to its thread interleavings.
Definition MHP.h:302
FuncPairToBool nonCandidateFuncMHPRelMap
Definition MHP.h:305
NodeBS edgeFlow(const CxtThreadStmt &cts, const ICFGNode *dst)
Definition MHP.cpp:82
void printInterleaving()
Print interleaving results.
Definition MHP.cpp:796
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:249
u32_t numOfTotalQueries
Total number of queries.
Definition MHP.h:308
Set< CxtThreadStmt > CxtThreadStmtSet
Definition MHP.h:62
void analyzeInterleaving(ICFGGraph icfg, CGGraph cg)
Analyze thread interleaving.
Definition MHP.cpp:134
std::pair< const FunObjVar *, const FunObjVar * > FuncPair
Definition MHP.h:69
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:65
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:254
void updateSiblingThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
Definition MHP.cpp:565
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:263
void updateAncestorThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
Update Ancestor and sibling threads.
Definition MHP.cpp:521
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:358
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:241
ThreadCallGraph * tcg
TCG.
Definition MHP.h:297
void addInterleavingThread(const CxtThreadStmt &tgr, NodeID tid)
Add/Remove interleaving thread for statement inst.
Definition MHP.h:179
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
Definition MHP.h:112
virtual ~MHP()
Destructor.
Definition MHP.cpp:110
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
Definition MHP.cpp:665
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
Definition MHP.h:301
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:273
void addInterleavingBits(const CxtThreadStmt &tgr, const NodeBS &bits)
Definition MHP.h:196
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:775
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition MHP.cpp:763
void buildSymJoinKillTables()
Definition MHP.cpp:65
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
Definition MHP.h:124
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:656
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:294
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition MHP.h:299
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:649
const CallGraph::FunctionSet & getCallee(const CallICFGNode *inst, CallGraph::FunctionSet &callees)
Definition MHP.h:141
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:130
SymJoinToLoopMap symJoinLoop
symmetric in-loop join -> its loop's blocks
Definition MHP.h:303
double interleavingQueriesTime
Definition MHP.h:311
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
Definition MHP.h:309
void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:202
MHP(TCT *t)
Constructor.
Definition MHP.cpp:54
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Definition MHP.cpp:630
double interleavingTime
Definition MHP.h:310
bool isConnectedfromMain(const FunObjVar *fun)
Whether the function is connected from main function in thread call graph.
Definition MHP.cpp:670
void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle intra.
Definition MHP.cpp:496
CxtThreadStmt popFromCTSWorkList()
Definition MHP.h:266
void handleNonCandidateFun(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle non-candidate function.
Definition MHP.cpp:240
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:640
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:705
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:279
static const Option< bool > PrintInterLev
Definition Options.h:155
const_iterator end() const
const ICFGNode * back() const
static double getClk(bool mark=false)
Definition SVFStat.cpp:51
NodeID getId() const
Get ID.
Definition SVFValue.h:158
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>
Definition TCT.h:102
const NodeBS getAncestorThreads(NodeID tid) const
Get all ancestor threads.
Definition TCT.h:330
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:203
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
Definition TCT.h:432
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition TCT.h:268
NodeBS getParentThreads(NodeID tid) const
Get parent threads.
Definition TCT.h:317
PointerAnalysis * getPTA() const
Get PTA.
Definition TCT.h:198
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:175
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
Definition TCT.h:214
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:193
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
Definition TCT.h:353
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:288
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:261
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
Definition TCT.h:218
const FunObjVar * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
Definition TCT.h:382
const CallStrCxtSet & getCxtOfCxtThread(const CxtThread &ct) const
get the contexts of a thread at its spawning sites (fork sites)
Definition TCT.h:374
bool isAliasedForkJoin(PointerAnalysis *pta, const SVFVar *forkArg, const SVFVar *joinArg) const
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
ThreadAPI * getThreadAPI() const
Thread API.
bool isProgEntryFunction(const FunObjVar *)
Program entry function e.g. main.
Definition SVFUtil.cpp:446
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:105
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:441
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition SVFUtil.cpp:153
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
std::vector< u32_t > CallStrCxt
Definition GeneralType.h:96