Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVF::MTASlicerBase Class Reference

#include <MTASlicer.h>

Inheritance diagram for SVF::MTASlicerBase:
SVF::MultiStageSlicer SVF::SingleSlicer

Public Member Functions

 MTASlicerBase (SVFIR *svfir, AndersenBase *pta, MHP *mhp, LockAnalysis *lockAnalysis, SVFG *svfg=nullptr)

Protected Member Functions

OrderedSet< const VFGNode * > computeDataDependenceSVFGNodes (const OrderedSet< const SVFStmt * > &seeds, SVFG *svfg)
OrderedSet< const ICFGNode * > svfgNodesToICFGNodes (const OrderedSet< const VFGNode * > &nodes, const OrderedSet< const SVFStmt * > &seeds)
 Project the retained VFG nodes (plus the seeds) onto their ICFG nodes.
OrderedSet< const CallICFGNode * > getDependentThreadCreate (const ICFGNode *node)
OrderedSet< const TCTNode * > getTCTNodeSetFromNode (const ICFGNode *node)
OrderedSet< const ICFGNode * > getLockSet (const ICFGNode *node)
OrderedSet< const CallICFGNode * > collectPthreadStatements (const OrderedSet< const ICFGNode * > &sourceNodes)
OrderedSet< const CallICFGNode * > collectMutexStatements (const OrderedSet< const ICFGNode * > &sourceNodes)
std::pair< OrderedSet< const CallICFGNode * >, OrderedSet< const CallICFGNode * > > collectCommonThreadStatements (const OrderedSet< const ICFGNode * > &sourceNodes)
void addSynchronizationDependencies (const OrderedSet< const CallICFGNode * > &pthreadCallNodes, const OrderedSet< const CallICFGNode * > &mutexCallNodes, OrderedSet< const ICFGNode * > &retainedNodes)
OrderedSet< const ICFGNode * > expandCallDependence (const OrderedSet< const ICFGNode * > &nodes)

Static Protected Member Functions

static void enqueueSVFGNode (const SVFGNode *node, OrderedSet< const SVFGNode * > &visited, std::deque< const SVFGNode * > &worklist)

Protected Attributes

SVFIR * svfir
AndersenBase * pta
MHP * mhp
LockAnalysis * lockAnalysis
CallGraph * callGraph
SVFG * svfg
 thread-aware VFG_pre (PTA/Single slicers; null for MTA)

Detailed Description

MTASlicerBase - Base class for program slicing.

Holds the shared helper methods and data members used by both concrete slicers (the ILA and FSPTA stages of MultiStageSlicer).

Definition at line 121 of file MTASlicer.h.

Constructor & Destructor Documentation

◆ MTASlicerBase()

SVF::MTASlicerBase::MTASlicerBase ( SVFIR * svfir,
AndersenBase * pta,
MHP * mhp,
LockAnalysis * lockAnalysis,
SVFG * svfg = nullptr )

Definition at line 300 of file MTASlicer.cpp.

303{
304 callGraph = pta->getCallGraph();
305}
AndersenBase * pta
Definition MTASlicer.h:129
LockAnalysis * lockAnalysis
Definition MTASlicer.h:131
CallGraph * callGraph
Definition MTASlicer.h:132
SVFG * svfg
thread-aware VFG_pre (PTA/Single slicers; null for MTA)
Definition MTASlicer.h:133

Member Function Documentation

◆ addSynchronizationDependencies()

void SVF::MTASlicerBase::addSynchronizationDependencies ( const OrderedSet< const CallICFGNode * > & pthreadCallNodes,
const OrderedSet< const CallICFGNode * > & mutexCallNodes,
OrderedSet< const ICFGNode * > & retainedNodes )
protected

Add synchronization primitives and the control-flow anchors required by the sliced MHP/lock analyses.

Definition at line 625 of file MTASlicer.cpp.

