svf-lib 1.0.2676 → 1.0.2678
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux-aarch64/bin/mta +0 -0
- package/SVF-linux-aarch64/bin/svf-ex +0 -0
- package/SVF-linux-aarch64/include/Graphs/CallGraph.h +18 -0
- package/SVF-linux-aarch64/include/Graphs/DOTGraphTraits.h +33 -20
- package/SVF-linux-aarch64/include/Graphs/GraphPrinter.h +1 -1
- package/SVF-linux-aarch64/include/Graphs/GraphWriter.h +6 -7
- package/SVF-linux-aarch64/include/Graphs/ICFG.h +40 -0
- package/SVF-linux-aarch64/include/Graphs/SVFG.h +8 -0
- package/SVF-linux-aarch64/include/Graphs/SlicedGraphs.h +1801 -0
- package/SVF-linux-aarch64/include/Graphs/ThreadCallGraph.h +13 -4
- package/SVF-linux-aarch64/include/MSSA/MemRegion.h +17 -0
- package/SVF-linux-aarch64/include/MSSA/MemSSA.h +7 -5
- package/SVF-linux-aarch64/include/MSSA/SVFGBuilder.h +6 -0
- package/SVF-linux-aarch64/include/MTA/FSMPTA.h +91 -0
- package/SVF-linux-aarch64/include/MTA/LockAnalysis.h +40 -25
- package/SVF-linux-aarch64/include/MTA/MHP.h +54 -21
- package/SVF-linux-aarch64/include/MTA/MTA.h +186 -3
- package/SVF-linux-aarch64/include/MTA/MTASVFGBuilder.h +176 -0
- package/SVF-linux-aarch64/include/MTA/MTASlicer.h +275 -0
- package/SVF-linux-aarch64/include/MTA/MTAStat.h +0 -2
- package/SVF-linux-aarch64/include/MTA/TCT.h +70 -29
- package/SVF-linux-aarch64/include/Util/CommandLine.h +5 -0
- package/SVF-linux-aarch64/include/Util/CxtStmt.h +29 -19
- package/SVF-linux-aarch64/include/Util/Options.h +12 -6
- package/SVF-linux-aarch64/include/Util/ThreadAPI.h +12 -0
- package/SVF-linux-aarch64/lib/cmake/SVF/SVFTargets.cmake +1 -1
- package/SVF-linux-aarch64/lib/libSvfCore.so.3.4 +0 -0
- package/SVF-linux-x86_64/bin/ae +0 -0
- package/SVF-linux-x86_64/bin/cfl +0 -0
- package/SVF-linux-x86_64/bin/dvf +0 -0
- package/SVF-linux-x86_64/bin/mta +0 -0
- package/SVF-linux-x86_64/bin/saber +0 -0
- package/SVF-linux-x86_64/bin/svf-ex +0 -0
- package/SVF-linux-x86_64/include/Graphs/CallGraph.h +18 -0
- package/SVF-linux-x86_64/include/Graphs/DOTGraphTraits.h +33 -20
- package/SVF-linux-x86_64/include/Graphs/GraphPrinter.h +1 -1
- package/SVF-linux-x86_64/include/Graphs/GraphWriter.h +6 -7
- package/SVF-linux-x86_64/include/Graphs/ICFG.h +40 -0
- package/SVF-linux-x86_64/include/Graphs/SVFG.h +8 -0
- package/SVF-linux-x86_64/include/Graphs/SlicedGraphs.h +1801 -0
- package/SVF-linux-x86_64/include/Graphs/ThreadCallGraph.h +13 -4
- package/SVF-linux-x86_64/include/MSSA/MemRegion.h +17 -0
- package/SVF-linux-x86_64/include/MSSA/MemSSA.h +7 -5
- package/SVF-linux-x86_64/include/MSSA/SVFGBuilder.h +6 -0
- package/SVF-linux-x86_64/include/MTA/FSMPTA.h +91 -0
- package/SVF-linux-x86_64/include/MTA/LockAnalysis.h +40 -25
- package/SVF-linux-x86_64/include/MTA/MHP.h +54 -21
- package/SVF-linux-x86_64/include/MTA/MTA.h +186 -3
- package/SVF-linux-x86_64/include/MTA/MTASVFGBuilder.h +176 -0
- package/SVF-linux-x86_64/include/MTA/MTASlicer.h +275 -0
- package/SVF-linux-x86_64/include/MTA/MTAStat.h +0 -2
- package/SVF-linux-x86_64/include/MTA/TCT.h +70 -29
- package/SVF-linux-x86_64/include/Util/CommandLine.h +5 -0
- package/SVF-linux-x86_64/include/Util/CxtStmt.h +29 -19
- package/SVF-linux-x86_64/include/Util/Options.h +12 -6
- package/SVF-linux-x86_64/include/Util/ThreadAPI.h +12 -0
- package/SVF-linux-x86_64/lib/cmake/SVF/SVFTargets.cmake +1 -1
- package/SVF-linux-x86_64/lib/libSvfCore.so.3.4 +0 -0
- package/package.json +1 -1
|
@@ -142,7 +142,18 @@ class ThreadCallGraph: public CallGraph
|
|
|
142
142
|
{
|
|
143
143
|
|
|
144
144
|
public:
|
|
145
|
-
|
|
145
|
+
/// Order fork/join callsites by ICFG node id, never by pointer value:
|
|
146
|
+
/// thread ids are assigned in discovery order over these sets (TCT), and
|
|
147
|
+
/// the MHP/lock fixed points seed from them, so their iteration order must
|
|
148
|
+
/// be identical across runs (a pointer-hashed set varies with ASLR).
|
|
149
|
+
struct CallSiteIdCmp
|
|
150
|
+
{
|
|
151
|
+
bool operator()(const CallICFGNode* lhs, const CallICFGNode* rhs) const
|
|
152
|
+
{
|
|
153
|
+
return lhs->getId() < rhs->getId();
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
typedef OrderedSet<const CallICFGNode*, CallSiteIdCmp> InstSet;
|
|
146
157
|
typedef InstSet CallSiteSet;
|
|
147
158
|
typedef Set<CallSiteSet*> CtxSet;
|
|
148
159
|
typedef ThreadForkEdge::ForkEdgeSet ForkEdgeSet;
|
|
@@ -158,9 +169,7 @@ public:
|
|
|
158
169
|
ThreadCallGraph(ThreadCallGraph& cg) = delete;
|
|
159
170
|
|
|
160
171
|
/// Destructor
|
|
161
|
-
virtual ~ThreadCallGraph()
|
|
162
|
-
{
|
|
163
|
-
}
|
|
172
|
+
virtual ~ThreadCallGraph();
|
|
164
173
|
|
|
165
174
|
/// ClassOf
|
|
166
175
|
//@{
|
|
@@ -337,6 +337,14 @@ protected:
|
|
|
337
337
|
/// Get Mod-Ref of a callee function
|
|
338
338
|
virtual bool handleCallsiteModRef(NodeBS& mod, NodeBS& ref, const CallICFGNode* cs, const FunObjVar* fun);
|
|
339
339
|
|
|
340
|
+
/// Extension hooks for specialised MRGenerators: no-op in the base. They
|
|
341
|
+
/// run during the mod/ref fixpoint, before MemorySSA creates callsite
|
|
342
|
+
/// MU/CHI nodes; subclasses use them when a call boundary needs non-standard
|
|
343
|
+
/// mod/ref effects to expose the right ActualIN/ActualOUT nodes.
|
|
344
|
+
virtual void refineCallsiteModRef(NodeBS& /*mod*/, NodeBS& /*ref*/,
|
|
345
|
+
const CallICFGNode* /*cs*/, const FunObjVar* /*callee*/) {}
|
|
346
|
+
virtual void propagateAdditionalModRef(CallGraphNode* /*callGraphNode*/, WorkList& /*worklist*/) {}
|
|
347
|
+
|
|
340
348
|
|
|
341
349
|
/// Add cpts to store/load
|
|
342
350
|
//@{
|
|
@@ -385,6 +393,15 @@ protected:
|
|
|
385
393
|
bool addRefSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& refs);
|
|
386
394
|
/// Add indirect def an memory object in the function
|
|
387
395
|
bool addModSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& mods);
|
|
396
|
+
/// Add indirect def to a callsite without applying call-argument filtering.
|
|
397
|
+
bool addUnfilteredModSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& mods);
|
|
398
|
+
|
|
399
|
+
/// The call graph this generator works on (for subclasses, e.g. the
|
|
400
|
+
/// thread-aware MTA MRGenerator that inspects fork/join edges).
|
|
401
|
+
CallGraph* getCallGraph() const
|
|
402
|
+
{
|
|
403
|
+
return callGraph;
|
|
404
|
+
}
|
|
388
405
|
|
|
389
406
|
/// Get indirect refs of a function
|
|
390
407
|
inline const NodeBS& getRefSideEffectOfFunction(const FunObjVar* fun)
|
|
@@ -119,7 +119,7 @@ public:
|
|
|
119
119
|
|
|
120
120
|
protected:
|
|
121
121
|
BVDataPTAImpl* pta;
|
|
122
|
-
MRGenerator
|
|
122
|
+
std::unique_ptr<MRGenerator> mrGen;
|
|
123
123
|
MemSSAStat* stat;
|
|
124
124
|
|
|
125
125
|
/// Create mu chi for candidate regions in a function
|
|
@@ -294,8 +294,10 @@ private:
|
|
|
294
294
|
//@}
|
|
295
295
|
|
|
296
296
|
public:
|
|
297
|
-
/// Constructor
|
|
298
|
-
|
|
297
|
+
/// Constructor. The builder (SVFGBuilder::createMRGenerator) supplies the
|
|
298
|
+
/// MRGenerator and decides the partition strategy / thread-awareness; MemSSA
|
|
299
|
+
/// takes ownership of it via unique_ptr. mrGenerator must not be null.
|
|
300
|
+
MemSSA(BVDataPTAImpl* p, std::unique_ptr<MRGenerator> mrGenerator);
|
|
299
301
|
|
|
300
302
|
/// Destructor
|
|
301
303
|
virtual ~MemSSA()
|
|
@@ -309,10 +311,10 @@ public:
|
|
|
309
311
|
{
|
|
310
312
|
return pta;
|
|
311
313
|
}
|
|
312
|
-
/// Return MRGenerator
|
|
314
|
+
/// Return MRGenerator (non-owning; MemSSA retains ownership)
|
|
313
315
|
inline MRGenerator* getMRGenerator()
|
|
314
316
|
{
|
|
315
|
-
return mrGen;
|
|
317
|
+
return mrGen.get();
|
|
316
318
|
}
|
|
317
319
|
/// We start from here
|
|
318
320
|
virtual void buildMemSSA(const FunObjVar& fun);
|
|
@@ -83,6 +83,12 @@ public:
|
|
|
83
83
|
virtual std::unique_ptr<MemSSA> buildMSSA(BVDataPTAImpl* pta, bool ptrOnlyMSSA);
|
|
84
84
|
|
|
85
85
|
protected:
|
|
86
|
+
/// Hook supplying the MRGenerator for the MemSSA built above. The default
|
|
87
|
+
/// builds the stock generator selected by Options::MemPar(); MTASVFGBuilder
|
|
88
|
+
/// overrides this to inject a thread-aware (ThreadMRG) generator. Ownership
|
|
89
|
+
/// transfers to the MemSSA constructed in buildMSSA.
|
|
90
|
+
virtual std::unique_ptr<MRGenerator> createMRGenerator(BVDataPTAImpl* pta, bool ptrOnlyMSSA);
|
|
91
|
+
|
|
86
92
|
/// Create a DDA SVFG. By default actualOut and FormalIN are removed, unless withAOFI is set true.
|
|
87
93
|
SVFG* build(BVDataPTAImpl* pta, VFG::VFGK kind);
|
|
88
94
|
/// Can be rewritten by subclasses
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//===- FSMPTA.h -- Flow-sensitive multithreaded pointer analysis (FSAM) -===//
|
|
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
|
+
* FSMPTA.h
|
|
25
|
+
*
|
|
26
|
+
* Author: Jiawei Yang
|
|
27
|
+
*
|
|
28
|
+
* Sparse flow-sensitive pointer analysis for multithreaded programs (FSAM,
|
|
29
|
+
* Sui/Di/Xue CGO'16). It runs the sparse flow-sensitive solver
|
|
30
|
+
* (`FlowSensitive`) over a *thread-aware* SVFG built by `MTASVFGBuilder`,
|
|
31
|
+
* i.e. the stock thread-oblivious value flow augmented with inter-thread
|
|
32
|
+
* (interference) edges derived from the MHP and lock analyses.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
#ifndef INCLUDE_MTA_FSMPTA_H_
|
|
36
|
+
#define INCLUDE_MTA_FSMPTA_H_
|
|
37
|
+
|
|
38
|
+
#include "WPA/FlowSensitive.h"
|
|
39
|
+
#include "MTA/MHP.h"
|
|
40
|
+
#include "MTA/LockAnalysis.h"
|
|
41
|
+
#include "MTA/MTASVFGBuilder.h"
|
|
42
|
+
#include "MTA/MTASlicer.h"
|
|
43
|
+
#include <unordered_set>
|
|
44
|
+
|
|
45
|
+
namespace SVF
|
|
46
|
+
{
|
|
47
|
+
|
|
48
|
+
/// One solver for the whole and the sliced SVFG: SVFGGraph is SVFG* (whole;
|
|
49
|
+
/// every node processed) or const SlicedSVFGView* (sliced; nodes outside the
|
|
50
|
+
/// view are propagation barriers). Restriction is answered by
|
|
51
|
+
/// GenericGraphTraits<SVFGGraph>::containsNode, resolved at compile time; the
|
|
52
|
+
/// stock FlowSensitive transfer semantics are untouched.
|
|
53
|
+
template<class SVFGGraph>
|
|
54
|
+
class FSMPTA : public FlowSensitive
|
|
55
|
+
{
|
|
56
|
+
public:
|
|
57
|
+
/// Constructor.
|
|
58
|
+
/// - graph: gates the per-node transfer (the solver runs over the whole
|
|
59
|
+
/// thread-aware SVFG). For SVFGGraph == SVFG* it may be null (every node
|
|
60
|
+
/// is processed). A SlicedSVFGView needs only its ICFG view for membership,
|
|
61
|
+
/// so it can be created before the SVFG itself is built here.
|
|
62
|
+
FSMPTA(MHP* m, LockAnalysis* la, SVFGGraph graph)
|
|
63
|
+
: FlowSensitive(m->getTCT()->getPTA()->getPAG()),
|
|
64
|
+
mhp(m), mtaSVFGBuilder(m, la), graph(graph)
|
|
65
|
+
{
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
~FSMPTA() override = default;
|
|
69
|
+
|
|
70
|
+
/// Initialise: build the thread-aware SVFG, then solve sparsely on it.
|
|
71
|
+
void initialize() override;
|
|
72
|
+
|
|
73
|
+
/// Restrict the solve to the graph's nodes (whole: no restriction).
|
|
74
|
+
void processNode(NodeID nodeId) override;
|
|
75
|
+
|
|
76
|
+
inline MHP* getMHP() const
|
|
77
|
+
{
|
|
78
|
+
return mhp;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private:
|
|
82
|
+
MHP* mhp;
|
|
83
|
+
/// Owns the thread-aware SVFG used by the FS solver (must outlive `svfg`).
|
|
84
|
+
MTASVFGBuilder mtaSVFGBuilder;
|
|
85
|
+
/// The graph the solve is restricted to (see the constructor).
|
|
86
|
+
SVFGGraph graph;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
} // End namespace SVF
|
|
90
|
+
|
|
91
|
+
#endif /* INCLUDE_MTA_FSMPTA_H_ */
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Created on: 26 Aug 2015
|
|
27
27
|
* Author: pengd
|
|
28
|
+
*
|
|
29
|
+
* Lock analysis. One implementation runs on the whole program or a slice:
|
|
30
|
+
* analyze() is templated on the graph handle (SVFIR* or const SlicedSVFIRView*),
|
|
31
|
+
* as used by "Multi-Stage On-Demand Program Slicing for Modular Analysis of
|
|
32
|
+
* Multi-Threaded Programs" (ISSTA 2026).
|
|
28
33
|
*/
|
|
29
34
|
|
|
30
35
|
#ifndef INCLUDE_MTA_LockAnalysis_H_
|
|
@@ -35,9 +40,15 @@
|
|
|
35
40
|
*/
|
|
36
41
|
#include "MTA/TCT.h"
|
|
37
42
|
|
|
43
|
+
#include <memory>
|
|
44
|
+
#include <vector>
|
|
45
|
+
|
|
38
46
|
namespace SVF
|
|
39
47
|
{
|
|
40
48
|
|
|
49
|
+
// Forward declaration for the sliced-graph handle analyze() can run on.
|
|
50
|
+
class SlicedSVFIRView;
|
|
51
|
+
|
|
41
52
|
/*!
|
|
42
53
|
* Lock analysis
|
|
43
54
|
*/
|
|
@@ -81,18 +92,23 @@ public:
|
|
|
81
92
|
{
|
|
82
93
|
}
|
|
83
94
|
|
|
95
|
+
~LockAnalysis() = default;
|
|
96
|
+
|
|
84
97
|
/// context-sensitive forward traversal from each lock site. Generate following results
|
|
85
98
|
/// (1) context-sensitive lock site,
|
|
86
99
|
/// (2) maps a context-sensitive lock site to its corresponding lock span.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
void
|
|
100
|
+
/// One implementation for the whole program and a slice: GraphT is SVFIR*
|
|
101
|
+
/// (whole) or const SlicedSVFIRView* (sliced). Per-graph queries resolve at
|
|
102
|
+
/// compile time via the graph* overloads in Graphs/SlicedGraphs.h.
|
|
103
|
+
template<class ICFGGraph, class CGGraph> void analyze(ICFGGraph icfg, CGGraph cg);
|
|
104
|
+
template<class ICFGGraph, class CGGraph> void analyzeIntraProcedualLock(ICFGGraph icfg, CGGraph cg);
|
|
105
|
+
template<class ICFGGraph, class CGGraph> bool intraForwardTraverse(ICFGGraph icfg, CGGraph cg, const ICFGNode* lock, InstSet& unlockset, InstSet& forwardInsts);
|
|
106
|
+
template<class ICFGGraph, class CGGraph> bool intraBackwardTraverse(ICFGGraph icfg, CGGraph cg, const InstSet& unlockset, InstSet& backwardInsts);
|
|
107
|
+
|
|
108
|
+
template<class ICFGGraph, class CGGraph> void collectCxtLock(ICFGGraph icfg, CGGraph cg);
|
|
109
|
+
template<class ICFGGraph, class CGGraph> void analyzeLockSpanCxtStmt(ICFGGraph icfg, CGGraph cg);
|
|
110
|
+
|
|
111
|
+
template<class ICFGGraph, class CGGraph> void collectLockUnlocksites(ICFGGraph icfg, CGGraph cg);
|
|
96
112
|
void buildCandidateFuncSetforLock();
|
|
97
113
|
|
|
98
114
|
/// Intraprocedural locks
|
|
@@ -135,6 +151,14 @@ public:
|
|
|
135
151
|
return instTocondCILocksMap.find(stmt)!=instTocondCILocksMap.end();
|
|
136
152
|
}
|
|
137
153
|
|
|
154
|
+
/// Whether a statement has an (unconditional) intra-procedural lock set, i.e.
|
|
155
|
+
/// getIntraLockSet is valid for it. A statement can be locked (isInsideIntraLock)
|
|
156
|
+
/// via a *conditional* intra lock or a *context* lock without being here.
|
|
157
|
+
inline bool hasIntraLockSet(const ICFGNode* stmt) const
|
|
158
|
+
{
|
|
159
|
+
return instCILocksMap.find(stmt)!=instCILocksMap.end();
|
|
160
|
+
}
|
|
161
|
+
|
|
138
162
|
inline const InstSet& getIntraLockSet(const ICFGNode* stmt) const
|
|
139
163
|
{
|
|
140
164
|
InstToInstSetMap::const_iterator it = instCILocksMap.find(stmt);
|
|
@@ -264,8 +288,6 @@ public:
|
|
|
264
288
|
}
|
|
265
289
|
//@}
|
|
266
290
|
|
|
267
|
-
|
|
268
|
-
|
|
269
291
|
/// Check if one instruction's context stmt is in a lock span
|
|
270
292
|
inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
|
|
271
293
|
{
|
|
@@ -297,7 +319,6 @@ public:
|
|
|
297
319
|
return true;
|
|
298
320
|
}
|
|
299
321
|
|
|
300
|
-
|
|
301
322
|
/// Check if two Instructions are protected by common locks
|
|
302
323
|
/// echo inst may have multiple cxt stmt
|
|
303
324
|
/// we check whether every cxt stmt of instructions is protected by a common lock.
|
|
@@ -323,32 +344,28 @@ public:
|
|
|
323
344
|
{
|
|
324
345
|
return tct;
|
|
325
346
|
}
|
|
326
|
-
|
|
347
|
+
protected:
|
|
327
348
|
/// Handle fork
|
|
328
|
-
void handleFork(const CxtStmt& cts);
|
|
349
|
+
template<class ICFGGraph, class CGGraph> void handleFork(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
|
|
329
350
|
|
|
330
351
|
/// Handle call
|
|
331
|
-
void handleCall(const CxtStmt& cts);
|
|
352
|
+
template<class ICFGGraph, class CGGraph> void handleCall(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
|
|
332
353
|
|
|
333
354
|
/// Handle return
|
|
334
|
-
void handleRet(const CxtStmt& cts);
|
|
355
|
+
template<class ICFGGraph, class CGGraph> void handleRet(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
|
|
335
356
|
|
|
336
357
|
/// Handle intra
|
|
337
|
-
void handleIntra(const CxtStmt& cts);
|
|
358
|
+
template<class ICFGGraph, class CGGraph> void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
|
|
338
359
|
|
|
339
360
|
/// Handle call relations
|
|
340
|
-
void handleCallRelation(CxtLockProc& clp, const CallGraphEdge* cgEdge, const CallICFGNode* call);
|
|
361
|
+
template<class ICFGGraph, class CGGraph> void handleCallRelation(ICFGGraph icfg, CGGraph cg, CxtLockProc& clp, const CallGraphEdge* cgEdge, const CallICFGNode* call);
|
|
341
362
|
|
|
342
363
|
/// Return true it a lock matches an unlock
|
|
343
364
|
bool isAliasedLocks(const CxtLock& cl1, const CxtLock& cl2)
|
|
344
365
|
{
|
|
345
366
|
return isAliasedLocks(cl1.getStmt(), cl2.getStmt());
|
|
346
367
|
}
|
|
347
|
-
bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2)
|
|
348
|
-
{
|
|
349
|
-
/// todo: must alias
|
|
350
|
-
return tct->getPTA()->alias(getLockVal(i1)->getId(), getLockVal(i2)->getId());
|
|
351
|
-
}
|
|
368
|
+
bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2);
|
|
352
369
|
|
|
353
370
|
/// Mark thread flags for cxtStmt
|
|
354
371
|
//@{
|
|
@@ -488,7 +505,6 @@ private:
|
|
|
488
505
|
/// Map a statement to all its context-sensitive statements
|
|
489
506
|
InstToCxtStmtSet instToCxtStmtSet;
|
|
490
507
|
|
|
491
|
-
|
|
492
508
|
/// Context-sensitive locks
|
|
493
509
|
CxtLockSet cxtLockset;
|
|
494
510
|
|
|
@@ -523,7 +539,6 @@ private:
|
|
|
523
539
|
InstToInstSetMap instTocondCILocksMap;
|
|
524
540
|
//@}
|
|
525
541
|
|
|
526
|
-
|
|
527
542
|
public:
|
|
528
543
|
double lockTime;
|
|
529
544
|
u32_t numOfTotalQueries;
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Created on: Jan 21, 2014
|
|
27
27
|
* Author: Yulei Sui, Peng Di
|
|
28
|
+
*
|
|
29
|
+
* May-happen-in-parallel analysis. One implementation runs on the whole program
|
|
30
|
+
* or a slice: analyze() is templated on the ICFG and CallGraph it traverses
|
|
31
|
+
* (whole graphs or their sliced views), as used by "Multi-Stage On-Demand Program Slicing for
|
|
32
|
+
* Modular Analysis of Multi-Threaded Programs" (ISSTA 2026).
|
|
28
33
|
*/
|
|
29
34
|
|
|
30
35
|
#ifndef MHP_H_
|
|
@@ -33,11 +38,16 @@
|
|
|
33
38
|
#include "MTA/TCT.h"
|
|
34
39
|
#include "Util/SVFUtil.h"
|
|
35
40
|
|
|
41
|
+
#include <memory>
|
|
42
|
+
#include <vector>
|
|
43
|
+
|
|
36
44
|
namespace SVF
|
|
37
45
|
{
|
|
38
46
|
|
|
39
47
|
class ForkJoinAnalysis;
|
|
40
48
|
class LockAnalysis;
|
|
49
|
+
// Forward declaration for the sliced-graph handle analyze() can run on.
|
|
50
|
+
class SlicedSVFIRView;
|
|
41
51
|
|
|
42
52
|
/*!
|
|
43
53
|
* This class serves as a base may-happen in parallel analysis for multithreaded program
|
|
@@ -65,11 +75,15 @@ public:
|
|
|
65
75
|
/// Destructor
|
|
66
76
|
virtual ~MHP();
|
|
67
77
|
|
|
68
|
-
/// Start analysis here
|
|
69
|
-
|
|
78
|
+
/// Start analysis here. One implementation for the whole program and a
|
|
79
|
+
/// slice: the compute is templated on the two graphs it traverses -- the ICFG
|
|
80
|
+
/// (ICFG* whole / const SlicedICFGView* sliced) and the CallGraph (CallGraph*
|
|
81
|
+
/// whole / const SlicedThreadCallGraphView* sliced) -- and calls their
|
|
82
|
+
/// GenericGraphTraits specialisations directly (no wrapper layer).
|
|
83
|
+
template<class ICFGGraph, class CGGraph> void analyze(ICFGGraph icfg, CGGraph cg);
|
|
70
84
|
|
|
71
85
|
/// Analyze thread interleaving
|
|
72
|
-
void analyzeInterleaving();
|
|
86
|
+
template<class ICFGGraph, class CGGraph> void analyzeInterleaving(ICFGGraph icfg, CGGraph cg);
|
|
73
87
|
|
|
74
88
|
/// Get ThreadCallGraph
|
|
75
89
|
inline ThreadCallGraph* getThreadCallGraph() const
|
|
@@ -122,7 +136,7 @@ public:
|
|
|
122
136
|
/// Print interleaving results
|
|
123
137
|
void printInterleaving();
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
protected:
|
|
126
140
|
|
|
127
141
|
inline const CallGraph::FunctionSet& getCallee(const CallICFGNode* inst, CallGraph::FunctionSet& callees)
|
|
128
142
|
{
|
|
@@ -131,25 +145,34 @@ private:
|
|
|
131
145
|
}
|
|
132
146
|
/// Update non-candidate functions' interleaving.
|
|
133
147
|
/// Copy interleaving threads of the entry inst to other insts.
|
|
134
|
-
void updateNonCandidateFunInterleaving();
|
|
148
|
+
template<class ICFGGraph, class CGGraph> void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg);
|
|
135
149
|
|
|
136
150
|
/// Handle non-candidate function
|
|
137
|
-
void handleNonCandidateFun(const CxtThreadStmt& cts);
|
|
151
|
+
template<class ICFGGraph, class CGGraph> void handleNonCandidateFun(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
|
|
138
152
|
|
|
139
153
|
/// Handle fork
|
|
140
|
-
void handleFork(const CxtThreadStmt& cts, NodeID rootTid);
|
|
154
|
+
template<class ICFGGraph, class CGGraph> void handleFork(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
|
|
141
155
|
|
|
142
156
|
/// Handle join
|
|
143
|
-
void handleJoin(const CxtThreadStmt& cts, NodeID rootTid);
|
|
157
|
+
template<class ICFGGraph, class CGGraph> void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
|
|
144
158
|
|
|
145
159
|
/// Handle call
|
|
146
|
-
void handleCall(const CxtThreadStmt& cts, NodeID rootTid);
|
|
160
|
+
template<class ICFGGraph, class CGGraph> void handleCall(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
|
|
147
161
|
|
|
148
162
|
/// Handle return
|
|
149
|
-
void handleRet(const CxtThreadStmt& cts);
|
|
163
|
+
template<class ICFGGraph, class CGGraph> void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
|
|
150
164
|
|
|
151
165
|
/// Handle intra
|
|
152
|
-
void handleIntra(const CxtThreadStmt& cts);
|
|
166
|
+
template<class ICFGGraph, class CGGraph> void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
|
|
167
|
+
|
|
168
|
+
/// Symmetric-join loop-exit kills, applied to EDGE flows (node states stay
|
|
169
|
+
/// pure unions, so paths bypassing the join keep their interleavings).
|
|
170
|
+
//@{
|
|
171
|
+
typedef Map<const SVFBasicBlock*, std::vector<CxtStmt>> BBToSymJoinsMap;
|
|
172
|
+
typedef Map<CxtStmt, Set<const SVFBasicBlock*>> SymJoinToLoopMap;
|
|
173
|
+
void buildSymJoinKillTables();
|
|
174
|
+
NodeBS edgeFlow(const CxtThreadStmt& cts, const ICFGNode* dst);
|
|
175
|
+
//@}
|
|
153
176
|
|
|
154
177
|
/// Add/Remove interleaving thread for statement inst
|
|
155
178
|
//@{
|
|
@@ -170,6 +193,15 @@ private:
|
|
|
170
193
|
pushToCTSWorkList(tgr);
|
|
171
194
|
}
|
|
172
195
|
}
|
|
196
|
+
inline void addInterleavingBits(const CxtThreadStmt& tgr, const NodeBS& bits)
|
|
197
|
+
{
|
|
198
|
+
bool changed = threadStmtToThreadInterLeav[tgr] |= bits;
|
|
199
|
+
if(changed)
|
|
200
|
+
{
|
|
201
|
+
instToTSMap[tgr.getStmt()].insert(tgr);
|
|
202
|
+
pushToCTSWorkList(tgr);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
173
205
|
inline void rmInterleavingThread(const CxtThreadStmt& tgr, const NodeBS& tids, const ICFGNode* joinsite)
|
|
174
206
|
{
|
|
175
207
|
NodeBS joinedTids;
|
|
@@ -187,8 +219,8 @@ private:
|
|
|
187
219
|
|
|
188
220
|
/// Update Ancestor and sibling threads
|
|
189
221
|
//@{
|
|
190
|
-
void updateAncestorThreads(NodeID tid);
|
|
191
|
-
void updateSiblingThreads(NodeID tid);
|
|
222
|
+
template<class ICFGGraph, class CGGraph> void updateAncestorThreads(ICFGGraph icfg, CGGraph cg, NodeID tid);
|
|
223
|
+
template<class ICFGGraph, class CGGraph> void updateSiblingThreads(ICFGGraph icfg, CGGraph cg, NodeID tid);
|
|
192
224
|
//@}
|
|
193
225
|
|
|
194
226
|
/// Thread curTid can be fully joined by parentTid recursively
|
|
@@ -267,10 +299,11 @@ private:
|
|
|
267
299
|
ForkJoinAnalysis* fja; ///< ForJoin Analysis
|
|
268
300
|
CxtThreadStmtWorkList cxtStmtList; ///< CxtThreadStmt worklist
|
|
269
301
|
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav; /// Map a statement to its thread interleavings
|
|
302
|
+
BBToSymJoinsMap bbToSymJoins; ///< loop block -> symmetric in-loop joins of that loop
|
|
303
|
+
SymJoinToLoopMap symJoinLoop; ///< symmetric in-loop join -> its loop's blocks
|
|
270
304
|
InstToThreadStmtSetMap instToTSMap; ///< Map an instruction to its ThreadStmtSet
|
|
271
305
|
FuncPairToBool nonCandidateFuncMHPRelMap;
|
|
272
306
|
|
|
273
|
-
|
|
274
307
|
public:
|
|
275
308
|
u32_t numOfTotalQueries; ///< Total number of queries
|
|
276
309
|
u32_t numOfMHPQueries; ///< Number of queries are answered as may-happen-in-parallel
|
|
@@ -278,8 +311,6 @@ public:
|
|
|
278
311
|
double interleavingQueriesTime;
|
|
279
312
|
};
|
|
280
313
|
|
|
281
|
-
|
|
282
|
-
|
|
283
314
|
/*!
|
|
284
315
|
*
|
|
285
316
|
*/
|
|
@@ -306,7 +337,6 @@ public:
|
|
|
306
337
|
typedef Set<CxtStmt> CxtStmtSet;
|
|
307
338
|
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
|
|
308
339
|
|
|
309
|
-
|
|
310
340
|
ForkJoinAnalysis(TCT* t) : tct(t)
|
|
311
341
|
{
|
|
312
342
|
collectSCEVInfo();
|
|
@@ -363,6 +393,11 @@ public:
|
|
|
363
393
|
{
|
|
364
394
|
return tct->hasJoinLoop(inst);
|
|
365
395
|
}
|
|
396
|
+
/// All SCEV-symmetric in-loop joins and their loop blocks.
|
|
397
|
+
inline const CxtStmtToLoopMap& getSymmetricLoopJoins() const
|
|
398
|
+
{
|
|
399
|
+
return cxtJoinInLoop;
|
|
400
|
+
}
|
|
366
401
|
private:
|
|
367
402
|
|
|
368
403
|
/// Handle fork
|
|
@@ -387,10 +422,8 @@ private:
|
|
|
387
422
|
bool sameLoopTripCount(const ICFGNode* forkSite, const ICFGNode* joinSite);
|
|
388
423
|
|
|
389
424
|
/// Whether it is a matched fork join pair
|
|
390
|
-
bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite)
|
|
391
|
-
|
|
392
|
-
return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId());
|
|
393
|
-
}
|
|
425
|
+
bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite);
|
|
426
|
+
ThreadAPI::ForkJoinAliasCache forkJoinAliasCache;
|
|
394
427
|
/// Mark thread flags for cxtStmt
|
|
395
428
|
//@{
|
|
396
429
|
/// Get the flag for a cxtStmt
|