Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Attributes | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
SVF::MTASVFGBuilder Class Reference

#include <MTASVFGBuilder.h>

Inheritance diagram for SVF::MTASVFGBuilder:
SVF::SVFGBuilder

Public Types

typedef Set< const StmtSVFGNode * > SVFGNodeSet
 
typedef NodeBS SVFGNodeIDSet
 
typedef std::pair< const StmtSVFGNode *, const StmtSVFGNode * > ThreadVFEdge
 
- Public Types inherited from SVF::SVFGBuilder
typedef PointerAnalysis::CallSiteSet CallSiteSet
 
typedef PointerAnalysis::CallEdgeMap CallEdgeMap
 
typedef PointerAnalysis::FunctionSet FunctionSet
 
typedef SVFG::SVFGEdgeSetTy SVFGEdgeSet
 

Public Member Functions

 MTASVFGBuilder (MHP *m, LockAnalysis *la)
 Constructor: driven by the interleaving (MHP) and lock analyses.
 
 ~MTASVFGBuilder () override=default
 
void configureForMainSolve (const SlicedICFGView *slice)
 
const std::map< ThreadVFEdge, std::set< const ICFGNode * > > & getThreadVFQueryMap () const
 
- Public Member Functions inherited from SVF::SVFGBuilder
 SVFGBuilder (bool _SVFGWithIndCall=Options::SVFGWithIndirectCall(), bool _SVFGWithPostOpts=Options::OPTSVFG())
 Constructor.
 
virtual ~SVFGBuilder ()=default
 Destructor.
 
SVFGbuildPTROnlySVFG (BVDataPTAImpl *pta)
 
SVFGbuildFullSVFG (BVDataPTAImpl *pta)
 
SVFGgetSVFG () const
 Get SVFG instance.
 
void markValidVFEdge (SVFGEdgeSet &edges)
 Mark feasible VF edge by removing it from set vfEdgesAtIndCallSite.
 
bool isSpuriousVFEdgeAtIndCallSite (const SVFGEdge *edge)
 Return true if this is an VF Edge pre-connected by Andersen's analysis.
 
virtual std::unique_ptr< MemSSAbuildMSSA (BVDataPTAImpl *pta, bool ptrOnlyMSSA)
 Build Memory SSA.
 

Static Public Attributes

static u32_t numOfNewSVFGEdges = 0
 Number of thread-aware (interference) SVFG edges added.
 

Protected Member Functions

void buildSVFG () override
 Rewrite the SVFG build hook: build the stock SVFG, then add MHP edges.
 
std::unique_ptr< MRGeneratorcreateMRGenerator (BVDataPTAImpl *pta, bool ptrOnlyMSSA) override
 
- Protected Member Functions inherited from SVF::SVFGBuilder
SVFGbuild (BVDataPTAImpl *pta, VFG::VFGK kind)
 Create a DDA SVFG. By default actualOut and FormalIN are removed, unless withAOFI is set true.
 
virtual void releaseMemory ()
 Release global SVFG.
 

Private Member Functions

void collectLoadStoreSVFGNodes ()
 
void connectThreadJoinEdges ()
 
void addJoinRetEdge (const FormalOUTSVFGNode *formalOut, const ActualOUTSVFGNode *actualOut, CallSiteID csId)
 
void connectMHPEdges (PointerAnalysis *pta)
 Connect inter-thread (interference) value-flow edges for MHP pairs.
 
void handleStoreLoad (const StmtSVFGNode *n1, const StmtSVFGNode *n2, PointerAnalysis *pta)
 
void handleStoreStore (const StmtSVFGNode *n1, const StmtSVFGNode *n2, PointerAnalysis *pta)
 
void recordThreadVFSource (const StmtSVFGNode *s, const StmtSVFGNode *sp, bool commonLock)
 
SVFGEdgeaddTDEdge (NodeID srcId, NodeID dstId, const PointsTo &pts)
 Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.
 
SVFGNodeIDSet getPrevNodes (const StmtSVFGNode *n)
 Lock-span head/tail tests (non-interference lock-pair pruning).
 
SVFGNodeIDSet getSuccNodes (const StmtSVFGNode *n)
 
bool isHeadOfSpan (const StmtSVFGNode *n)
 
bool isTailOfSpan (const StmtSVFGNode *n)
 