629{
630 for (const CallICFGNode* callNode : pthreadCallNodes)
631 {
632 sliceResult.insert(callNode);
633 if (callNode->getRetICFGNode() != nullptr)
634 sliceResult.insert(callNode->getRetICFGNode());
635 }
636 for (const CallICFGNode* callNode : mutexCallNodes)
637 {
638 sliceResult.insert(callNode);
639 if (callNode->getRetICFGNode() != nullptr)
640 sliceResult.insert(callNode->getRetICFGNode());
641 }
642
643 for (const CallICFGNode* mutexCallNode : mutexCallNodes)
644 {
645 const FunObjVar* fun = mutexCallNode->getFun();
646 if (fun == nullptr)
647 continue;
648 if (const SVFBasicBlock* entry = fun->getEntryBlock())
649 {
650 sliceResult.insert(entry->front());
651 sliceResult.insert(entry->back());
652 }
653 if (const SVFBasicBlock* exit = fun->getExitBB())
654 sliceResult.insert(exit->back());
655 }
656
657 ThreadAPI* threadAPI = mhp->getThreadCallGraph()->getThreadAPI();
658 for (const CallICFGNode* callNode : pthreadCallNodes)
659 {
660 if (!threadAPI->isTDJoin(callNode) || callNode->getBB() == nullptr)
661 continue;
662 std::vector<const SVFBasicBlock*> exitBlocks;
663 callNode->getFun()->getExitBlocksOfLoop(callNode->getBB(), exitBlocks);
664 for (const SVFBasicBlock* exitBlock : exitBlocks)
665 if (!exitBlock->getICFGNodeList().empty())
666 sliceResult.insert(exitBlock->front());
667 }
668}
const SVFBasicBlock * getEntryBlock() const
const SVFBasicBlock * getExitBB() const
bool isTDJoin(const CallICFGNode *inst) const
Return true if this call wait for a worker thread.

◆ collectCommonThreadStatements()

std::pair< OrderedSet< const CallICFGNode * >, OrderedSet< const CallICFGNode * > > SVF::MTASlicerBase::collectCommonThreadStatements ( const OrderedSet< const ICFGNode * > & sourceNodes)
protected

Collect common pthread and mutex statements (shared by PTA and MTA slicing).

Parameters
sourceNodesComplete ILA source set ([INIT] union [THREAD-VF])
Returns
Pair of (pthreadCallNodes, mutexCallNodes)

Definition at line 595 of file MTASlicer.cpp.

597{
598 // Step 1: Collect pthread-related statements, i.e., pthread_create and pthread_join
599 OrderedSet<const CallICFGNode*> pthreadCallNodes =
600 collectPthreadStatements(sourceNodes);
601
602 // Step 2: Collect mutex-related statements
603 OrderedSet<const CallICFGNode*> mutexCallNodes =
604 collectMutexStatements(sourceNodes);
605
606 return std::make_pair(pthreadCallNodes, mutexCallNodes);
607}
OrderedSet< const CallICFGNode * > collectMutexStatements(const OrderedSet< const ICFGNode * > &sourceNodes)
OrderedSet< const CallICFGNode * > collectPthreadStatements(const OrderedSet< const ICFGNode * > &sourceNodes)
std::set< Key, Compare, Allocator > OrderedSet
Definition GeneralType.h:60

◆ collectMutexStatements()

OrderedSet< const CallICFGNode * > SVF::MTASlicerBase::collectMutexStatements ( const OrderedSet< const ICFGNode * > & sourceNodes)
protected

Definition at line 534 of file MTASlicer.cpp.

536{
537 OrderedSet<const CallICFGNode*> mutexCallNodes;
538
539 ThreadCallGraph* tcg = mhp->getThreadCallGraph();
540 ThreadAPI* threadAPI = tcg->getThreadAPI();
541
542 // Map mutex_lock nodes to their corresponding mutex_unlock nodes
543 OrderedSet<const CallICFGNode*> mutexLockCallNodes;
544
545 // First pass: collect all mutex_lock nodes from lock sets
546 for (const ICFGNode* sourceNode : sourceNodes)
547 {
548 OrderedSet<const ICFGNode*> lockSet = getLockSet(sourceNode);
549 for (const ICFGNode* lockNode : lockSet)
550 {
551 const CallICFGNode* lockCallNode =
553 if (lockCallNode != nullptr &&
554 threadAPI->isTDAcquire(lockCallNode))
555 {
556 mutexCallNodes.insert(lockCallNode);
557 mutexLockCallNodes.insert(lockCallNode);
558 }
559 }
560 }
561
562 // Second pass: find corresponding mutex_unlock nodes
563 ICFG* icfg = svfir->getICFG();
564 for (ICFG::iterator it = icfg->begin(), eit = icfg->end();
565 it != eit; ++it)
566 {
567 const ICFGNode* node = it->second;
568 const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node);
569 if (callNode != nullptr && threadAPI->isTDRelease(callNode))
570 {
571 const SVFVar* unlockVar = threadAPI->getLockVal(callNode);
572 if (unlockVar != nullptr)
573 {
574 for (const CallICFGNode* lockCallNode : mutexLockCallNodes)
575 {
576 if (lockCallNode != nullptr)
577 {
578 const SVFVar* lockVar = threadAPI->getLockVal(lockCallNode);
579 if (lockVar != nullptr &&
580 pta->alias(unlockVar->getId(), lockVar->getId()))
581 {
582 mutexCallNodes.insert(callNode);
583 }
584 }
585 }
586 }
587 }
588 }
589
590 return mutexCallNodes;
591}
iterator begin()
Iterators.
ICFGNodeIDToNodeMapTy::iterator iterator
Definition ICFG.h:58
OrderedSet< const ICFGNode * > getLockSet(const ICFGNode *node)
NodeID getId() const
Get ID.
Definition SVFValue.h:158
bool isTDRelease(const CallICFGNode *inst) const
Return true if this call release a lock.
const SVFVar * getLockVal(const ICFGNode *inst) const
Return lock value.
bool isTDAcquire(const CallICFGNode *inst) const
Return true if this call acquire a lock.
ThreadAPI * getThreadAPI() const
Thread API.
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405

