Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
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 *vfg=nullptr)
 
virtual ~MTASlicerBase ()
 

Protected Member Functions

OrderedSet< const ICFGNode * > sliceDataDependenceOverVFG (const OrderedSet< const SVFStmt * > &seeds, SVFG *vfg)
 
OrderedSet< const VFGNode * > computeDataDependenceSVFGNodes (const OrderedSet< const SVFStmt * > &seeds, SVFG *vfg)
 
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 SVFStmt * > getDependentThreadCreate (const SVFStmt *stmt)
 
OrderedSet< const TCTNode * > getTCTNodeSetFromNode (const ICFGNode *node)
 
OrderedSet< const ICFGNode * > getLockSet (const ICFGNode *node)
 
OrderedSet< const CallICFGNode * > collectPthreadStatements (const OrderedSet< const SVFStmt * > &vulnerableStmts)
 
OrderedSet< const CallICFGNode * > collectMutexStatements (const OrderedSet< const SVFStmt * > &vulnerableStmts)
 
std::pair< OrderedSet< const CallICFGNode * >, OrderedSet< const CallICFGNode * > > collectCommonThreadStatements (const OrderedSet< const SVFStmt * > &vulnerableStatements)
 
OrderedSet< const ICFGNode * > buildBackwardICFGNodeSet (const OrderedSet< const ICFGNode * > &vulnerableNodes)
 
OrderedSet< const ICFGNode * > expandCallDependence (const OrderedSet< const ICFGNode * > &nodes)
 
OrderedSet< const ICFGNode * > runDualSlicing (const OrderedSet< const ICFGNode * > &slicedNodes)
 

Protected Attributes

SVFIRsvfIr
 
AndersenBasepta
 
MHPmhp
 
LockAnalysislockAnalysis
 
CallGraphcallGraph
 
SVFGvfg
 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 119 of file MTASlicer.h.

Constructor & Destructor Documentation

◆ MTASlicerBase()

SVF::MTASlicerBase::MTASlicerBase ( SVFIR svfIr,
AndersenBase pta,
MHP mhp,
LockAnalysis lockAnalysis,
SVFG vfg = nullptr 
)

Definition at line 410 of file MTASlicer.cpp.

413{
415}
SVFG * vfg
thread-aware VFG_pre (PTA/Single slicers; null for MTA)
Definition MTASlicer.h:132
AndersenBase * pta
Definition MTASlicer.h:128
LockAnalysis * lockAnalysis
Definition MTASlicer.h:130
CallGraph * callGraph
Definition MTASlicer.h:131
CallGraph * getCallGraph() const
Return call graph.

◆ ~MTASlicerBase()

SVF::MTASlicerBase::~MTASlicerBase ( )
virtual

Definition at line 417 of file MTASlicer.cpp.

418{
419 // No dynamic memory to clean up - all pointers are managed externally
420}

Member Function Documentation

◆ buildBackwardICFGNodeSet()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::buildBackwardICFGNodeSet ( const OrderedSet< const ICFGNode * > &  vulnerableNodes)
protected

Definition at line 747 of file MTASlicer.cpp.

749{
751 std::deque<const ICFGNode*> worklist;
752
753 // Initialize with vulnerable nodes
754 for (const ICFGNode* node : vulnerableNodes)
755 {
756 backwardICFGNodeSet.insert(node);
757 worklist.push_back(node);
758 }
759
760 // Traverse backward along ICFG edges
761 while (!worklist.empty())
762 {
763 const ICFGNode* currICFGNode = worklist.front();
764 worklist.pop_front();
765
766 for (const ICFGEdge* inEdge : currICFGNode->getInEdges())
767 {
768 const ICFGNode* srcNode = inEdge->getSrcNode();
770 {
772 worklist.push_back(srcNode);
773 }
774 }
775 }
776
777 return backwardICFGNodeSet;
778}
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ collectCommonThreadStatements()

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

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

Parameters
vulnerableStatementsSet of vulnerable statements
Returns
Pair of (pthreadCallNodes, mutexCallNodes)

Definition at line 700 of file MTASlicer.cpp.

701{
702 // Step 1: Collect pthread-related statements, i.e., pthread_create and pthread_join
704
705 // Step 2: Collect mutex-related statements
707
708 return std::make_pair(pthreadCallNodes, mutexCallNodes);
709}
OrderedSet< const CallICFGNode * > collectMutexStatements(const OrderedSet< const SVFStmt * > &vulnerableStmts)
OrderedSet< const CallICFGNode * > collectPthreadStatements(const OrderedSet< const SVFStmt * > &vulnerableStmts)