Private Attributes

const SlicedICFGViewicfgSlice = nullptr
 Main-solve configuration (see configureForMainSolve); defaults suit VFG_pre.
 
bool recordThreadVF = true
 false = skip [THREAD-VF] recording
 
SVFGNodeSet stnodeSet
 all store SVFG nodes
 
SVFGNodeSet ldnodeSet
 all load SVFG nodes
 
std::map< ThreadVFEdge, std::set< const ICFGNode * > > threadVFQueryMap
 [THREAD-VF] per-edge query map (see getThreadVFQueryMap).
 
MHPmhp
 
LockAnalysislockana
 
Map< const StmtSVFGNode *, SVFGNodeIDSetprevset
 
Map< const StmtSVFGNode *, SVFGNodeIDSetsuccset
 
Map< const StmtSVFGNode *, boolheadmap
 
Map< const StmtSVFGNode *, booltailmap
 

Additional Inherited Members

- Protected Attributes inherited from SVF::SVFGBuilder
SVFGEdgeSet vfEdgesAtIndCallSite
 SVFG Edges connected at indirect call/ret sites.
 
std::unique_ptr< SVFGsvfg
 
bool SVFGWithIndCall
 SVFG with precomputed indirect call edges.
 
bool SVFGWithPostOpts
 Build optimised version of SVFG.
 

Detailed Description

Definition at line 56 of file MTASVFGBuilder.h.

Member Typedef Documentation

◆ SVFGNodeIDSet

Definition at line 60 of file MTASVFGBuilder.h.

◆ SVFGNodeSet

Definition at line 59 of file MTASVFGBuilder.h.

◆ ThreadVFEdge

A candidate thread-aware value-flow edge s –o--> s' (src store, dst load/store), keyed by its endpoint SVFG nodes.

Definition at line 84 of file MTASVFGBuilder.h.

Constructor & Destructor Documentation

◆ MTASVFGBuilder()

SVF::MTASVFGBuilder::MTASVFGBuilder ( MHP m,
LockAnalysis la 
)
inline

Constructor: driven by the interleaving (MHP) and lock analyses.

Definition at line 63 of file MTASVFGBuilder.h.

63: SVFGBuilder(), mhp(m), lockana(la) {}
LockAnalysis * lockana
SVFGBuilder(bool _SVFGWithIndCall=Options::SVFGWithIndirectCall(), bool _SVFGWithPostOpts=Options::OPTSVFG())
Constructor.
Definition SVFGBuilder.h:53
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ ~MTASVFGBuilder()

SVF::MTASVFGBuilder::~MTASVFGBuilder ( )
overridedefault

Member Function Documentation

◆ addJoinRetEdge()

void MTASVFGBuilder::addJoinRetEdge ( const FormalOUTSVFGNode formalOut,
const ActualOUTSVFGNode actualOut,
CallSiteID  csId 
)
private

Add a FormalOUT -> ActualOUT inter-procedural indirect ret edge for a join, mirroring SVFG::addInterIndirectVFRetEdge using the public SVFG API (points-to intersection + dedup via hasInterVFGEdge + addSVFGEdge).

Mirror of SVFG::addInterIndirectVFRetEdge over the public SVFG API, so the join edges can be added from the builder without modifying core SVFG.

Definition at line 137 of file MTASVFGBuilder.cpp.

139{
140 NodeBS cpts = formalOut->getPointsTo();
141 const NodeBS& dpts = actualOut->getPointsTo();
142 if (!cpts.intersects(dpts))
143 return;
144 cpts &= dpts;
145
146 SVFGNode* src = svfg->getSVFGNode(formalOut->getId());
147 SVFGNode* dst = svfg->getSVFGNode(actualOut->getId());
148 if (SVFGEdge* edge = svfg->hasInterVFGEdge(src, dst, SVFGEdge::RetIndVF, csId))
149 {
150 SVFUtil::cast<RetIndSVFGEdge>(edge)->addPointsTo(cpts);
151 }
152 else
153 {
154 RetIndSVFGEdge* retEdge = new RetIndSVFGEdge(src, dst, csId);
155 retEdge->addPointsTo(cpts);
156 svfg->addSVFGEdge(retEdge);
157 }
158}
std::unique_ptr< SVFG > svfg
bool intersects(const SparseBitVector< ElementSize > *RHS) const