◆ collectPthreadStatements()

OrderedSet< const CallICFGNode * > SVF::MTASlicerBase::collectPthreadStatements ( const OrderedSet< const ICFGNode * > & sourceNodes)
protected

Definition at line 481 of file MTASlicer.cpp.

483{
484 OrderedSet<const CallICFGNode*> pthreadCallNodes;
485
486 ThreadCallGraph* tcg = mhp->getThreadCallGraph();
487 ThreadAPI* threadAPI = tcg->getThreadAPI();
488
489 // Map pthread_create nodes to their corresponding pthread_join nodes
490 OrderedSet<const CallICFGNode*> pthreadCreateNodes;
491
492 // First pass: collect all pthread_create nodes
493 for (const ICFGNode* sourceNode : sourceNodes)
494 {
496 getDependentThreadCreate(sourceNode);
497 for (const CallICFGNode* forkCallNode : forkSites)
498 {
499 pthreadCallNodes.insert(forkCallNode);
500 pthreadCreateNodes.insert(forkCallNode);
501 }
502 }
503
504 // Second pass: find corresponding pthread_join nodes
505 ICFG* icfg = svfir->getICFG();
506 for (ICFG::iterator it = icfg->begin(), eit = icfg->end();
507 it != eit; ++it)
508 {
509 const ICFGNode* node = it->second;
510 const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node);
511 if (callNode != nullptr && threadAPI->isTDJoin(callNode))
512 {
513 const SVFVar* joinThread = threadAPI->getJoinedThread(callNode);
514 if (joinThread != nullptr)
515 {
516 for (const CallICFGNode* createCallNode : pthreadCreateNodes)
517 {
518 const SVFVar* forkedThread = threadAPI->getForkedThread(createCallNode);
519 if (forkedThread != nullptr &&
520 threadAPI->isAliasedForkJoin(
521 pta, forkedThread, joinThread))
522 {
523 pthreadCallNodes.insert(callNode);
524 }
525 }
526 }
527 }
528 }
529
530 return pthreadCallNodes;
531}
OrderedSet< const CallICFGNode * > getDependentThreadCreate(const ICFGNode *node)
const ValVar * getForkedThread(const CallICFGNode *inst) const
Return arguments/attributes of pthread_create / hare_parallel_for.
const SVFVar * getJoinedThread(const CallICFGNode *inst) const
Return arguments/attributes of pthread_join.
bool isAliasedForkJoin(PointerAnalysis *pta, const SVFVar *forkArg, const SVFVar *joinArg) const

◆ computeDataDependenceSVFGNodes()

OrderedSet< const SVFGNode * > SVF::MTASlicerBase::computeDataDependenceSVFGNodes ( const OrderedSet< const SVFStmt * > & seeds,
SVFG * svfg )
protected