◆ collectMutexStatements()

OrderedSet< const CallICFGNode * > SVF::MTASlicerBase::collectMutexStatements ( const OrderedSet< const SVFStmt * > &  vulnerableStmts)
protected

Definition at line 643 of file MTASlicer.cpp.

645{
647
650
651 // Map mutex_lock nodes to their corresponding mutex_unlock nodes
653
654 // First pass: collect all mutex_lock nodes from lock sets
655 for (const SVFStmt* stmt : vulnerableStmts)
656 {
657 OrderedSet<const ICFGNode*> lockSet = getLockSet(stmt->getICFGNode());
658 for (const ICFGNode* lockNode : lockSet)
659 {
660 const CallICFGNode* lockCallNode = SVFUtil::dyn_cast<CallICFGNode>(lockNode);
661 if (lockCallNode != nullptr && threadAPI->isTDAcquire(lockCallNode))
662 {
665 }
666 }
667 }
668
669 // Second pass: find corresponding mutex_unlock nodes
670 ICFG* icfg = svfIr->getICFG();
671 for (ICFG::iterator it = icfg->begin(), eit = icfg->end(); it != eit; ++it)
672 {
673 const ICFGNode* node = it->second;
674 const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node);
675 if (callNode != nullptr && threadAPI->isTDRelease(callNode))
676 {
677 const SVFVar* unlockVar = threadAPI->getLockVal(callNode);
678 if (unlockVar != nullptr)
679 {
681 {
682 if (lockCallNode != nullptr)
683 {
684 const SVFVar* lockVar = threadAPI->getLockVal(lockCallNode);
685 if (lockVar != nullptr && pta->alias(unlockVar->getId(), lockVar->getId()))
686 {
687 mutexCallNodes.insert(callNode);
688 }
689 }
690 }
691 }
692 }
693 }
694
695 return mutexCallNodes;
696}
AliasResult alias(const SVFVar *V1, const SVFVar *V2) override
Interface expose to users of our pointer analysis, given Value infos.
iterator begin()
Iterators.
ICFGNodeIDToNodeMapTy::iterator iterator
Definition ICFG.h:58
ThreadCallGraph * getThreadCallGraph() const
Get ThreadCallGraph.
Definition MHP.h:89
OrderedSet< const ICFGNode * > getLockSet(const ICFGNode *node)
ICFG * getICFG() const
Definition SVFIR.h:231
ThreadAPI * getThreadAPI() const
Thread API.

◆ collectPthreadStatements()

OrderedSet< const CallICFGNode * > SVF::MTASlicerBase::collectPthreadStatements ( const OrderedSet< const SVFStmt * > &  vulnerableStmts)
protected

Definition at line 583 of file MTASlicer.cpp.

585{
587
590
591 // Map pthread_create nodes to their corresponding pthread_join nodes
593
594 // First pass: collect all pthread_create nodes
595 for (const SVFStmt* stmt : vulnerableStmts)
596 {
598
599 for (const SVFStmt* forkSiteStmt : forkSiteStmts)
600 {
601 const ICFGNode* forkSiteNode = forkSiteStmt->getICFGNode();
602 const CallICFGNode* forkCallNode = SVFUtil::dyn_cast<CallICFGNode>(forkSiteNode);
603 if (forkCallNode != nullptr && threadAPI->isTDFork(forkCallNode))
604 {
607 }
608 }
609 }
610
611 // Second pass: find corresponding pthread_join nodes
612 ICFG* icfg = svfIr->getICFG();
613 for (ICFG::iterator it = icfg->begin(), eit = icfg->end(); it != eit; ++it)
614 {
615 const ICFGNode* node = it->second;
616 const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node);
617 if (callNode != nullptr && threadAPI->isTDJoin(callNode))
618 {
619 const SVFVar* joinThread = threadAPI->getJoinedThread(callNode);
620 if (joinThread != nullptr)
621 {
622 for (auto& createStmt : pthreadCreateStmts)
623 {
624 const ICFGNode* createNode = createStmt->getICFGNode();
625 const CallICFGNode* createCallNode = SVFUtil::dyn_cast<CallICFGNode>(createNode);
626 if (createCallNode != nullptr)
627 {
628 const SVFVar* forkedThread = threadAPI->getForkedThread(createCallNode);
629 if (forkedThread != nullptr && threadAPI->isAliasedForkJoin(pta, forkedThread, joinThread))
630 {
632 }
633 }
634 }
635 }
636 }
637 }
638
639 return pthreadCallNodes;
640}
OrderedSet< const SVFStmt * > getDependentThreadCreate(const SVFStmt *stmt)