◆ addTDEdge()

SVFGEdge * MTASVFGBuilder::addTDEdge ( NodeID  srcId,
NodeID  dstId,
const PointsTo pts 
)
private

Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.

Add (or merge into) a thread-MHP indirect value-flow edge src -> dst.

Definition at line 226 of file MTASVFGBuilder.cpp.

227{
228 SVFGNode* srcNode = svfg->getSVFGNode(srcId);
229 SVFGNode* dstNode = svfg->getSVFGNode(dstId);
230
231 if (SVFGEdge* edge = svfg->hasThreadVFGEdge(srcNode, dstNode, SVFGEdge::TheadMHPIndirectVF))
232 {
233 assert(SVFUtil::isa<IndirectSVFGEdge>(edge) && "should be an indirect value-flow edge!");
234 return (SVFUtil::cast<IndirectSVFGEdge>(edge)->addPointsTo(pts.toNodeBS()) ? edge : nullptr);
235 }
236 else
237 {
240 indirectEdge->addPointsTo(pts.toNodeBS());
241 return (svfg->addSVFGEdge(indirectEdge) ? indirectEdge : nullptr);
242 }
243}
static u32_t numOfNewSVFGEdges
Number of thread-aware (interference) SVFG edges added.
@ TheadMHPIndirectVF
Definition VFGEdge.h:59

◆ buildSVFG()

void MTASVFGBuilder::buildSVFG ( )
overrideprotectedvirtual

Rewrite the SVFG build hook: build the stock SVFG, then add MHP edges.

Build the stock (thread-oblivious) SVFG, add the FSAM join-related def-use edges (relocated out of core SVFG.cpp), then add thread-aware MHP edges.

Reimplemented from SVF::SVFGBuilder.

Definition at line 126 of file MTASVFGBuilder.cpp.

127{
128 svfg->buildSVFG();
130 connectMHPEdges(svfg->getMSSA()->getPTA());
131}
void connectMHPEdges(PointerAnalysis *pta)
Connect inter-thread (interference) value-flow edges for MHP pairs.

◆ collectLoadStoreSVFGNodes()

void MTASVFGBuilder::collectLoadStoreSVFGNodes ( )
private

Collect the store/load SVFG nodes to pair for interference edges (all of them, or – when a slice is set – only the kept ones).

Collect all store/load SVFG nodes.

Definition at line 200 of file MTASVFGBuilder.cpp.

201{
202 for (SVFG::const_iterator it = svfg->begin(), eit = svfg->end(); it != eit; ++it)
203 {
204 const SVFGNode* snode = it->second;
205 const bool isLoad = SVFUtil::isa<LoadSVFGNode>(snode);
206 if (!isLoad && !SVFUtil::isa<StoreSVFGNode>(snode))
207 continue;
208 const StmtSVFGNode* node = SVFUtil::cast<StmtSVFGNode>(snode);
209 const ICFGNode* icfg = node->getICFGNode();
210 if (icfg == nullptr)
211 continue;
212 // Main-solve slice restriction: an interference edge touching a sliced-out
213 // node is inert in the gated FSAM solve, so skip building it here.
214 if (icfgSlice != nullptr && !icfgSlice->isKeptNode(icfg))
215 continue;
216 if (isLoad)
217 ldnodeSet.insert(node);
218 else
219 stnodeSet.insert(node);
220 }
221}
IDToNodeMapTy::const_iterator const_iterator
SVFGNodeSet ldnodeSet
all load SVFG nodes
SVFGNodeSet stnodeSet
all store SVFG nodes
const SlicedICFGView * icfgSlice
Main-solve configuration (see configureForMainSolve); defaults suit VFG_pre.
bool isKeptNode(const ICFGNode *node) const
Check if a node is in the sliced view.
virtual const ICFGNode * getICFGNode() const
Return corresponding ICFG node.
Definition VFGNode.h:67

◆ configureForMainSolve()

void SVF::MTASVFGBuilder::configureForMainSolve ( const SlicedICFGView slice)
inline