The SVFG-node granularity of the data-dependence slice above: the set of VFG nodes reachable backward from the seeds. ThreadVF(VFG'_pre) is exactly the thread-aware edges whose both endpoints lie in this set, so ILA slicing uses it to restrict the [THREAD-VF] sources to surviving edges.

Definition at line 405 of file MTASlicer.cpp.

407{
408
409 assert(svfg != nullptr && "data-dependence slice requires the thread-aware VFG_pre");
410
412 std::deque<const SVFGNode*> worklist;
413
414 // Seed from the value-flow nodes of the given (e.g. race target) statements.
415 // VFG_pre is a pointer-only SVFG, so a load/store of a NON-pointer value (the
416 // usual case -- a race on an int/float field) has no statement node. For those
417 // we must still preserve the points-to of the dereferenced address pointer, or
418 // the sliced flow-sensitive solve sees an empty slice for it, computes empty
419 // points-to, and drops the race (a soundness bug). So additionally seed from the
420 // definition of each load/store's address pointer (always a pointer, hence
421 // always in the pointer-only SVFG); its backward closure keeps the pointer's
422 // def chain regardless of the value type.
423 for (const SVFStmt* stmt : seeds)
424 {
425 if (svfg->hasStmtVFGNode(stmt))
426 enqueueSVFGNode(svfg->getStmtVFGNode(stmt), visited, worklist);
427
428 NodeID addrPtr = 0;
429 if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
430 addrPtr = load->getRHSVarID();
431 else if (const StoreStmt* store = SVFUtil::dyn_cast<StoreStmt>(stmt))
432 addrPtr = store->getLHSVarID();
433 if (addrPtr != 0)
434 {
435 // getDefSVFGNode takes a ValVar (the address pointer is a top-level
436 // value variable).
437 const ValVar* ptrNode = SVFUtil::dyn_cast<ValVar>(svfir->getGNode(addrPtr));
438 if (ptrNode != nullptr && svfg->hasDefSVFGNode(ptrNode))
439 enqueueSVFGNode(svfg->getDefSVFGNode(ptrNode), visited, worklist);
440 }
441 }
442
443 // Backward over every value-flow edge.
444 while (!worklist.empty())
445 {
446 const SVFGNode* node = worklist.front();
447 worklist.pop_front();
448 for (const VFGEdge* edge : node->getInEdges())
449 enqueueSVFGNode(edge->getSrcNode(), visited, worklist);
450 }
451
452 return visited;
453}
const GEdgeSetTy & getInEdges() const
static void enqueueSVFGNode(const SVFGNode *node, OrderedSet< const SVFGNode * > &visited, std::deque< const SVFGNode * > &worklist)
u32_t NodeID
Definition GeneralType.h:76
VFGNode SVFGNode
Definition SVFG.h:43

◆ enqueueSVFGNode()

void SVF::MTASlicerBase::enqueueSVFGNode ( const SVFGNode * node,
OrderedSet< const SVFGNode * > & visited,
std::deque< const SVFGNode * > & worklist )
staticprotected

Definition at line 455 of file MTASlicer.cpp.

458{
459 if (node != nullptr && visited.insert(node).second)
460 worklist.push_back(node);
461}

◆ expandCallDependence()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::expandCallDependence ( const OrderedSet< const ICFGNode * > & nodes)
protected

Call-dependence expansion (used by MultiStageSlicer): take the kept functions of the given nodes, close upward over the call graph (every transitive caller), then add each kept function's entry/exit nodes and the call/ret nodes of every call site targeting it.

Parameters
nodesCurrent set of ICFG nodes
Returns
The input nodes plus the call/ret and entry/exit nodes above

Definition at line 671 of file MTASlicer.cpp.

673{
674
675 // Determine keptFunctions from the given nodes
676 OrderedSet<const FunObjVar*> keptFunctions;
677 for (const ICFGNode* node : nodes)
678 {
679 if (node != nullptr && node->getFun() != nullptr)
680 {
681 keptFunctions.insert(node->getFun());
682 }
683 }
684
685 // Build ancestor closure (upward traversal in call graph)
686 std::queue<const FunObjVar*> functionWorklist;
687 for (const FunObjVar* fun : keptFunctions)
688 functionWorklist.push(fun);
689
691 for (auto it = callGraph->begin(), eit = callGraph->end();
692 it != eit; ++it)
693 {
694 const CallGraphNode* node = it->second;
695 if (node != nullptr && node->getFunction() != nullptr)
696 functionToNode[node->getFunction()] = node;
697 }
698
699 OrderedSet<const FunObjVar*> visitedFunctions = keptFunctions;
700 while (!functionWorklist.empty())
701 {
702 const FunObjVar* target = functionWorklist.front();
703 functionWorklist.pop();
704 const auto nodeIt = functionToNode.find(target);
705 if (nodeIt == functionToNode.end())
706 continue;
707
708 const CallGraphNode* node = nodeIt->second;
709 for (const CallGraphEdge* inEdge : node->getInEdges())
710 {
711 if (inEdge == nullptr)
712 continue;
713 const CallGraphNode* callerNode = inEdge->getSrcNode();
714 if (callerNode != nullptr && callerNode->getFunction() != nullptr)
715 {
716 const FunObjVar* callerFun = callerNode->getFunction();
717 if (visitedFunctions.find(callerFun) == visitedFunctions.end())
718 {
719 keptFunctions.insert(callerFun);
720 visitedFunctions.insert(callerFun);
721 functionWorklist.push(callerFun);
722 }
723 }
724 }
725 }
726
727 // For each keptFunction, add call/ret nodes and entry/exit nodes
728 ICFG* icfg = svfir->getICFG();
729 OrderedSet<const ICFGNode*> expandedNodes = nodes;
730 for (const FunObjVar* fun : keptFunctions)
731 {
732 if (fun == nullptr)
733 continue;
734
735 // Add function entry/exit nodes
736 if (fun->hasBasicBlock())
737 {
738 if (FunEntryICFGNode* entry = icfg->getFunEntryICFGNode(fun))
739 expandedNodes.insert(entry);
740 if (FunExitICFGNode* exit = icfg->getFunExitICFGNode(fun))
741 expandedNodes.insert(exit);
742 }
743
744 // Find all call/ret nodes that call this function
745 const auto funNodeIt = functionToNode.find(fun);
746 if (funNodeIt != functionToNode.end())
747 {
748 const CallGraphNode* calleeNode = funNodeIt->second;
749
750 // Traverse all edges that call this function
751 for (const CallGraphEdge* inEdge : calleeNode->getInEdges())
752 {
753 if (inEdge == nullptr)
754 continue;
755
756 const CallGraphEdge::CallInstSet& directCalls =
757 inEdge->getDirectCalls();
758 const CallGraphEdge::CallInstSet& indirectCalls =
759 inEdge->getIndirectCalls();
760
761 for (const CallICFGNode* callNode : directCalls)
762 {
763 if (callNode != nullptr)
764 {
765 expandedNodes.insert(callNode);
766 const RetICFGNode* retNode = callNode->getRetICFGNode();
767 if (retNode != nullptr)
768 expandedNodes.insert(retNode);
769 }
770 }
771
772 for (const CallICFGNode* callNode : indirectCalls)
773 {
774 if (callNode != nullptr)
775 {
776 expandedNodes.insert(callNode);
777 const RetICFGNode* retNode = callNode->getRetICFGNode();
778 if (retNode != nullptr)
779 expandedNodes.insert(retNode);
780 }
781 }
782 }
783 }
784 }
785
786 return expandedNodes;
787}
Set< const CallICFGNode * > CallInstSet
Definition CallGraph.h:55
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:250
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:243
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)