◆ computeDataDependenceSVFGNodes()

OrderedSet< const SVFGNode * > SVF::MTASlicerBase::computeDataDependenceSVFGNodes ( const OrderedSet< const SVFStmt * > &  seeds,
SVFG vfg 
)
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 507 of file MTASlicer.cpp.

509{
510
511 assert(vfg != nullptr && "data-dependence slice requires the thread-aware VFG_pre");
512
514 std::deque<const SVFGNode*> worklist;
515 auto seed = [&](const SVFGNode* n)
516 {
517 if (n != nullptr && visited.insert(n).second)
518 worklist.push_back(n);
519 };
520
521 // Seed from the value-flow nodes of the given (e.g. race target) statements.
522 // VFG_pre is a pointer-only SVFG, so a load/store of a NON-pointer value (the
523 // usual case -- a race on an int/float field) has no statement node. For those
524 // we must still preserve the points-to of the dereferenced address pointer, or
525 // the sliced flow-sensitive solve sees an empty slice for it, computes empty
526 // points-to, and drops the race (a soundness bug). So additionally seed from the
527 // definition of each load/store's address pointer (always a pointer, hence
528 // always in the pointer-only SVFG); its backward closure keeps the pointer's
529 // def chain regardless of the value type.
530 for (const SVFStmt* stmt : seeds)
531 {
532 if (vfg->hasStmtVFGNode(stmt))
533 seed(vfg->getStmtVFGNode(stmt));
534
535 NodeID addrPtr = 0;
536 if (const LoadStmt* ld = SVFUtil::dyn_cast<LoadStmt>(stmt))
537 addrPtr = ld->getRHSVarID();
538 else if (const StoreStmt* st = SVFUtil::dyn_cast<StoreStmt>(stmt))
539 addrPtr = st->getLHSVarID();
540 if (addrPtr != 0)
541 {
542 // getDefSVFGNode takes a ValVar (the address pointer is a top-level
543 // value variable).
544 const ValVar* ptrNode = SVFUtil::dyn_cast<ValVar>(svfIr->getGNode(addrPtr));
545 if (ptrNode != nullptr && vfg->hasDefSVFGNode(ptrNode))
547 }
548 }
549
550 // Backward over every value-flow edge.
551 while (!worklist.empty())
552 {
553 const SVFGNode* n = worklist.front();
554 worklist.pop_front();
555 for (const VFGEdge* e : n->getInEdges())
556 seed(e->getSrcNode());
557 }
558
559 return visited;
560}
cJSON * n
Definition cJSON.cpp:2558
NodeType * getGNode(NodeID id) const
Get a node.
bool hasDefSVFGNode(const ValVar *valVar) const
Given a valVar, return whether it has definition site.
Definition SVFG.h:177
const SVFGNode * getDefSVFGNode(const ValVar *valVar) const
Given a valVar, return its definition site.
Definition SVFG.h:171
bool hasStmtVFGNode(const SVFStmt *svfStmt) const
Existence checks for VFGNodes.
Definition VFG.h:217
StmtVFGNode * getStmtVFGNode(const SVFStmt *svfStmt) const
Get an VFGNode.
Definition VFG.h:261
u32_t NodeID
Definition GeneralType.h:76

◆ 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 815 of file MTASlicer.cpp.