Configure the builder for the main (post-slicing) FSAM solve rather than the pre-analysis VFG_pre:

  • slice != null restricts the interference-edge construction to kept store/load nodes (a sliced-out endpoint's edge is inert in the gated solve, so it need not be built);
  • the [THREAD-VF] query map is skipped, as only VFG_pre slicing reads it. The pre-analysis build leaves this unset (whole program, query map built).

Definition at line 76 of file MTASVFGBuilder.h.

77 {
79 recordThreadVF = false;
80 }
bool recordThreadVF
false = skip [THREAD-VF] recording

◆ connectMHPEdges()

void MTASVFGBuilder::connectMHPEdges ( PointerAnalysis pta)
private

Connect inter-thread (interference) value-flow edges for MHP pairs.

For every MHP store/load and store/store pair, add the thread-aware (interference) value-flow edges.

Definition at line 490 of file MTASVFGBuilder.cpp.

491{
493
494 // Inverted access index (object -> access-node bitset): unioning the
495 // bitsets per store visits each may-alias pair exactly once, no dedup tables.
498 for (const StmtSVFGNode* store : stnodeSet)
499 for (NodeID obj : pta->getPts(store->getDstNodeID()))
500 objToStoreIds[obj].set(store->getId());
501 for (const StmtSVFGNode* load : ldnodeSet)
502 for (NodeID obj : pta->getPts(load->getSrcNodeID()))
503 objToLoadIds[obj].set(load->getId());
504
505 for (const StmtSVFGNode* store : stnodeSet)
506 {
508 for (NodeID obj : pta->getPts(store->getDstNodeID()))
509 {
512 if (lIt != objToLoadIds.end())
513 candLoads |= lIt->second;
514 }
515
516 for (NodeID loadId : candLoads)
517 handleStoreLoad(store, SVFUtil::cast<StmtSVFGNode>(svfg->getSVFGNode(loadId)), pta);
518
519 // Visit each unordered store pair once: only partners with a larger id.
520 const NodeID storeId = store->getId();
522 {
523 if (otherId <= storeId)
524 continue;
525 handleStoreStore(store, SVFUtil::cast<StmtSVFGNode>(svfg->getSVFGNode(otherId)), pta);
526 }
527 }
528}
for(i=0;a &&(i<(size_t) count);i++)
Definition cJSON.cpp:2569
void handleStoreLoad(const StmtSVFGNode *n1, const StmtSVFGNode *n2, PointerAnalysis *pta)
void handleStoreStore(const StmtSVFGNode *n1, const StmtSVFGNode *n2, PointerAnalysis *pta)
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
u32_t NodeID
Definition GeneralType.h:76
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56

◆ connectThreadJoinEdges()

void MTASVFGBuilder::connectThreadJoinEdges ( )
private

FSAM join-related thread-oblivious value flow (the "return" half of treating a join as a call without a forward): connect each start routine's exit defs (FormalOUT) to the ActualOUT at every site that joins it (FormalOUT -> ActualOUT ret edge). Done here as a post-pass over the stock SVFG, so core SVFG.cpp stays unmodified.

FSAM join-related def-use (the "return" half of treating a join as a call without a forward): for every FormalOUT (a start routine's exit def), connect it to the ActualOUT at each site that joins that routine. Relocated here from core SVFG::connectIndirectSVFGEdges so the stock SVFG stays unmodified.

Definition at line 166 of file MTASVFGBuilder.cpp.

167{
168 ThreadCallGraph* tcg =
169 SVFUtil::dyn_cast<ThreadCallGraph>(svfg->getMSSA()->getPTA()->getCallGraph());
170 if (tcg == nullptr)
171 return;
172
173 MemSSA* mssa = svfg->getMSSA();
174 for (SVFG::const_iterator it = svfg->begin(), eit = svfg->end(); it != eit; ++it)
175 {
176 const FormalOUTSVFGNode* formalOut = SVFUtil::dyn_cast<FormalOUTSVFGNode>(it->second);
177 if (formalOut == nullptr)
178 continue;
179
180 ThreadCallGraph::InstSet joinsites;
181 tcg->getJoinSites(tcg->getCallGraphNode(formalOut->getFun()), joinsites);
182 for (const CallICFGNode* cs : joinsites)
183 {
184 if (!mssa->hasCHI(cs))
185 continue;
186 SVFG::ActualOUTSVFGNodeSet& actualOuts = svfg->getActualOUTSVFGNodes(cs);
187 for (NodeID aoId : actualOuts)
188 {
190 SVFUtil::cast<ActualOUTSVFGNode>(svfg->getSVFGNode(aoId));
191 addJoinRetEdge(formalOut, actualOut, svfg->getCallSiteID(cs, formalOut->getFun()));
192 }
193 }
194 }
195}
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
void addJoinRetEdge(const FormalOUTSVFGNode *formalOut, const ActualOUTSVFGNode *actualOut, CallSiteID csId)
bool hasCHI(const PAGEdge *inst) const
Definition MemSSA.h:338
OrderedSet< const CallICFGNode *, CallSiteIdCmp > InstSet
void getJoinSites(const CallGraphNode *routine, InstSet &csSet)

◆ createMRGenerator()

std::unique_ptr< MRGenerator > MTASVFGBuilder::createMRGenerator ( BVDataPTAImpl pta,
bool  ptrOnlyMSSA 
)
overrideprotectedvirtual

Inject a thread-aware MRGenerator so the MemSSA mod-ref carries the FSAM fork/join side effects (relocated here from core MemRegion).

Reimplemented from SVF::SVFGBuilder.

Definition at line 106 of file MTASVFGBuilder.cpp.

107{
108 switch (Options::MemPar())
109 {
111 return std::make_unique<ThreadMRG<DistinctMRG>>(pta, ptrOnlyMSSA);
113 return std::make_unique<ThreadMRG<IntraDisjointMRG>>(pta, ptrOnlyMSSA);
115 return std::make_unique<ThreadMRG<InterDisjointMRG>>(pta, ptrOnlyMSSA);
116 default:
117 assert(false && "unrecognised memory partition strategy");
118 return nullptr;
119 }
120}
@ InterDisjoint
Definition MemSSA.h:117
@ IntraDisjoint
Definition MemSSA.h:116
static const OptionMap< u32_t > MemPar
Definition Options.h:141

◆ getPrevNodes()

MTASVFGBuilder::SVFGNodeIDSet MTASVFGBuilder::getPrevNodes ( const StmtSVFGNode n)
private

Lock-span head/tail tests (non-interference lock-pair pruning).

Backward reachable store SVFG nodes via indirect value flow (lock-span head test).

Definition at line 248 of file MTASVFGBuilder.cpp.

249{
250 if (prevset.find(n) != prevset.end())
251 return prevset[n];
252
254 Set<const SVFGNode*> worklist;
255 Set<const SVFGNode*> visited;
256
257 for (SVFGEdge::SVFGEdgeSetTy::iterator iter = n->InEdgeBegin(); iter != n->InEdgeEnd(); ++iter)
258 {
259 SVFGEdge* edge = *iter;
260 if (edge->isIndirectVFGEdge())
261 worklist.insert(edge->getSrcNode());
262 }
263
264 while (!worklist.empty())
265 {
266 const SVFGNode* node = *worklist.begin();
267 worklist.erase(worklist.begin());
268 visited.insert(node);
269 if (SVFUtil::isa<StoreSVFGNode>(node))
270 prev.set(node->getId());
271 else
272 {
273 for (SVFGEdge::SVFGEdgeSetTy::iterator iter = node->InEdgeBegin(); iter != node->InEdgeEnd(); ++iter)
274 {
275 SVFGEdge* edge = *iter;
276 if (edge->isIndirectVFGEdge() && visited.find(edge->getSrcNode()) == visited.end())
277 worklist.insert(edge->getSrcNode());
278 }
279 }
280 }
281 prevset[n] = prev;
282 return prev;
283}
newitem prev
Definition cJSON.cpp:2285
cJSON * n
Definition cJSON.cpp:2558
iterator InEdgeBegin()
iterator InEdgeEnd()
Map< const StmtSVFGNode *, SVFGNodeIDSet > prevset
NodeID getId() const
Get ID.
Definition SVFValue.h:158

◆ getSuccNodes()

MTASVFGBuilder::SVFGNodeIDSet MTASVFGBuilder::getSuccNodes ( const StmtSVFGNode n)
private

Forward reachable store/load SVFG nodes via indirect value flow (lock-span tail test).

Definition at line 288 of file MTASVFGBuilder.cpp.

289{
290 if (succset.find(n) != succset.end())
291 return succset[n];
292
294 Set<const SVFGNode*> worklist;
295 Set<const SVFGNode*> visited;
296
297 for (SVFGEdge::SVFGEdgeSetTy::iterator iter = n->OutEdgeBegin(); iter != n->OutEdgeEnd(); ++iter)
298 {
299 SVFGEdge* edge = *iter;
300 if (edge->isIndirectVFGEdge())
301 worklist.insert(edge->getDstNode());
302 }
303
304 while (!worklist.empty())
305 {
306 const SVFGNode* node = *worklist.begin();
307 worklist.erase(worklist.begin());
308 visited.insert(node);
309 if (SVFUtil::isa<StoreSVFGNode, LoadSVFGNode>(node))
310 succ.set(node->getId());
311 else
312 {
313 for (SVFGEdge::SVFGEdgeSetTy::iterator iter = node->OutEdgeBegin(); iter != node->OutEdgeEnd(); ++iter)
314 {
315 SVFGEdge* edge = *iter;
316 if (edge->isIndirectVFGEdge() && visited.find(edge->getDstNode()) == visited.end())
317 worklist.insert(edge->getDstNode());
318 }
319 }
320 }
321 succset[n] = succ;
322 return succ;
323}
iterator OutEdgeEnd()
iterator OutEdgeBegin()
iterators
Map< const StmtSVFGNode *, SVFGNodeIDSet > succset

◆ getThreadVFQueryMap()

const std::map< ThreadVFEdge, std::set< const ICFGNode * > > & SVF::MTASVFGBuilder::getThreadVFQueryMap ( ) const
inline

[THREAD-VF] per-edge query map (MSli §4.2, Fig. 6 rule [THREAD-VF]).

While building VFG_pre we record, for every candidate thread-aware value-flow edge (s,s') the construction evaluates, its Query(s –o--> s') set: the endpoints {s,s'} plus — under a common lock — the in-span witnesses Succ_spl(s) / Pred_spl'(s') that decide TL/HD membership, i.e. whether the edge survives the non-interference test (Def. 2). The query is kept per edge (not pre-unioned) so ILA slicing can restrict the sources to the edges that survive the FSPTA slice — ThreadVF(VFG'_pre) — rather than every candidate pair. Feeding the retained edges' queries into ILA slicing makes the sliced MHP/lock reproduce the same value-flow decisions the main phase makes, while keeping the slice minimal.

The value stores only the additional lock-span witnesses; the endpoint ICFG nodes are implicit in the key and consumers must add them back.

Definition at line 101 of file MTASVFGBuilder.h.

102 {
103 return threadVFQueryMap;
104 }
std::map< ThreadVFEdge, std::set< const ICFGNode * > > threadVFQueryMap
[THREAD-VF] per-edge query map (see getThreadVFQueryMap).

◆ handleStoreLoad()

void MTASVFGBuilder::handleStoreLoad ( const StmtSVFGNode n1,
const StmtSVFGNode n2,
PointerAnalysis pta 
)
private

Store -> Load interference: add a thread-aware def-use edge if the store may happen in parallel with and may alias the load, unless excluded by a common lock (then only when the store is a span tail and the load a span head).

Definition at line 415 of file MTASVFGBuilder.cpp.

416{
417 const ICFGNode* i1 = n1->getICFGNode();
418 const ICFGNode* i2 = n2->getICFGNode();
419
421 return;
422
423 // No alias() re-check: the bucketed candidate generator only pairs accesses
424 // whose raw points-to sets share an object, so the intersection below is
425 // non-empty by construction and alias() could never answer NoAlias here.
426 PointsTo pts = pta->getPts(n1->getDstNodeID());
427 pts &= pta->getPts(n2->getSrcNodeID());
428
429 // [THREAD-VF] source extraction runs for every candidate pair (both the
430 // pairs that survive and the ones the lock test prunes), so the sliced ILA
431 // can re-derive whether the edge holds.
433 if (recordThreadVF)
435
436 if (commonLock)
437 {
439 addTDEdge(n1->getId(), n2->getId(), pts);
440 }
441 else
442 {
443 addTDEdge(n1->getId(), n2->getId(), pts);
444 }
445}
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition MHP.cpp:763
SVFGEdge * addTDEdge(NodeID srcId, NodeID dstId, const PointsTo &pts)
Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.
bool isHeadOfSpan(const StmtSVFGNode *n)
void recordThreadVFSource(const StmtSVFGNode *s, const StmtSVFGNode *sp, bool commonLock)
bool isTailOfSpan(const StmtSVFGNode *n)
virtual const PointsTo & getPts(NodeID ptr)=0
Get points-to targets of a pointer. It needs to be implemented in child class.

◆ handleStoreStore()

void MTASVFGBuilder::handleStoreStore ( const StmtSVFGNode n1,
const StmtSVFGNode n2,
PointerAnalysis pta 
)
private

Store -> Store interference (symmetric): add thread-aware def-use edges in both directions, with the same lock-span pruning as store/load.

Definition at line 451 of file MTASVFGBuilder.cpp.

452{
453 const ICFGNode* i1 = n1->getICFGNode();
454 const ICFGNode* i2 = n2->getICFGNode();
455
457 return;
458
459 // No alias() re-check: see handleStoreLoad -- bucketing already guarantees a
460 // shared raw object.
461 PointsTo pts = pta->getPts(n1->getDstNodeID());
462 pts &= pta->getPts(n2->getDstNodeID());
463
464 // Both directions are candidate thread-aware edges; extract sources for each.
466 if (recordThreadVF)
467 {
470 }
471
472 if (commonLock)
473 {
475 addTDEdge(n1->getId(), n2->getId(), pts);
477 addTDEdge(n2->getId(), n1->getId(), pts);
478 }
479 else
480 {
481 addTDEdge(n1->getId(), n2->getId(), pts);
482 addTDEdge(n2->getId(), n1->getId(), pts);
483 }
484}

◆ isHeadOfSpan()

bool MTASVFGBuilder::isHeadOfSpan ( const StmtSVFGNode n)
private

Whether, for all lock spans n belongs to, n is the first write (span head).

Definition at line 328 of file MTASVFGBuilder.cpp.

329{
330 if (headmap.find(n) != headmap.end())
331 return headmap[n];
332
334 for (NodeID id : prev)
335 {
336 const StmtSVFGNode* prevNode = SVFUtil::dyn_cast<StmtSVFGNode>(svfg->getSVFGNode(id));
337 if (prevNode && lockana->isInSameSpan(prevNode->getICFGNode(), n->getICFGNode()))
338 {
339 headmap[n] = false;
340 return false;
341 }
342 }
343 headmap[n] = true;
344 return true;
345}
bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2)
SVFGNodeIDSet getPrevNodes(const StmtSVFGNode *n)
Lock-span head/tail tests (non-interference lock-pair pruning).
Map< const StmtSVFGNode *, bool > headmap

◆ isTailOfSpan()

bool MTASVFGBuilder::isTailOfSpan ( const StmtSVFGNode n)
private

Whether, for all lock spans n belongs to, n is the last write (span tail).

Definition at line 350 of file MTASVFGBuilder.cpp.

351{
352 assert(SVFUtil::isa<StoreSVFGNode>(n) && "tail test only for store nodes");
353
354 if (tailmap.find(n) != tailmap.end())
355 return tailmap[n];
356
358 for (NodeID id : succ)
359 {
360 const SVFGNode* sn = svfg->getSVFGNode(id);
361 if (SVFUtil::isa<LoadSVFGNode>(sn))
362 continue;
363 const StmtSVFGNode* succNode = SVFUtil::dyn_cast<StmtSVFGNode>(sn);
364 if (succNode && lockana->isInSameSpan(succNode->getICFGNode(), n->getICFGNode()))
365 {
366 tailmap[n] = false;
367 return false;
368 }
369 }
370 tailmap[n] = true;
371 return true;
372}
SVFGNodeIDSet getSuccNodes(const StmtSVFGNode *n)
Map< const StmtSVFGNode *, bool > tailmap

◆ recordThreadVFSource()

void MTASVFGBuilder::recordThreadVFSource ( const StmtSVFGNode s,
const StmtSVFGNode sp,
bool  commonLock 
)
private

Record the [THREAD-VF] slicing sources for one candidate pair s –o--> s' (s = src store, sp = dst load/store). Adds the endpoints, and — when the pair is protected by a common lock — the in-span successor/predecessor witnesses needed to re-decide the non-interference (tail/head) test.

Record the per-edge [THREAD-VF] query for one candidate pair s –o--> sp (see getThreadVFQueryMap for the rule): the endpoints, plus – under a common lock – the in-span Succ_spl(s) / Pred_spl'(sp) witnesses. Enumerated fully (the tail/head boolean tests short-circuit; source extraction must not).

Definition at line 380 of file MTASVFGBuilder.cpp.

381{
382 // Per-edge Query set. The endpoints are NOT duplicated into the value --
383 // they are recoverable from the map key -- so the value holds only the
384 // additional in-span witnesses below (empty for the common lock-free case).
385 std::set<const ICFGNode*>& query = threadVFQueryMap[ {s, sp}];
386
387 if (!commonLock)
388 return;
389
390 // Succ_spl(s) = { x in s's span | x is a store, s --o--> x } (tail witnesses).
391 for (NodeID id : getSuccNodes(s))
392 {
393 const SVFGNode* sn = svfg->getSVFGNode(id);
394 if (!SVFUtil::isa<StoreSVFGNode>(sn))
395 continue;
396 const StmtSVFGNode* succNode = SVFUtil::cast<StmtSVFGNode>(sn);
397 if (lockana->isInSameSpan(succNode->getICFGNode(), s->getICFGNode()))
398 query.insert(succNode->getICFGNode());
399 }
400
401 // Pred_spl'(sp) = { x in sp's span | x --o--> sp } (head witnesses).
402 for (NodeID id : getPrevNodes(sp))
403 {
404 const StmtSVFGNode* prevNode = SVFUtil::dyn_cast<StmtSVFGNode>(svfg->getSVFGNode(id));
405 if (prevNode && lockana->isInSameSpan(prevNode->getICFGNode(), sp->getICFGNode()))
406 query.insert(prevNode->getICFGNode());
407 }
408}

Member Data Documentation

◆ headmap

Map<const StmtSVFGNode*, bool> SVF::MTASVFGBuilder::headmap
private

Definition at line 170 of file MTASVFGBuilder.h.

◆ icfgSlice

const SlicedICFGView* SVF::MTASVFGBuilder::icfgSlice = nullptr
private

Main-solve configuration (see configureForMainSolve); defaults suit VFG_pre.

null = whole program

Definition at line 116 of file MTASVFGBuilder.h.

◆ ldnodeSet

SVFGNodeSet SVF::MTASVFGBuilder::ldnodeSet
private

all load SVFG nodes

Definition at line 160 of file MTASVFGBuilder.h.

◆ lockana

LockAnalysis* SVF::MTASVFGBuilder::lockana
private

Definition at line 166 of file MTASVFGBuilder.h.

◆ mhp

MHP* SVF::MTASVFGBuilder::mhp
private

Definition at line 165 of file MTASVFGBuilder.h.

◆ numOfNewSVFGEdges

u32_t MTASVFGBuilder::numOfNewSVFGEdges = 0
static

Number of thread-aware (interference) SVFG edges added.

Definition at line 67 of file MTASVFGBuilder.h.

◆ prevset

Map<const StmtSVFGNode*, SVFGNodeIDSet> SVF::MTASVFGBuilder::prevset
private

Definition at line 168 of file MTASVFGBuilder.h.

◆ recordThreadVF

bool SVF::MTASVFGBuilder::recordThreadVF = true
private

false = skip [THREAD-VF] recording

Definition at line 117 of file MTASVFGBuilder.h.

◆ stnodeSet

SVFGNodeSet SVF::MTASVFGBuilder::stnodeSet
private

all store SVFG nodes

Definition at line 159 of file MTASVFGBuilder.h.

◆ succset

Map<const StmtSVFGNode*, SVFGNodeIDSet> SVF::MTASVFGBuilder::succset
private

Definition at line 169 of file MTASVFGBuilder.h.

◆ tailmap

Map<const StmtSVFGNode*, bool> SVF::MTASVFGBuilder::tailmap
private

Definition at line 171 of file MTASVFGBuilder.h.

◆ threadVFQueryMap

std::map<ThreadVFEdge, std::set<const ICFGNode*> > SVF::MTASVFGBuilder::threadVFQueryMap
private

[THREAD-VF] per-edge query map (see getThreadVFQueryMap).

Definition at line 163 of file MTASVFGBuilder.h.


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