◆ getDependentThreadCreate()

OrderedSet< const CallICFGNode * > SVF::MTASlicerBase::getDependentThreadCreate ( const ICFGNode * node)
protected

Definition at line 375 of file MTASlicer.cpp.

377{
380 ThreadAPI* threadAPI = mhp->getThreadCallGraph()->getThreadAPI();
381
382 TCT* tct = mhp->getTCT();
383 for (const TCTNode* tctNode : tctNodeSet)
384 {
385 NodeBS dependentThreads = tct->getAncestorThreads(tctNode->getId());
386 dependentThreads.set(tctNode->getId());
387 for (NodeID tid : dependentThreads)
388 {
389 const ICFGNode* forkSite =
390 tct->getTCTNode(tid)->getCxtThread().getThread();
391 const CallICFGNode* forkCall =
393 if (forkCall != nullptr && threadAPI->isTDFork(forkCall))
394 forkSites.insert(forkCall);
395 }
396 }
397
398 return forkSites;
399}
const ICFGNode * getThread() const
Return forksite.
Definition CxtStmt.h:209
OrderedSet< const TCTNode * > getTCTNodeSetFromNode(const ICFGNode *node)
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>.
Definition TCT.h:103
const NodeBS getAncestorThreads(NodeID tid) const
Get all ancestor threads.
Definition TCT.h:336
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:209
bool isTDFork(const CallICFGNode *inst) const
Return true if this call create a new thread.
SparseBitVector NodeBS
Definition GeneralType.h:82