817{
818
819 // Determine keptFunctions from the given nodes
821 for (const ICFGNode* node : nodes)
822 {
823 if (node != nullptr && node->getFun() != nullptr)
824 {
825 keptFunctions.insert(node->getFun());
826 }
827 }
828
829 // Build ancestor closure (upward traversal in call graph)
830 std::queue<const FunObjVar*> worklistFuncs;
831 for (const FunObjVar* fun : keptFunctions)
832 {
833 worklistFuncs.push(fun);
834 }
835
837 for (auto it = callGraph->begin(), eit = callGraph->end(); it != eit; ++it)
838 {
839 const CallGraphNode* node = it->second;
840 if (node && node->getFunction())
841 {
842 fun2Node[node->getFunction()] = node;
843 }
844 }
845
847 while (!worklistFuncs.empty())
848 {
849 const FunObjVar* target = worklistFuncs.front();
850 worklistFuncs.pop();
851 auto nodeIt = fun2Node.find(target);
852 if (nodeIt == fun2Node.end()) continue;
853
854 const CallGraphNode* node = nodeIt->second;
855 for (const CallGraphEdge* inEdge : node->getInEdges())
856 {
857 if (inEdge == nullptr) continue;
858 const CallGraphNode* callerNode = inEdge->getSrcNode();
859 if (callerNode && callerNode->getFunction())
860 {
862 if (visitedFuncs.find(callerFun) == visitedFuncs.end())
863 {
864 keptFunctions.insert(callerFun);
865 visitedFuncs.insert(callerFun);
867 }
868 }
869 }
870 }
871
872 // For each keptFunction, add call/ret nodes and entry/exit nodes
873 ICFG* icfg = svfIr->getICFG();
875 for (const FunObjVar* fun : keptFunctions)
876 {
877 if (!fun) continue;
878
879 // Add function entry/exit nodes
880 if (fun->hasBasicBlock())
881 {
882 if (FunEntryICFGNode* entry = icfg->getFunEntryICFGNode(fun))
883 {
884 expandedNodes.insert(entry);
885 }
886 if (FunExitICFGNode* exit = icfg->getFunExitICFGNode(fun))
887 {
888 expandedNodes.insert(exit);
889 }
890 }
891
892 // Find all call/ret nodes that call this function
893 auto funNodeIt = fun2Node.find(fun);
894 if (funNodeIt != fun2Node.end())
895 {
896 const CallGraphNode* calleeNode = funNodeIt->second;
897
898 // Traverse all edges that call this function
899 for (const CallGraphEdge* inEdge : calleeNode->getInEdges())
900 {
901 if (inEdge == nullptr) continue;
902
903 const CallGraphEdge::CallInstSet &directCalls = inEdge->getDirectCalls();
904 const CallGraphEdge::CallInstSet &indirectCalls = inEdge->getIndirectCalls();
905
906 for (const CallICFGNode* callNode : directCalls)
907 {
908 if (callNode != nullptr)
909 {
910 expandedNodes.insert(callNode);
911 const RetICFGNode* retNode = callNode->getRetICFGNode();
912 if (retNode != nullptr)
913 {
914 expandedNodes.insert(retNode);
915 }
916 }
917 }
918
919 for (const CallICFGNode* callNode : indirectCalls)
920 {
921 if (callNode != nullptr)
922 {
923 expandedNodes.insert(callNode);
924 const RetICFGNode* retNode = callNode->getRetICFGNode();
925 if (retNode != nullptr)
926 {
927 expandedNodes.insert(retNode);
928 }
929 }
930 }
931 }
932 }
933 }
934
935 return expandedNodes;
936}
Set< const CallICFGNode * > CallInstSet
Definition CallGraph.h:55
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const SVFBasicBlock * front() const
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
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)

◆ getDependentThreadCreate()

OrderedSet< const SVFStmt * > SVF::MTASlicerBase::getDependentThreadCreate ( const SVFStmt stmt)
protected

Definition at line 479 of file MTASlicer.cpp.

480{
482
483 const ICFGNode* icfgNode = stmt->getICFGNode();
485
486 for (const TCTNode* tctNode : tctNodeSet)
487 {
488 const CxtThread& cxtThread = tctNode->getCxtThread();
489 const ICFGNode* forkSite = cxtThread.getThread();
490 if (forkSite != nullptr)
491 {
493 if (!svfStmts.empty())
494 {
495 forkSiteStmts.insert(svfStmts.front());
496 }
497 }
498 }
499
500 return forkSiteStmts;
501}
std::list< const SVFStmt * > SVFStmtList
Definition ICFGNode.h:65
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:116
OrderedSet< const TCTNode * > getTCTNodeSetFromNode(const ICFGNode *node)
ICFGNode * getICFGNode() const

◆ getLockSet()

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

Definition at line 423 of file MTASlicer.cpp.

424{
426
427 // Get intra-procedural locks
428 if (lockAnalysis->isInsideIntraLock(node) &&
430 {
432 for (const ICFGNode* lockSite : intraLocks)
433 {
434 allLockSites.insert(lockSite);
435 }
436 }
437
438 // Get context-sensitive locks
440 {
442 for (const CxtStmt& cxtStmt : cxtStmts)
443 {
445 {
449 {
450 allLockSites.insert(cxtLock.getStmt());
451 }
452 }
453 }
454 }
455
456 return allLockSites;
457}
Set< CxtLock > CxtLockSet
bool hasCxtLockfromCxtStmt(const CxtStmt &cts) const
Set< CxtStmt > CxtStmtSet
bool isInsideIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside an intra-procedural lock.
bool isInsideCondIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside a partial lock/unlock pair (conditional lock with unconditional ...
const InstSet & getIntraLockSet(const ICFGNode *stmt) const
bool hasCxtStmtFromInst(const ICFGNode *inst) const
Context-sensitive statement and lock spans.
Set< const ICFGNode * > InstSet
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
const CxtLockSet & getCxtLockfromCxtStmt(const CxtStmt &cts) const

◆ getTCTNodeSetFromNode()

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

Definition at line 460 of file MTASlicer.cpp.

461{
463
464 if (mhp->hasThreadStmtSet(node))
465 {
466 for (const CxtThreadStmt& cts : mhp->getThreadStmtSet(node))
467 {
468 if (mhp->getTCT()->hasGNode(cts.getTid()))
469 {
470 tctNodeSet.insert(mhp->getTCT()->getTCTNode(cts.getTid()));
471 }
472 }
473 }
474
475 return tctNodeSet;
476}
bool hasGNode(NodeID id) const
Has a node.
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:130
TCT * getTCT() const
Get Thread Creation Tree.
Definition MHP.h:95
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:203

◆ runDualSlicing()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::runDualSlicing ( const OrderedSet< const ICFGNode * > &  slicedNodes)
protected

Perform dual slicing (temporal slicing): filter statements based on control flow and parallel execution. This is shared by both PTA and MTA slicing.

Parameters
slicedNodesSet of statements from statement-level slicing
Returns
Set of ICFG nodes in the dual slice

Definition at line 781 of file MTASlicer.cpp.

783{
785
786 // Build backward ICFG node set
788
789 // Perform control slicing
790 for (const ICFGNode* stmtICFGNode : slicedNodes)
791 {
792 // Check if the ICFG node is in backward_icfg_node_set
794 {
796 }
797 else
798 {
799 // Check if it may happen in parallel with any vulnerable node
800 for (const ICFGNode* bugICFGNode : slicedNodes)
801 {
803 {
805 break;
806 }
807 }
808 }
809 }
810
811 return dualSlicedNodes;
812}
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:741
OrderedSet< const ICFGNode * > buildBackwardICFGNodeSet(const OrderedSet< const ICFGNode * > &vulnerableNodes)

◆ sliceDataDependenceOverVFG()

OrderedSet< const ICFGNode * > SVF::MTASlicerBase::sliceDataDependenceOverVFG ( const OrderedSet< const SVFStmt * > &  seeds,
SVFG vfg 
)
protected

Paper-faithful (ยง4.3) data-dependence slice over the thread-aware SVFG (VFG_pre): seed from the value-flow nodes of the given statements and backward-traverse every value-flow edge – direct (top-level def-use), indirect (address-taken / MemSSA def-use), and thread-aware interference. Returns the kept ICFG nodes. This is the single dependence model used by the FSPTA stage.

Definition at line 576 of file MTASlicer.cpp.

578{
580}
OrderedSet< const VFGNode * > computeDataDependenceSVFGNodes(const OrderedSet< const SVFStmt * > &seeds, SVFG *vfg)
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.

◆ 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 563 of file MTASlicer.cpp.

565{
567 for (const SVFGNode* n : nodes)
568 if (const StmtVFGNode* s = SVFUtil::dyn_cast<StmtVFGNode>(n))
569 if (s->getICFGNode() != nullptr)
570 result.insert(s->getICFGNode());
571 for (const SVFStmt* stmt : seeds)
572 result.insert(stmt->getICFGNode());
573 return result;
574}
if(prebuffer< 0)
Definition cJSON.cpp:1269
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

Member Data Documentation

◆ callGraph

CallGraph* SVF::MTASlicerBase::callGraph
protected

Definition at line 131 of file MTASlicer.h.

◆ lockAnalysis

LockAnalysis* SVF::MTASlicerBase::lockAnalysis
protected

Definition at line 130 of file MTASlicer.h.

◆ mhp

MHP* SVF::MTASlicerBase::mhp
protected

Definition at line 129 of file MTASlicer.h.

◆ pta

AndersenBase* SVF::MTASlicerBase::pta
protected

Definition at line 128 of file MTASlicer.h.

◆ svfIr

SVFIR* SVF::MTASlicerBase::svfIr
protected

Definition at line 127 of file MTASlicer.h.

◆ vfg

SVFG* SVF::MTASlicerBase::vfg
protected

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

Definition at line 132 of file MTASlicer.h.


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