◆ getLockSet()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::getLockSet ( const ICFGNode * node)
protected

Definition at line 308 of file MTASlicer.cpp.

309{
310 OrderedSet<const ICFGNode*> allLockSites;
311
312 // Synchronization dependence is based on may-lock spans. Retain both the
313 // unconditional locks used to prove mutual exclusion and conditional locks
314 // whose spans can affect the sliced lock analysis' classification.
315 if (lockAnalysis->hasIntraLockSet(node))
316 {
317 const LockAnalysis::InstSet& intraLocks = lockAnalysis->getIntraLockSet(node);
318 for (const ICFGNode* lockSite : intraLocks)
319 {
320 allLockSites.insert(lockSite);
321 }
322 }
323 if (lockAnalysis->isInsideCondIntraLock(node))
324 {
325 const LockAnalysis::InstSet& conditionalLocks =
326 lockAnalysis->getCondIntraLockSet(node);
327 for (const ICFGNode* lockSite : conditionalLocks)
328 {
329 allLockSites.insert(lockSite);
330 }
331 }
332
333 // Get context-sensitive locks
334 if (lockAnalysis->hasCxtStmtFromInst(node))
335 {
336 const LockAnalysis::CxtStmtSet& cxtStmts = lockAnalysis->getCxtStmtsFromInst(node);
337 for (const CxtStmt& cxtStmt : cxtStmts)
338 {
339 if (lockAnalysis->hasCxtLockFromCxtStmt(cxtStmt))
340 {
341 const LockAnalysis::CxtLockSet& cxtLocks =
342 lockAnalysis->getCxtLockFromCxtStmt(cxtStmt);
343 for (const LockAnalysis::CxtLock& cxtLock : cxtLocks)
344 {
345 allLockSites.insert(cxtLock.getStmt());
346 }
347 }
348 }
349 }
350
351 return allLockSites;
352}
Set< CxtLock > CxtLockSet
Set< CxtStmt > CxtStmtSet
Set< const ICFGNode * > InstSet

◆ getTCTNodeSetFromNode()

OrderedSet< const TCTNode * > SVF::MTASlicerBase::getTCTNodeSetFromNode ( const ICFGNode * node)
protected

Definition at line 355 of file MTASlicer.cpp.

357{
359
360 if (mhp->hasThreadStmtSet(node))
361 {
362 for (const CxtThreadStmt& cts : mhp->getThreadStmtSet(node))
363 {
364 if (mhp->getTCT()->hasGNode(cts.getTid()))
365 {
366 tctNodeSet.insert(mhp->getTCT()->getTCTNode(cts.getTid()));
367 }
368 }
369 }
370
371 return tctNodeSet;
372}

◆ svfgNodesToICFGNodes()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::svfgNodesToICFGNodes ( const OrderedSet< const VFGNode * > & nodes,
const OrderedSet< const SVFStmt * > & seeds )
protected

Project the retained VFG nodes (plus the seeds) onto their ICFG nodes.

Definition at line 464 of file MTASlicer.cpp.

467{
469 for (const SVFGNode* node : nodes)
470 if (const StmtVFGNode* statementNode =
472 if (statementNode->getICFGNode() != nullptr)
473 result.insert(statementNode->getICFGNode());
474 for (const SVFStmt* stmt : seeds)
475 if (stmt != nullptr && stmt->getICFGNode() != nullptr)
476 result.insert(stmt->getICFGNode());
477 return result;
478}

Member Data Documentation

◆ callGraph

CallGraph* SVF::MTASlicerBase::callGraph
protected

Definition at line 132 of file MTASlicer.h.

◆ lockAnalysis

LockAnalysis* SVF::MTASlicerBase::lockAnalysis
protected

Definition at line 131 of file MTASlicer.h.

◆ mhp

MHP* SVF::MTASlicerBase::mhp
protected

Definition at line 130 of file MTASlicer.h.

◆ pta

AndersenBase* SVF::MTASlicerBase::pta
protected

Definition at line 129 of file MTASlicer.h.

◆ svfg

SVFG* SVF::MTASlicerBase::svfg
protected

thread-aware VFG_pre (PTA/Single slicers; null for MTA)

Definition at line 133 of file MTASlicer.h.

◆ svfir

SVFIR* SVF::MTASlicerBase::svfir
protected

Definition at line 128 of file MTASlicer.h.


The documentation for this class was generated from the following files: