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
|
@@ -0,0 +1,1801 @@
|
|
|
1
|
+
//===- SlicedGraphs.h -- General sliced graph views ------------------------===//
|
|
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
|
+
* SlicedGraphs.h
|
|
25
|
+
*
|
|
26
|
+
* Author: Jiawei Yang
|
|
27
|
+
*
|
|
28
|
+
* General non-owning sliced views of the ICFG, PAG, and (Thread)CallGraph, and
|
|
29
|
+
* their GenericGraphTraits specialisations, so a slice works with SVF's generic
|
|
30
|
+
* graph algorithms and GraphWriter.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
#ifndef GRAPHS_SLICEDGRAPHS_H
|
|
34
|
+
#define GRAPHS_SLICEDGRAPHS_H
|
|
35
|
+
|
|
36
|
+
#include "Graphs/ICFG.h"
|
|
37
|
+
#include "Graphs/ICFGNode.h"
|
|
38
|
+
#include "Graphs/ICFGEdge.h"
|
|
39
|
+
#include "Graphs/CallGraph.h"
|
|
40
|
+
#include "Graphs/ThreadCallGraph.h"
|
|
41
|
+
#include "Graphs/SVFG.h"
|
|
42
|
+
#include "Graphs/SVFGNode.h"
|
|
43
|
+
#include "Graphs/GraphTraits.h"
|
|
44
|
+
#include "SVFIR/SVFIR.h"
|
|
45
|
+
#include "SVFIR/SVFStatements.h"
|
|
46
|
+
#include "SVFIR/SVFVariables.h"
|
|
47
|
+
#include <cstddef>
|
|
48
|
+
#include <fstream>
|
|
49
|
+
#include <iterator>
|
|
50
|
+
#include <memory>
|
|
51
|
+
#include <set>
|
|
52
|
+
#include <string>
|
|
53
|
+
#include <unordered_map>
|
|
54
|
+
#include <unordered_set>
|
|
55
|
+
#include <vector>
|
|
56
|
+
#include <utility>
|
|
57
|
+
|
|
58
|
+
namespace SVF
|
|
59
|
+
{
|
|
60
|
+
|
|
61
|
+
//===----------------------------------------------------------------------===//
|
|
62
|
+
// SlicedICFGView - sliced view of the ICFG.
|
|
63
|
+
// Provides getSuccNodes()/getPredNodes() restricted to kept nodes, plus the
|
|
64
|
+
// bridged edges produced by contracting removed nodes.
|
|
65
|
+
//===----------------------------------------------------------------------===//
|
|
66
|
+
class SlicedICFGView
|
|
67
|
+
{
|
|
68
|
+
public:
|
|
69
|
+
/// Build complete ICFG view from keepNodes and keptFunctions
|
|
70
|
+
// buildBridged=false skips bridged-edge construction for views whose control
|
|
71
|
+
// flow is never walked (e.g. the FSPTA view, used only for isKeptNode).
|
|
72
|
+
SlicedICFGView(ICFG* icfg,
|
|
73
|
+
CallGraph* cg,
|
|
74
|
+
const OrderedSet<const ICFGNode*>& keepNodes,
|
|
75
|
+
const OrderedSet<const FunObjVar*>& keptFunctions,
|
|
76
|
+
bool buildBridged = true);
|
|
77
|
+
|
|
78
|
+
/// Get successor nodes (including bridged edges)
|
|
79
|
+
void getSuccNodes(const ICFGNode* node, std::vector<const ICFGNode*>& out) const;
|
|
80
|
+
|
|
81
|
+
/// Get predecessor nodes (including bridged edges)
|
|
82
|
+
void getPredNodes(const ICFGNode* node, std::vector<const ICFGNode*>& out) const;
|
|
83
|
+
|
|
84
|
+
/// Check if a node is in the sliced view
|
|
85
|
+
bool isKeptNode(const ICFGNode* node) const;
|
|
86
|
+
|
|
87
|
+
/// First kept node of fun's entry (the kept FunEntryICFGNode, else the first
|
|
88
|
+
/// kept node of the entry block, else the original entry).
|
|
89
|
+
const ICFGNode* getFunEntry(const FunObjVar* fun) const;
|
|
90
|
+
|
|
91
|
+
/// Kept ICFG nodes of fun.
|
|
92
|
+
void getFunICFGNodes(const FunObjVar* fun, std::vector<const ICFGNode*>& out) const;
|
|
93
|
+
|
|
94
|
+
/// Get all kept nodes
|
|
95
|
+
inline const OrderedSet<const ICFGNode*>& getKeptNodes() const
|
|
96
|
+
{
|
|
97
|
+
return keptNodes;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/// Bridged (synthetic) successors/predecessors of a kept node, or null if none.
|
|
101
|
+
/// The traits iterators use these alongside the node's kept original edges.
|
|
102
|
+
inline const OrderedSet<const ICFGNode*>* bridgedSuccsOf(const ICFGNode* n) const
|
|
103
|
+
{
|
|
104
|
+
auto it = bridgedEdges.find(n);
|
|
105
|
+
return it == bridgedEdges.end() ? nullptr : &it->second;
|
|
106
|
+
}
|
|
107
|
+
inline const OrderedSet<const ICFGNode*>* bridgedPredsOf(const ICFGNode* n) const
|
|
108
|
+
{
|
|
109
|
+
auto it = bridgedPreds.find(n);
|
|
110
|
+
return it == bridgedPreds.end() ? nullptr : &it->second;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Dump sliced ICFG to dot file
|
|
114
|
+
void dump(const std::string& filename) const;
|
|
115
|
+
|
|
116
|
+
/// Get original ICFG
|
|
117
|
+
inline ICFG* getOriginalICFG() const
|
|
118
|
+
{
|
|
119
|
+
return icfg;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private:
|
|
123
|
+
ICFG* icfg;
|
|
124
|
+
OrderedSet<const ICFGNode*> keptNodes;
|
|
125
|
+
OrderedSet<const ICFGEdge*> keptEdges;
|
|
126
|
+
Map<const ICFGNode*, OrderedSet<const ICFGNode*>> bridgedEdges;
|
|
127
|
+
// Reverse of bridgedEdges (dst -> srcs), so getPredNodes is O(preds) instead
|
|
128
|
+
// of scanning every bridged edge.
|
|
129
|
+
Map<const ICFGNode*, OrderedSet<const ICFGNode*>> bridgedPreds;
|
|
130
|
+
Set<const ICFGNode*> keptNodesSet; // For fast lookup
|
|
131
|
+
|
|
132
|
+
void buildICFGSets(const OrderedSet<const ICFGNode*>& keepNodes,
|
|
133
|
+
const OrderedSet<const FunObjVar*>& keptFunctions);
|
|
134
|
+
void buildBridgedEdges();
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
//===----------------------------------------------------------------------===//
|
|
138
|
+
// SlicedPAGView - a sliced view of the PAG, built from the kept statements.
|
|
139
|
+
//===----------------------------------------------------------------------===//
|
|
140
|
+
class SlicedPAGView
|
|
141
|
+
{
|
|
142
|
+
public:
|
|
143
|
+
SlicedPAGView(SVFIR* pag, const OrderedSet<const SVFStmt*>& keptStmts);
|
|
144
|
+
|
|
145
|
+
/// Get all kept statements
|
|
146
|
+
inline const OrderedSet<const SVFStmt*>& getKeptStmts() const
|
|
147
|
+
{
|
|
148
|
+
return keptStmts;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// Node IDs (SVFVars) touched by the kept statements -- the sliced PAG's nodes.
|
|
152
|
+
inline const Set<NodeID>& getKeptNodeIds() const
|
|
153
|
+
{
|
|
154
|
+
return keptNodeIds;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/// Canonical edge membership: a kept SVFVar may have incident statements not
|
|
158
|
+
/// in the slice, so traits/queries keep only statements in keptStmts.
|
|
159
|
+
inline bool isKeptStmt(const SVFStmt* s) const
|
|
160
|
+
{
|
|
161
|
+
return keptStmts.count(s) > 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// The underlying SVFIR (to resolve node ids to SVFVars).
|
|
165
|
+
inline SVFIR* getSVFIR() const
|
|
166
|
+
{
|
|
167
|
+
return pag;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// Dump the sliced PAG to a dot file
|
|
171
|
+
void dump(const std::string& filename) const;
|
|
172
|
+
|
|
173
|
+
private:
|
|
174
|
+
SVFIR* pag;
|
|
175
|
+
OrderedSet<const SVFStmt*> keptStmts;
|
|
176
|
+
Set<NodeID> keptNodeIds; // node IDs extracted from kept statements
|
|
177
|
+
|
|
178
|
+
void buildKeptNodeIds();
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
//===----------------------------------------------------------------------===//
|
|
182
|
+
// SlicedThreadCallGraphView - sliced view of the ThreadCallGraph, built from the
|
|
183
|
+
// kept functions.
|
|
184
|
+
//===----------------------------------------------------------------------===//
|
|
185
|
+
class SlicedThreadCallGraphView
|
|
186
|
+
{
|
|
187
|
+
public:
|
|
188
|
+
SlicedThreadCallGraphView(ThreadCallGraph* tcg,
|
|
189
|
+
const OrderedSet<const FunObjVar*>& keptFunctions,
|
|
190
|
+
const OrderedSet<const ICFGNode*>& extendedKeptNodes = OrderedSet<const ICFGNode*>());
|
|
191
|
+
|
|
192
|
+
/// Get out edges of a node (only returns kept edges and target nodes)
|
|
193
|
+
void getOutEdgesOf(const CallGraphNode* node, std::vector<const CallGraphEdge*>& out) const;
|
|
194
|
+
|
|
195
|
+
/// Get in edges of a node (only returns kept edges and source nodes)
|
|
196
|
+
void getInEdgesOf(const CallGraphNode* node, std::vector<const CallGraphEdge*>& out) const;
|
|
197
|
+
|
|
198
|
+
/// Check if a node is in the sliced view
|
|
199
|
+
bool isKeptNode(const CallGraphNode* node) const;
|
|
200
|
+
|
|
201
|
+
/// Get all kept nodes
|
|
202
|
+
inline const OrderedSet<const CallGraphNode*>& getKeptNodes() const
|
|
203
|
+
{
|
|
204
|
+
return keptNodes;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const Set<const FunObjVar*>& getKeptFunctions() const
|
|
208
|
+
{
|
|
209
|
+
return keptFunctionsSet;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/// Get all kept edges
|
|
213
|
+
inline const CallGraph::CallGraphEdgeSet& getKeptEdges() const
|
|
214
|
+
{
|
|
215
|
+
return keptEdges;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// Canonical edge membership: keptEdges excludes edges whose call site was
|
|
219
|
+
/// pruned, so endpoint checks alone are not enough (queries/traits use this).
|
|
220
|
+
inline bool isKeptEdge(const CallGraphEdge* e) const
|
|
221
|
+
{
|
|
222
|
+
return keptEdges.find(const_cast<CallGraphEdge*>(e)) != keptEdges.end();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// Indirect call sites that lost all targets after filtering
|
|
226
|
+
inline const Set<const CallICFGNode*>& getIndirectSitesWithEmptyTargets() const
|
|
227
|
+
{
|
|
228
|
+
return indirectSitesWithEmptyTargets;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Dump sliced ThreadCallGraph to dot file
|
|
232
|
+
void dump(const std::string& filename) const;
|
|
233
|
+
|
|
234
|
+
/// Get original ThreadCallGraph
|
|
235
|
+
inline ThreadCallGraph* getOriginalThreadCallGraph() const
|
|
236
|
+
{
|
|
237
|
+
return tcg;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/// Get original CallGraph (ThreadCallGraph inherits from CallGraph)
|
|
241
|
+
inline CallGraph* getOriginalCallGraph() const
|
|
242
|
+
{
|
|
243
|
+
return tcg;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private:
|
|
247
|
+
ThreadCallGraph* tcg;
|
|
248
|
+
OrderedSet<const CallGraphNode*> keptNodes;
|
|
249
|
+
CallGraph::CallGraphEdgeSet keptEdges;
|
|
250
|
+
Set<const FunObjVar*> keptFunctionsSet; // For fast lookup
|
|
251
|
+
Set<const CallICFGNode*> indirectSitesWithEmptyTargets;
|
|
252
|
+
OrderedSet<const ICFGNode*> extendedKeptNodes; // For checking if call sites are kept
|
|
253
|
+
|
|
254
|
+
void buildKeptNodes();
|
|
255
|
+
void buildCallGraphSets();
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
//===----------------------------------------------------------------------===//
|
|
259
|
+
// SlicedSVFGView - non-owning sliced view of the (thread-aware) SVFG.
|
|
260
|
+
// Retained nodes: everything except Load/Store statement nodes whose ICFG node
|
|
261
|
+
// was sliced out; structural nodes (Addr/Copy/Gep, MSSA phi/mu/chi, call/return
|
|
262
|
+
// boundaries) always remain so inter-procedural and memory-SSA flow is intact.
|
|
263
|
+
// Deliberately NO bridge edges: bridging removed SVFG nodes could fabricate
|
|
264
|
+
// value-flow paths that do not exist in the original graph. Removed nodes act
|
|
265
|
+
// as propagation barriers (matching the sliced FSAM solve).
|
|
266
|
+
//===----------------------------------------------------------------------===//
|
|
267
|
+
class SlicedSVFGView
|
|
268
|
+
{
|
|
269
|
+
public:
|
|
270
|
+
/// Membership needs only the sliced ICFG view; the SVFG handle (for node
|
|
271
|
+
/// iteration and dumping) may be bound later, once the solver has built it.
|
|
272
|
+
explicit SlicedSVFGView(const SlicedICFGView* icfgView, const SVFG* svfg = nullptr)
|
|
273
|
+
: icfgView(icfgView), svfg(svfg) {}
|
|
274
|
+
|
|
275
|
+
/// Whether the node is retained (see the class comment for the rule).
|
|
276
|
+
bool isKeptNode(const SVFGNode* n) const;
|
|
277
|
+
|
|
278
|
+
/// Whether the edge is retained: both endpoints kept (no bridges).
|
|
279
|
+
inline bool isKeptEdge(const SVFGEdge* e) const
|
|
280
|
+
{
|
|
281
|
+
return isKeptNode(e->getSrcNode()) && isKeptNode(e->getDstNode());
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
inline const SlicedICFGView* getICFGView() const
|
|
285
|
+
{
|
|
286
|
+
return icfgView;
|
|
287
|
+
}
|
|
288
|
+
inline const SVFG* getSVFG() const
|
|
289
|
+
{
|
|
290
|
+
return svfg;
|
|
291
|
+
}
|
|
292
|
+
/// Bind the underlying SVFG (enables node iteration and dumping).
|
|
293
|
+
inline void setSVFG(const SVFG* g)
|
|
294
|
+
{
|
|
295
|
+
svfg = g;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/// Dump the sliced SVFG (retained nodes/edges only) via GraphWriter.
|
|
299
|
+
void dump(const std::string& filename) const;
|
|
300
|
+
|
|
301
|
+
private:
|
|
302
|
+
const SlicedICFGView* icfgView;
|
|
303
|
+
const SVFG* svfg;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
//===----------------------------------------------------------------------===//
|
|
307
|
+
// SlicedSVFIRView - unified facade over the three sliced graph views.
|
|
308
|
+
// The MTA pipeline always slices over a ThreadCallGraph.
|
|
309
|
+
//===----------------------------------------------------------------------===//
|
|
310
|
+
class SlicedSVFIRView
|
|
311
|
+
{
|
|
312
|
+
public:
|
|
313
|
+
SlicedSVFIRView(SVFIR* svfIr,
|
|
314
|
+
CallGraph* cg,
|
|
315
|
+
ICFG* icfg,
|
|
316
|
+
const OrderedSet<const ICFGNode*>& keepNodes,
|
|
317
|
+
bool buildBridged = true);
|
|
318
|
+
|
|
319
|
+
/// Get SlicedICFGView
|
|
320
|
+
inline const SlicedICFGView* getICFG() const
|
|
321
|
+
{
|
|
322
|
+
return icfgView.get();
|
|
323
|
+
}
|
|
324
|
+
inline SlicedICFGView* getICFG()
|
|
325
|
+
{
|
|
326
|
+
return icfgView.get();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/// Get SlicedPAGView
|
|
330
|
+
inline const SlicedPAGView* getPAG() const
|
|
331
|
+
{
|
|
332
|
+
return pagView.get();
|
|
333
|
+
}
|
|
334
|
+
inline SlicedPAGView* getPAG()
|
|
335
|
+
{
|
|
336
|
+
return pagView.get();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/// Get SlicedThreadCallGraphView
|
|
340
|
+
inline const SlicedThreadCallGraphView* getThreadCallGraph() const
|
|
341
|
+
{
|
|
342
|
+
return tcgView.get();
|
|
343
|
+
}
|
|
344
|
+
inline SlicedThreadCallGraphView* getThreadCallGraph()
|
|
345
|
+
{
|
|
346
|
+
return tcgView.get();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/// Get all kept functions
|
|
350
|
+
inline const Set<const FunObjVar*>& getKeptFunctions() const
|
|
351
|
+
{
|
|
352
|
+
return tcgView->getKeptFunctions();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/// Get indirect call sites that lost all targets after filtering
|
|
356
|
+
inline const Set<const CallICFGNode*>& getIndirectSitesWithEmptyTargets() const
|
|
357
|
+
{
|
|
358
|
+
return tcgView->getIndirectSitesWithEmptyTargets();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/// Get all kept statements
|
|
362
|
+
inline const OrderedSet<const SVFStmt*>& getKeptStatements() const
|
|
363
|
+
{
|
|
364
|
+
return pagView->getKeptStmts();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/// In-edges of a call-graph node under the sliced ThreadCallGraph view (the
|
|
368
|
+
/// full node in-edges if no TCG view was built).
|
|
369
|
+
void getInEdgesOfCallGraphNode(const CallGraphNode* node,
|
|
370
|
+
std::vector<const CallGraphEdge*>& out) const;
|
|
371
|
+
|
|
372
|
+
/// The CallGraph the sliced analyses scan: the sliced ThreadCallGraph's
|
|
373
|
+
/// original CallGraph, or the full PAG CallGraph if no TCG view was built.
|
|
374
|
+
const CallGraph* getAnalysisCallGraph() const;
|
|
375
|
+
|
|
376
|
+
/// Dump all views to files
|
|
377
|
+
void dumpAll(const std::string& prefix) const;
|
|
378
|
+
|
|
379
|
+
/// Get original SVFIR
|
|
380
|
+
inline SVFIR* getSVFIR() const
|
|
381
|
+
{
|
|
382
|
+
return svfIr;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/// Output statistics
|
|
386
|
+
void dumpStats(const std::string& prefix = "") const;
|
|
387
|
+
|
|
388
|
+
private:
|
|
389
|
+
SVFIR* svfIr;
|
|
390
|
+
std::unique_ptr<SlicedICFGView> icfgView;
|
|
391
|
+
std::unique_ptr<SlicedPAGView> pagView;
|
|
392
|
+
std::unique_ptr<SlicedThreadCallGraphView> tcgView;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
//===----------------------------------------------------------------------===//
|
|
396
|
+
// GenericGraphTraits for the sliced leaf views. The views do NOT inherit
|
|
397
|
+
// GenericGraph (they are non-owning); these stateless specializations make them
|
|
398
|
+
// usable with SVF's generic graph algorithms and GraphWriter. The NodeRef is a
|
|
399
|
+
// light value carrying (view, raw-node) so the same raw node under two different
|
|
400
|
+
// slices is a distinct node. (Kept in this header next to the views, as ICFG.h
|
|
401
|
+
// keeps GenericGraphTraits<ICFG*>.)
|
|
402
|
+
//===----------------------------------------------------------------------===//
|
|
403
|
+
|
|
404
|
+
// Contextual value NodeRef: a raw node paired with the view it is viewed under.
|
|
405
|
+
template <class ViewT, class RawNodeT>
|
|
406
|
+
struct SlicedNodeRef
|
|
407
|
+
{
|
|
408
|
+
const ViewT* view = nullptr;
|
|
409
|
+
const RawNodeT* raw = nullptr;
|
|
410
|
+
|
|
411
|
+
SlicedNodeRef() = default;
|
|
412
|
+
SlicedNodeRef(const ViewT* v, const RawNodeT* r) : view(v), raw(r) {}
|
|
413
|
+
|
|
414
|
+
explicit operator bool() const
|
|
415
|
+
{
|
|
416
|
+
return raw != nullptr;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
friend bool operator==(SlicedNodeRef lhs, SlicedNodeRef rhs)
|
|
420
|
+
{
|
|
421
|
+
return lhs.view == rhs.view && lhs.raw == rhs.raw;
|
|
422
|
+
}
|
|
423
|
+
friend bool operator!=(SlicedNodeRef lhs, SlicedNodeRef rhs)
|
|
424
|
+
{
|
|
425
|
+
return !(lhs == rhs);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
using SlicedICFGNodeRef = SlicedNodeRef<SlicedICFGView, ICFGNode>;
|
|
430
|
+
|
|
431
|
+
// A sliced ICFG edge. underlying==nullptr && bridged==true for synthetic bridges.
|
|
432
|
+
struct SlicedICFGEdgeRef
|
|
433
|
+
{
|
|
434
|
+
SlicedICFGNodeRef src;
|
|
435
|
+
SlicedICFGNodeRef dst;
|
|
436
|
+
const ICFGEdge* underlying = nullptr;
|
|
437
|
+
bool bridged = false;
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// Forward/reverse child-edge iterator over a kept node: first its kept original
|
|
441
|
+
// edges, then its bridged edges. Forward==true walks out-edges/bridgedSuccs;
|
|
442
|
+
// Forward==false walks in-edges/bridgedPreds. A standard forward iterator.
|
|
443
|
+
template <bool Forward>
|
|
444
|
+
class SlicedICFGEdgeIterImpl
|
|
445
|
+
{
|
|
446
|
+
public:
|
|
447
|
+
using iterator_category = std::forward_iterator_tag;
|
|
448
|
+
using value_type = SlicedICFGEdgeRef;
|
|
449
|
+
using difference_type = std::ptrdiff_t;
|
|
450
|
+
using pointer = const SlicedICFGEdgeRef*;
|
|
451
|
+
using reference = const SlicedICFGEdgeRef&;
|
|
452
|
+
|
|
453
|
+
SlicedICFGEdgeIterImpl() = default;
|
|
454
|
+
|
|
455
|
+
static SlicedICFGEdgeIterImpl begin(const SlicedICFGView* v, const ICFGNode* n)
|
|
456
|
+
{
|
|
457
|
+
SlicedICFGEdgeIterImpl it(v, n);
|
|
458
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
459
|
+
it.realIt = edges.begin();
|
|
460
|
+
it.realEnd = edges.end();
|
|
461
|
+
it.bridged = Forward ? v->bridgedSuccsOf(n) : v->bridgedPredsOf(n);
|
|
462
|
+
it.brIt = it.bridged ? it.bridged->begin() : emptySet().begin();
|
|
463
|
+
it.brEnd = it.bridged ? it.bridged->end() : emptySet().end();
|
|
464
|
+
it.skipNonKeptReal();
|
|
465
|
+
it.refresh();
|
|
466
|
+
return it;
|
|
467
|
+
}
|
|
468
|
+
static SlicedICFGEdgeIterImpl end(const SlicedICFGView* v, const ICFGNode* n)
|
|
469
|
+
{
|
|
470
|
+
SlicedICFGEdgeIterImpl it(v, n);
|
|
471
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
472
|
+
it.realIt = edges.end();
|
|
473
|
+
it.realEnd = edges.end();
|
|
474
|
+
it.bridged = Forward ? v->bridgedSuccsOf(n) : v->bridgedPredsOf(n);
|
|
475
|
+
it.brIt = it.bridged ? it.bridged->end() : emptySet().end();
|
|
476
|
+
it.brEnd = it.bridged ? it.bridged->end() : emptySet().end();
|
|
477
|
+
return it;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
reference operator*() const
|
|
481
|
+
{
|
|
482
|
+
return cur;
|
|
483
|
+
}
|
|
484
|
+
pointer operator->() const
|
|
485
|
+
{
|
|
486
|
+
return &cur;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// The node this edge traverses to (successor for Forward, predecessor for Inverse).
|
|
490
|
+
SlicedICFGNodeRef target() const
|
|
491
|
+
{
|
|
492
|
+
return Forward ? cur.dst : cur.src;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
SlicedICFGEdgeIterImpl& operator++()
|
|
496
|
+
{
|
|
497
|
+
if (realIt != realEnd)
|
|
498
|
+
{
|
|
499
|
+
++realIt;
|
|
500
|
+
skipNonKeptReal();
|
|
501
|
+
}
|
|
502
|
+
else if (brIt != brEnd)
|
|
503
|
+
{
|
|
504
|
+
++brIt;
|
|
505
|
+
}
|
|
506
|
+
refresh();
|
|
507
|
+
return *this;
|
|
508
|
+
}
|
|
509
|
+
SlicedICFGEdgeIterImpl operator++(int)
|
|
510
|
+
{
|
|
511
|
+
SlicedICFGEdgeIterImpl t = *this;
|
|
512
|
+
++*this;
|
|
513
|
+
return t;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
friend bool operator==(const SlicedICFGEdgeIterImpl& a, const SlicedICFGEdgeIterImpl& b)
|
|
517
|
+
{
|
|
518
|
+
return a.view == b.view && a.src == b.src && a.realIt == b.realIt && a.brIt == b.brIt;
|
|
519
|
+
}
|
|
520
|
+
friend bool operator!=(const SlicedICFGEdgeIterImpl& a, const SlicedICFGEdgeIterImpl& b)
|
|
521
|
+
{
|
|
522
|
+
return !(a == b);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private:
|
|
526
|
+
using EdgeIt = ICFGNode::const_iterator;
|
|
527
|
+
using BrIt = OrderedSet<const ICFGNode*>::const_iterator;
|
|
528
|
+
|
|
529
|
+
const SlicedICFGView* view = nullptr;
|
|
530
|
+
const ICFGNode* src = nullptr;
|
|
531
|
+
EdgeIt realIt{}, realEnd{};
|
|
532
|
+
const OrderedSet<const ICFGNode*>* bridged = nullptr;
|
|
533
|
+
BrIt brIt{}, brEnd{};
|
|
534
|
+
SlicedICFGEdgeRef cur{};
|
|
535
|
+
|
|
536
|
+
SlicedICFGEdgeIterImpl(const SlicedICFGView* v, const ICFGNode* n) : view(v), src(n) {}
|
|
537
|
+
|
|
538
|
+
static const OrderedSet<const ICFGNode*>& emptySet()
|
|
539
|
+
{
|
|
540
|
+
static const OrderedSet<const ICFGNode*> e;
|
|
541
|
+
return e;
|
|
542
|
+
}
|
|
543
|
+
static const ICFGNode* other(const ICFGEdge* e)
|
|
544
|
+
{
|
|
545
|
+
return Forward ? e->getDstNode() : e->getSrcNode();
|
|
546
|
+
}
|
|
547
|
+
void skipNonKeptReal()
|
|
548
|
+
{
|
|
549
|
+
while (realIt != realEnd && !view->isKeptNode(other(*realIt))) ++realIt;
|
|
550
|
+
}
|
|
551
|
+
void refresh()
|
|
552
|
+
{
|
|
553
|
+
if (realIt != realEnd)
|
|
554
|
+
{
|
|
555
|
+
const ICFGEdge* e = *realIt;
|
|
556
|
+
SlicedICFGNodeRef a{view, e->getSrcNode()}, b{view, e->getDstNode()};
|
|
557
|
+
cur = SlicedICFGEdgeRef{a, b, e, false};
|
|
558
|
+
}
|
|
559
|
+
else if (brIt != brEnd)
|
|
560
|
+
{
|
|
561
|
+
SlicedICFGNodeRef self{view, src}, adj{view, *brIt};
|
|
562
|
+
cur = Forward ? SlicedICFGEdgeRef{self, adj, nullptr, true}
|
|
563
|
+
:
|
|
564
|
+
SlicedICFGEdgeRef{adj, self, nullptr, true};
|
|
565
|
+
}
|
|
566
|
+
else
|
|
567
|
+
{
|
|
568
|
+
cur = SlicedICFGEdgeRef{};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
// Node-child iterator: adapts the edge iterator, dereferencing to the traversed
|
|
574
|
+
// node; currentEdge() exposes the domain edge (for bridged-aware DOT styling).
|
|
575
|
+
template <bool Forward>
|
|
576
|
+
class SlicedICFGChildIterImpl
|
|
577
|
+
{
|
|
578
|
+
public:
|
|
579
|
+
using iterator_category = std::forward_iterator_tag;
|
|
580
|
+
using value_type = SlicedICFGNodeRef;
|
|
581
|
+
using difference_type = std::ptrdiff_t;
|
|
582
|
+
using pointer = const SlicedICFGNodeRef*;
|
|
583
|
+
using reference = SlicedICFGNodeRef;
|
|
584
|
+
|
|
585
|
+
SlicedICFGChildIterImpl() = default;
|
|
586
|
+
explicit SlicedICFGChildIterImpl(SlicedICFGEdgeIterImpl<Forward> it) : e(it) {}
|
|
587
|
+
|
|
588
|
+
reference operator*() const
|
|
589
|
+
{
|
|
590
|
+
return e.target();
|
|
591
|
+
}
|
|
592
|
+
const SlicedICFGEdgeRef& currentEdge() const
|
|
593
|
+
{
|
|
594
|
+
return *e;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
SlicedICFGChildIterImpl& operator++()
|
|
598
|
+
{
|
|
599
|
+
++e;
|
|
600
|
+
return *this;
|
|
601
|
+
}
|
|
602
|
+
SlicedICFGChildIterImpl operator++(int)
|
|
603
|
+
{
|
|
604
|
+
SlicedICFGChildIterImpl t = *this;
|
|
605
|
+
++e;
|
|
606
|
+
return t;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
friend bool operator==(const SlicedICFGChildIterImpl& a, const SlicedICFGChildIterImpl& b)
|
|
610
|
+
{
|
|
611
|
+
return a.e == b.e;
|
|
612
|
+
}
|
|
613
|
+
friend bool operator!=(const SlicedICFGChildIterImpl& a, const SlicedICFGChildIterImpl& b)
|
|
614
|
+
{
|
|
615
|
+
return !(a == b);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
private:
|
|
619
|
+
SlicedICFGEdgeIterImpl<Forward> e{};
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// Node iterator over the kept-node set, yielding contextual NodeRefs.
|
|
623
|
+
class SlicedICFGNodeIter
|
|
624
|
+
{
|
|
625
|
+
public:
|
|
626
|
+
using iterator_category = std::forward_iterator_tag;
|
|
627
|
+
using value_type = SlicedICFGNodeRef;
|
|
628
|
+
using difference_type = std::ptrdiff_t;
|
|
629
|
+
using pointer = const SlicedICFGNodeRef*;
|
|
630
|
+
using reference = SlicedICFGNodeRef;
|
|
631
|
+
|
|
632
|
+
SlicedICFGNodeIter() = default;
|
|
633
|
+
SlicedICFGNodeIter(const SlicedICFGView* v, OrderedSet<const ICFGNode*>::const_iterator i)
|
|
634
|
+
: view(v), it(i) {}
|
|
635
|
+
|
|
636
|
+
reference operator*() const
|
|
637
|
+
{
|
|
638
|
+
return SlicedICFGNodeRef{view, *it};
|
|
639
|
+
}
|
|
640
|
+
SlicedICFGNodeIter& operator++()
|
|
641
|
+
{
|
|
642
|
+
++it;
|
|
643
|
+
return *this;
|
|
644
|
+
}
|
|
645
|
+
SlicedICFGNodeIter operator++(int)
|
|
646
|
+
{
|
|
647
|
+
SlicedICFGNodeIter t = *this;
|
|
648
|
+
++it;
|
|
649
|
+
return t;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
friend bool operator==(const SlicedICFGNodeIter& a, const SlicedICFGNodeIter& b)
|
|
653
|
+
{
|
|
654
|
+
return a.it == b.it;
|
|
655
|
+
}
|
|
656
|
+
friend bool operator!=(const SlicedICFGNodeIter& a, const SlicedICFGNodeIter& b)
|
|
657
|
+
{
|
|
658
|
+
return !(a == b);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
private:
|
|
662
|
+
const SlicedICFGView* view = nullptr;
|
|
663
|
+
OrderedSet<const ICFGNode*>::const_iterator it{};
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
//===----------------------------------------------------------------------===//
|
|
667
|
+
// SlicedThreadCallGraphView traits support (no bridged edges; canonical
|
|
668
|
+
// adjacency is the kept-edge set, so pruned-call-site edges never appear).
|
|
669
|
+
//===----------------------------------------------------------------------===//
|
|
670
|
+
|
|
671
|
+
using SlicedCallGraphNodeRef = SlicedNodeRef<SlicedThreadCallGraphView, CallGraphNode>;
|
|
672
|
+
|
|
673
|
+
struct SlicedCallGraphEdgeRef
|
|
674
|
+
{
|
|
675
|
+
SlicedCallGraphNodeRef src;
|
|
676
|
+
SlicedCallGraphNodeRef dst;
|
|
677
|
+
const CallGraphEdge* underlying = nullptr;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
// Forward==true walks kept out-edges; Forward==false walks kept in-edges. Join
|
|
681
|
+
// edges are not part of the node's normal adjacency, so they never appear here.
|
|
682
|
+
template <bool Forward>
|
|
683
|
+
class SlicedCGEdgeIterImpl
|
|
684
|
+
{
|
|
685
|
+
public:
|
|
686
|
+
using iterator_category = std::forward_iterator_tag;
|
|
687
|
+
using value_type = SlicedCallGraphEdgeRef;
|
|
688
|
+
using difference_type = std::ptrdiff_t;
|
|
689
|
+
using pointer = const SlicedCallGraphEdgeRef*;
|
|
690
|
+
using reference = const SlicedCallGraphEdgeRef&;
|
|
691
|
+
|
|
692
|
+
SlicedCGEdgeIterImpl() = default;
|
|
693
|
+
|
|
694
|
+
static SlicedCGEdgeIterImpl begin(const SlicedThreadCallGraphView* v, const CallGraphNode* n)
|
|
695
|
+
{
|
|
696
|
+
SlicedCGEdgeIterImpl it(v, n);
|
|
697
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
698
|
+
it.realIt = edges.begin();
|
|
699
|
+
it.realEnd = edges.end();
|
|
700
|
+
it.skipNonKept();
|
|
701
|
+
it.refresh();
|
|
702
|
+
return it;
|
|
703
|
+
}
|
|
704
|
+
static SlicedCGEdgeIterImpl end(const SlicedThreadCallGraphView* v, const CallGraphNode* n)
|
|
705
|
+
{
|
|
706
|
+
SlicedCGEdgeIterImpl it(v, n);
|
|
707
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
708
|
+
it.realIt = edges.end();
|
|
709
|
+
it.realEnd = edges.end();
|
|
710
|
+
return it;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
reference operator*() const
|
|
714
|
+
{
|
|
715
|
+
return cur;
|
|
716
|
+
}
|
|
717
|
+
pointer operator->() const
|
|
718
|
+
{
|
|
719
|
+
return &cur;
|
|
720
|
+
}
|
|
721
|
+
SlicedCallGraphNodeRef target() const
|
|
722
|
+
{
|
|
723
|
+
return Forward ? cur.dst : cur.src;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
SlicedCGEdgeIterImpl& operator++()
|
|
727
|
+
{
|
|
728
|
+
if (realIt != realEnd)
|
|
729
|
+
{
|
|
730
|
+
++realIt;
|
|
731
|
+
skipNonKept();
|
|
732
|
+
}
|
|
733
|
+
refresh();
|
|
734
|
+
return *this;
|
|
735
|
+
}
|
|
736
|
+
SlicedCGEdgeIterImpl operator++(int)
|
|
737
|
+
{
|
|
738
|
+
SlicedCGEdgeIterImpl t = *this;
|
|
739
|
+
++*this;
|
|
740
|
+
return t;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
friend bool operator==(const SlicedCGEdgeIterImpl& a, const SlicedCGEdgeIterImpl& b)
|
|
744
|
+
{
|
|
745
|
+
return a.view == b.view && a.src == b.src && a.realIt == b.realIt;
|
|
746
|
+
}
|
|
747
|
+
friend bool operator!=(const SlicedCGEdgeIterImpl& a, const SlicedCGEdgeIterImpl& b)
|
|
748
|
+
{
|
|
749
|
+
return !(a == b);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
private:
|
|
753
|
+
using EdgeIt = CallGraphNode::const_iterator;
|
|
754
|
+
const SlicedThreadCallGraphView* view = nullptr;
|
|
755
|
+
const CallGraphNode* src = nullptr;
|
|
756
|
+
EdgeIt realIt{}, realEnd{};
|
|
757
|
+
SlicedCallGraphEdgeRef cur{};
|
|
758
|
+
|
|
759
|
+
SlicedCGEdgeIterImpl(const SlicedThreadCallGraphView* v, const CallGraphNode* n) : view(v), src(n) {}
|
|
760
|
+
|
|
761
|
+
void skipNonKept()
|
|
762
|
+
{
|
|
763
|
+
while (realIt != realEnd && !view->isKeptEdge(*realIt)) ++realIt;
|
|
764
|
+
}
|
|
765
|
+
void refresh()
|
|
766
|
+
{
|
|
767
|
+
if (realIt != realEnd)
|
|
768
|
+
{
|
|
769
|
+
const CallGraphEdge* e = *realIt;
|
|
770
|
+
cur = SlicedCallGraphEdgeRef{{view, e->getSrcNode()}, {view, e->getDstNode()}, e};
|
|
771
|
+
}
|
|
772
|
+
else
|
|
773
|
+
{
|
|
774
|
+
cur = SlicedCallGraphEdgeRef{};
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
template <bool Forward>
|
|
780
|
+
class SlicedCGChildIterImpl
|
|
781
|
+
{
|
|
782
|
+
public:
|
|
783
|
+
using iterator_category = std::forward_iterator_tag;
|
|
784
|
+
using value_type = SlicedCallGraphNodeRef;
|
|
785
|
+
using difference_type = std::ptrdiff_t;
|
|
786
|
+
using pointer = const SlicedCallGraphNodeRef*;
|
|
787
|
+
using reference = SlicedCallGraphNodeRef;
|
|
788
|
+
|
|
789
|
+
SlicedCGChildIterImpl() = default;
|
|
790
|
+
explicit SlicedCGChildIterImpl(SlicedCGEdgeIterImpl<Forward> it) : e(it) {}
|
|
791
|
+
|
|
792
|
+
reference operator*() const
|
|
793
|
+
{
|
|
794
|
+
return e.target();
|
|
795
|
+
}
|
|
796
|
+
const SlicedCallGraphEdgeRef& currentEdge() const
|
|
797
|
+
{
|
|
798
|
+
return *e;
|
|
799
|
+
}
|
|
800
|
+
SlicedCGChildIterImpl& operator++()
|
|
801
|
+
{
|
|
802
|
+
++e;
|
|
803
|
+
return *this;
|
|
804
|
+
}
|
|
805
|
+
SlicedCGChildIterImpl operator++(int)
|
|
806
|
+
{
|
|
807
|
+
SlicedCGChildIterImpl t = *this;
|
|
808
|
+
++e;
|
|
809
|
+
return t;
|
|
810
|
+
}
|
|
811
|
+
friend bool operator==(const SlicedCGChildIterImpl& a, const SlicedCGChildIterImpl& b)
|
|
812
|
+
{
|
|
813
|
+
return a.e == b.e;
|
|
814
|
+
}
|
|
815
|
+
friend bool operator!=(const SlicedCGChildIterImpl& a, const SlicedCGChildIterImpl& b)
|
|
816
|
+
{
|
|
817
|
+
return !(a == b);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
private:
|
|
821
|
+
SlicedCGEdgeIterImpl<Forward> e{};
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
class SlicedCGNodeIter
|
|
825
|
+
{
|
|
826
|
+
public:
|
|
827
|
+
using iterator_category = std::forward_iterator_tag;
|
|
828
|
+
using value_type = SlicedCallGraphNodeRef;
|
|
829
|
+
using difference_type = std::ptrdiff_t;
|
|
830
|
+
using pointer = const SlicedCallGraphNodeRef*;
|
|
831
|
+
using reference = SlicedCallGraphNodeRef;
|
|
832
|
+
|
|
833
|
+
SlicedCGNodeIter() = default;
|
|
834
|
+
SlicedCGNodeIter(const SlicedThreadCallGraphView* v, OrderedSet<const CallGraphNode*>::const_iterator i)
|
|
835
|
+
: view(v), it(i) {}
|
|
836
|
+
|
|
837
|
+
reference operator*() const
|
|
838
|
+
{
|
|
839
|
+
return SlicedCallGraphNodeRef{view, *it};
|
|
840
|
+
}
|
|
841
|
+
SlicedCGNodeIter& operator++()
|
|
842
|
+
{
|
|
843
|
+
++it;
|
|
844
|
+
return *this;
|
|
845
|
+
}
|
|
846
|
+
SlicedCGNodeIter operator++(int)
|
|
847
|
+
{
|
|
848
|
+
SlicedCGNodeIter t = *this;
|
|
849
|
+
++it;
|
|
850
|
+
return t;
|
|
851
|
+
}
|
|
852
|
+
friend bool operator==(const SlicedCGNodeIter& a, const SlicedCGNodeIter& b)
|
|
853
|
+
{
|
|
854
|
+
return a.it == b.it;
|
|
855
|
+
}
|
|
856
|
+
friend bool operator!=(const SlicedCGNodeIter& a, const SlicedCGNodeIter& b)
|
|
857
|
+
{
|
|
858
|
+
return !(a == b);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
private:
|
|
862
|
+
const SlicedThreadCallGraphView* view = nullptr;
|
|
863
|
+
OrderedSet<const CallGraphNode*>::const_iterator it{};
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
//===----------------------------------------------------------------------===//
|
|
867
|
+
// SlicedPAGView traits support. Nodes are the SVFVars touched by kept statements;
|
|
868
|
+
// edges are the kept SVFStmts (a kept var may have non-kept incident statements,
|
|
869
|
+
// so keptStmts membership is the canonical filter). MultiOpndStmts use the
|
|
870
|
+
// underlying SVFStmt src/dst (first operand -> result), not an operand fan-out.
|
|
871
|
+
//===----------------------------------------------------------------------===//
|
|
872
|
+
|
|
873
|
+
using SlicedPAGNodeRef = SlicedNodeRef<SlicedPAGView, SVFVar>;
|
|
874
|
+
|
|
875
|
+
struct SlicedPAGEdgeRef
|
|
876
|
+
{
|
|
877
|
+
SlicedPAGNodeRef src;
|
|
878
|
+
SlicedPAGNodeRef dst;
|
|
879
|
+
const SVFStmt* underlying = nullptr;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
template <bool Forward>
|
|
883
|
+
class SlicedPAGEdgeIterImpl
|
|
884
|
+
{
|
|
885
|
+
public:
|
|
886
|
+
using iterator_category = std::forward_iterator_tag;
|
|
887
|
+
using value_type = SlicedPAGEdgeRef;
|
|
888
|
+
using difference_type = std::ptrdiff_t;
|
|
889
|
+
using pointer = const SlicedPAGEdgeRef*;
|
|
890
|
+
using reference = const SlicedPAGEdgeRef&;
|
|
891
|
+
|
|
892
|
+
SlicedPAGEdgeIterImpl() = default;
|
|
893
|
+
|
|
894
|
+
static SlicedPAGEdgeIterImpl begin(const SlicedPAGView* v, const SVFVar* n)
|
|
895
|
+
{
|
|
896
|
+
SlicedPAGEdgeIterImpl it(v, n);
|
|
897
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
898
|
+
it.realIt = edges.begin();
|
|
899
|
+
it.realEnd = edges.end();
|
|
900
|
+
it.skipNonKept();
|
|
901
|
+
it.refresh();
|
|
902
|
+
return it;
|
|
903
|
+
}
|
|
904
|
+
static SlicedPAGEdgeIterImpl end(const SlicedPAGView* v, const SVFVar* n)
|
|
905
|
+
{
|
|
906
|
+
SlicedPAGEdgeIterImpl it(v, n);
|
|
907
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
908
|
+
it.realIt = edges.end();
|
|
909
|
+
it.realEnd = edges.end();
|
|
910
|
+
return it;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
reference operator*() const
|
|
914
|
+
{
|
|
915
|
+
return cur;
|
|
916
|
+
}
|
|
917
|
+
pointer operator->() const
|
|
918
|
+
{
|
|
919
|
+
return &cur;
|
|
920
|
+
}
|
|
921
|
+
SlicedPAGNodeRef target() const
|
|
922
|
+
{
|
|
923
|
+
return Forward ? cur.dst : cur.src;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
SlicedPAGEdgeIterImpl& operator++()
|
|
927
|
+
{
|
|
928
|
+
if (realIt != realEnd)
|
|
929
|
+
{
|
|
930
|
+
++realIt;
|
|
931
|
+
skipNonKept();
|
|
932
|
+
}
|
|
933
|
+
refresh();
|
|
934
|
+
return *this;
|
|
935
|
+
}
|
|
936
|
+
SlicedPAGEdgeIterImpl operator++(int)
|
|
937
|
+
{
|
|
938
|
+
SlicedPAGEdgeIterImpl t = *this;
|
|
939
|
+
++*this;
|
|
940
|
+
return t;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
friend bool operator==(const SlicedPAGEdgeIterImpl& a, const SlicedPAGEdgeIterImpl& b)
|
|
944
|
+
{
|
|
945
|
+
return a.view == b.view && a.src == b.src && a.realIt == b.realIt;
|
|
946
|
+
}
|
|
947
|
+
friend bool operator!=(const SlicedPAGEdgeIterImpl& a, const SlicedPAGEdgeIterImpl& b)
|
|
948
|
+
{
|
|
949
|
+
return !(a == b);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
private:
|
|
953
|
+
using EdgeIt = SVFVar::const_iterator;
|
|
954
|
+
const SlicedPAGView* view = nullptr;
|
|
955
|
+
const SVFVar* src = nullptr;
|
|
956
|
+
EdgeIt realIt{}, realEnd{};
|
|
957
|
+
SlicedPAGEdgeRef cur{};
|
|
958
|
+
|
|
959
|
+
SlicedPAGEdgeIterImpl(const SlicedPAGView* v, const SVFVar* n) : view(v), src(n) {}
|
|
960
|
+
|
|
961
|
+
void skipNonKept()
|
|
962
|
+
{
|
|
963
|
+
while (realIt != realEnd && !view->isKeptStmt(*realIt)) ++realIt;
|
|
964
|
+
}
|
|
965
|
+
void refresh()
|
|
966
|
+
{
|
|
967
|
+
if (realIt != realEnd)
|
|
968
|
+
{
|
|
969
|
+
const SVFStmt* s = *realIt;
|
|
970
|
+
cur = SlicedPAGEdgeRef{{view, s->getSrcNode()}, {view, s->getDstNode()}, s};
|
|
971
|
+
}
|
|
972
|
+
else
|
|
973
|
+
{
|
|
974
|
+
cur = SlicedPAGEdgeRef{};
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
template <bool Forward>
|
|
980
|
+
class SlicedPAGChildIterImpl
|
|
981
|
+
{
|
|
982
|
+
public:
|
|
983
|
+
using iterator_category = std::forward_iterator_tag;
|
|
984
|
+
using value_type = SlicedPAGNodeRef;
|
|
985
|
+
using difference_type = std::ptrdiff_t;
|
|
986
|
+
using pointer = const SlicedPAGNodeRef*;
|
|
987
|
+
using reference = SlicedPAGNodeRef;
|
|
988
|
+
|
|
989
|
+
SlicedPAGChildIterImpl() = default;
|
|
990
|
+
explicit SlicedPAGChildIterImpl(SlicedPAGEdgeIterImpl<Forward> it) : e(it) {}
|
|
991
|
+
|
|
992
|
+
reference operator*() const
|
|
993
|
+
{
|
|
994
|
+
return e.target();
|
|
995
|
+
}
|
|
996
|
+
const SlicedPAGEdgeRef& currentEdge() const
|
|
997
|
+
{
|
|
998
|
+
return *e;
|
|
999
|
+
}
|
|
1000
|
+
SlicedPAGChildIterImpl& operator++()
|
|
1001
|
+
{
|
|
1002
|
+
++e;
|
|
1003
|
+
return *this;
|
|
1004
|
+
}
|
|
1005
|
+
SlicedPAGChildIterImpl operator++(int)
|
|
1006
|
+
{
|
|
1007
|
+
SlicedPAGChildIterImpl t = *this;
|
|
1008
|
+
++e;
|
|
1009
|
+
return t;
|
|
1010
|
+
}
|
|
1011
|
+
friend bool operator==(const SlicedPAGChildIterImpl& a, const SlicedPAGChildIterImpl& b)
|
|
1012
|
+
{
|
|
1013
|
+
return a.e == b.e;
|
|
1014
|
+
}
|
|
1015
|
+
friend bool operator!=(const SlicedPAGChildIterImpl& a, const SlicedPAGChildIterImpl& b)
|
|
1016
|
+
{
|
|
1017
|
+
return !(a == b);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
private:
|
|
1021
|
+
SlicedPAGEdgeIterImpl<Forward> e{};
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
// Node iterator over the kept SVFVar ids (resolved against the SVFIR).
|
|
1025
|
+
class SlicedPAGNodeIter
|
|
1026
|
+
{
|
|
1027
|
+
public:
|
|
1028
|
+
using iterator_category = std::forward_iterator_tag;
|
|
1029
|
+
using value_type = SlicedPAGNodeRef;
|
|
1030
|
+
using difference_type = std::ptrdiff_t;
|
|
1031
|
+
using pointer = const SlicedPAGNodeRef*;
|
|
1032
|
+
using reference = SlicedPAGNodeRef;
|
|
1033
|
+
|
|
1034
|
+
SlicedPAGNodeIter() = default;
|
|
1035
|
+
SlicedPAGNodeIter(const SlicedPAGView* v, Set<NodeID>::const_iterator i)
|
|
1036
|
+
: view(v), it(i) {}
|
|
1037
|
+
|
|
1038
|
+
reference operator*() const
|
|
1039
|
+
{
|
|
1040
|
+
return SlicedPAGNodeRef{view, view->getSVFIR()->getGNode(*it)};
|
|
1041
|
+
}
|
|
1042
|
+
SlicedPAGNodeIter& operator++()
|
|
1043
|
+
{
|
|
1044
|
+
++it;
|
|
1045
|
+
return *this;
|
|
1046
|
+
}
|
|
1047
|
+
SlicedPAGNodeIter operator++(int)
|
|
1048
|
+
{
|
|
1049
|
+
SlicedPAGNodeIter t = *this;
|
|
1050
|
+
++it;
|
|
1051
|
+
return t;
|
|
1052
|
+
}
|
|
1053
|
+
friend bool operator==(const SlicedPAGNodeIter& a, const SlicedPAGNodeIter& b)
|
|
1054
|
+
{
|
|
1055
|
+
return a.it == b.it;
|
|
1056
|
+
}
|
|
1057
|
+
friend bool operator!=(const SlicedPAGNodeIter& a, const SlicedPAGNodeIter& b)
|
|
1058
|
+
{
|
|
1059
|
+
return !(a == b);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
private:
|
|
1063
|
+
const SlicedPAGView* view = nullptr;
|
|
1064
|
+
Set<NodeID>::const_iterator it{};
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
//===----------------------------------------------------------------------===//
|
|
1068
|
+
// SlicedSVFGView traits support (no bridged edges; membership is the view's
|
|
1069
|
+
// retained-node rule, so removed nodes are propagation barriers).
|
|
1070
|
+
//===----------------------------------------------------------------------===//
|
|
1071
|
+
|
|
1072
|
+
using SlicedSVFGNodeRef = SlicedNodeRef<SlicedSVFGView, SVFGNode>;
|
|
1073
|
+
|
|
1074
|
+
struct SlicedSVFGEdgeRef
|
|
1075
|
+
{
|
|
1076
|
+
SlicedSVFGNodeRef src;
|
|
1077
|
+
SlicedSVFGNodeRef dst;
|
|
1078
|
+
const SVFGEdge* underlying = nullptr;
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
// Forward==true walks kept out-edges; Forward==false walks kept in-edges.
|
|
1082
|
+
template <bool Forward>
|
|
1083
|
+
class SlicedSVFGEdgeIterImpl
|
|
1084
|
+
{
|
|
1085
|
+
public:
|
|
1086
|
+
using iterator_category = std::forward_iterator_tag;
|
|
1087
|
+
using value_type = SlicedSVFGEdgeRef;
|
|
1088
|
+
using difference_type = std::ptrdiff_t;
|
|
1089
|
+
using pointer = const SlicedSVFGEdgeRef*;
|
|
1090
|
+
using reference = const SlicedSVFGEdgeRef&;
|
|
1091
|
+
|
|
1092
|
+
SlicedSVFGEdgeIterImpl() = default;
|
|
1093
|
+
|
|
1094
|
+
static SlicedSVFGEdgeIterImpl begin(const SlicedSVFGView* v, const SVFGNode* n)
|
|
1095
|
+
{
|
|
1096
|
+
SlicedSVFGEdgeIterImpl it(v, n);
|
|
1097
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
1098
|
+
it.realIt = edges.begin();
|
|
1099
|
+
it.realEnd = edges.end();
|
|
1100
|
+
it.skipNonKept();
|
|
1101
|
+
it.refresh();
|
|
1102
|
+
return it;
|
|
1103
|
+
}
|
|
1104
|
+
static SlicedSVFGEdgeIterImpl end(const SlicedSVFGView* v, const SVFGNode* n)
|
|
1105
|
+
{
|
|
1106
|
+
SlicedSVFGEdgeIterImpl it(v, n);
|
|
1107
|
+
const auto& edges = Forward ? n->getOutEdges() : n->getInEdges();
|
|
1108
|
+
it.realIt = edges.end();
|
|
1109
|
+
it.realEnd = edges.end();
|
|
1110
|
+
return it;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
reference operator*() const
|
|
1114
|
+
{
|
|
1115
|
+
return cur;
|
|
1116
|
+
}
|
|
1117
|
+
pointer operator->() const
|
|
1118
|
+
{
|
|
1119
|
+
return &cur;
|
|
1120
|
+
}
|
|
1121
|
+
SlicedSVFGNodeRef target() const
|
|
1122
|
+
{
|
|
1123
|
+
return Forward ? cur.dst : cur.src;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
SlicedSVFGEdgeIterImpl& operator++()
|
|
1127
|
+
{
|
|
1128
|
+
if (realIt != realEnd)
|
|
1129
|
+
{
|
|
1130
|
+
++realIt;
|
|
1131
|
+
skipNonKept();
|
|
1132
|
+
}
|
|
1133
|
+
refresh();
|
|
1134
|
+
return *this;
|
|
1135
|
+
}
|
|
1136
|
+
SlicedSVFGEdgeIterImpl operator++(int)
|
|
1137
|
+
{
|
|
1138
|
+
SlicedSVFGEdgeIterImpl t = *this;
|
|
1139
|
+
++*this;
|
|
1140
|
+
return t;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
friend bool operator==(const SlicedSVFGEdgeIterImpl& a, const SlicedSVFGEdgeIterImpl& b)
|
|
1144
|
+
{
|
|
1145
|
+
return a.view == b.view && a.src == b.src && a.realIt == b.realIt;
|
|
1146
|
+
}
|
|
1147
|
+
friend bool operator!=(const SlicedSVFGEdgeIterImpl& a, const SlicedSVFGEdgeIterImpl& b)
|
|
1148
|
+
{
|
|
1149
|
+
return !(a == b);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
private:
|
|
1153
|
+
using EdgeIt = SVFGNode::const_iterator;
|
|
1154
|
+
const SlicedSVFGView* view = nullptr;
|
|
1155
|
+
const SVFGNode* src = nullptr;
|
|
1156
|
+
EdgeIt realIt{}, realEnd{};
|
|
1157
|
+
SlicedSVFGEdgeRef cur{};
|
|
1158
|
+
|
|
1159
|
+
SlicedSVFGEdgeIterImpl(const SlicedSVFGView* v, const SVFGNode* n) : view(v), src(n) {}
|
|
1160
|
+
|
|
1161
|
+
void skipNonKept()
|
|
1162
|
+
{
|
|
1163
|
+
while (realIt != realEnd &&
|
|
1164
|
+
!view->isKeptNode(Forward ? (*realIt)->getDstNode() : (*realIt)->getSrcNode()))
|
|
1165
|
+
++realIt;
|
|
1166
|
+
}
|
|
1167
|
+
void refresh()
|
|
1168
|
+
{
|
|
1169
|
+
if (realIt != realEnd)
|
|
1170
|
+
{
|
|
1171
|
+
const SVFGEdge* e = *realIt;
|
|
1172
|
+
cur = SlicedSVFGEdgeRef{{view, e->getSrcNode()}, {view, e->getDstNode()}, e};
|
|
1173
|
+
}
|
|
1174
|
+
else
|
|
1175
|
+
{
|
|
1176
|
+
cur = SlicedSVFGEdgeRef{};
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
|
|
1181
|
+
template <bool Forward>
|
|
1182
|
+
class SlicedSVFGChildIterImpl
|
|
1183
|
+
{
|
|
1184
|
+
public:
|
|
1185
|
+
using iterator_category = std::forward_iterator_tag;
|
|
1186
|
+
using value_type = SlicedSVFGNodeRef;
|
|
1187
|
+
using difference_type = std::ptrdiff_t;
|
|
1188
|
+
using pointer = const SlicedSVFGNodeRef*;
|
|
1189
|
+
using reference = SlicedSVFGNodeRef;
|
|
1190
|
+
|
|
1191
|
+
SlicedSVFGChildIterImpl() = default;
|
|
1192
|
+
explicit SlicedSVFGChildIterImpl(SlicedSVFGEdgeIterImpl<Forward> it) : e(it) {}
|
|
1193
|
+
|
|
1194
|
+
reference operator*() const
|
|
1195
|
+
{
|
|
1196
|
+
return e.target();
|
|
1197
|
+
}
|
|
1198
|
+
const SlicedSVFGEdgeRef& currentEdge() const
|
|
1199
|
+
{
|
|
1200
|
+
return *e;
|
|
1201
|
+
}
|
|
1202
|
+
SlicedSVFGChildIterImpl& operator++()
|
|
1203
|
+
{
|
|
1204
|
+
++e;
|
|
1205
|
+
return *this;
|
|
1206
|
+
}
|
|
1207
|
+
SlicedSVFGChildIterImpl operator++(int)
|
|
1208
|
+
{
|
|
1209
|
+
SlicedSVFGChildIterImpl t = *this;
|
|
1210
|
+
++e;
|
|
1211
|
+
return t;
|
|
1212
|
+
}
|
|
1213
|
+
friend bool operator==(const SlicedSVFGChildIterImpl& a, const SlicedSVFGChildIterImpl& b)
|
|
1214
|
+
{
|
|
1215
|
+
return a.e == b.e;
|
|
1216
|
+
}
|
|
1217
|
+
friend bool operator!=(const SlicedSVFGChildIterImpl& a, const SlicedSVFGChildIterImpl& b)
|
|
1218
|
+
{
|
|
1219
|
+
return !(a == b);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
private:
|
|
1223
|
+
SlicedSVFGEdgeIterImpl<Forward> e{};
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
// Node iterator: filters the underlying SVFG's node map by the retained rule.
|
|
1227
|
+
class SlicedSVFGNodeIter
|
|
1228
|
+
{
|
|
1229
|
+
public:
|
|
1230
|
+
using iterator_category = std::forward_iterator_tag;
|
|
1231
|
+
using value_type = SlicedSVFGNodeRef;
|
|
1232
|
+
using difference_type = std::ptrdiff_t;
|
|
1233
|
+
using pointer = const SlicedSVFGNodeRef*;
|
|
1234
|
+
using reference = SlicedSVFGNodeRef;
|
|
1235
|
+
|
|
1236
|
+
SlicedSVFGNodeIter() = default;
|
|
1237
|
+
SlicedSVFGNodeIter(const SlicedSVFGView* v, SVFG::const_iterator i, SVFG::const_iterator e)
|
|
1238
|
+
: view(v), it(i), endIt(e)
|
|
1239
|
+
{
|
|
1240
|
+
skipNonKept();
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
reference operator*() const
|
|
1244
|
+
{
|
|
1245
|
+
return SlicedSVFGNodeRef{view, it->second};
|
|
1246
|
+
}
|
|
1247
|
+
SlicedSVFGNodeIter& operator++()
|
|
1248
|
+
{
|
|
1249
|
+
++it;
|
|
1250
|
+
skipNonKept();
|
|
1251
|
+
return *this;
|
|
1252
|
+
}
|
|
1253
|
+
SlicedSVFGNodeIter operator++(int)
|
|
1254
|
+
{
|
|
1255
|
+
SlicedSVFGNodeIter t = *this;
|
|
1256
|
+
++*this;
|
|
1257
|
+
return t;
|
|
1258
|
+
}
|
|
1259
|
+
friend bool operator==(const SlicedSVFGNodeIter& a, const SlicedSVFGNodeIter& b)
|
|
1260
|
+
{
|
|
1261
|
+
return a.it == b.it;
|
|
1262
|
+
}
|
|
1263
|
+
friend bool operator!=(const SlicedSVFGNodeIter& a, const SlicedSVFGNodeIter& b)
|
|
1264
|
+
{
|
|
1265
|
+
return !(a == b);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
private:
|
|
1269
|
+
const SlicedSVFGView* view = nullptr;
|
|
1270
|
+
SVFG::const_iterator it{}, endIt{};
|
|
1271
|
+
void skipNonKept()
|
|
1272
|
+
{
|
|
1273
|
+
while (it != endIt && !view->isKeptNode(it->second)) ++it;
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
|
|
1277
|
+
} // End namespace SVF
|
|
1278
|
+
|
|
1279
|
+
//===----------------------------------------------------------------------===//
|
|
1280
|
+
// Traits specializations must be at namespace SVF scope too (that is where the
|
|
1281
|
+
// GenericGraphTraits primary template and Inverse live).
|
|
1282
|
+
//===----------------------------------------------------------------------===//
|
|
1283
|
+
namespace SVF
|
|
1284
|
+
{
|
|
1285
|
+
|
|
1286
|
+
// Forward traits for SlicedICFGView.
|
|
1287
|
+
template <>
|
|
1288
|
+
struct GenericGraphTraits<const SlicedICFGView*>
|
|
1289
|
+
{
|
|
1290
|
+
using NodeRef = SlicedICFGNodeRef;
|
|
1291
|
+
using EdgeRef = SlicedICFGEdgeRef;
|
|
1292
|
+
using nodes_iterator = SlicedICFGNodeIter;
|
|
1293
|
+
using ChildIteratorType = SlicedICFGChildIterImpl<true>;
|
|
1294
|
+
using ChildEdgeIteratorType = SlicedICFGEdgeIterImpl<true>;
|
|
1295
|
+
|
|
1296
|
+
// Escape hatch to the underlying node so graph-generic algorithms can reach
|
|
1297
|
+
// domain data (getFun/getSVFStmts) uniformly. Full-ICFG traits return the node.
|
|
1298
|
+
static const ICFGNode* getRawNode(NodeRef n)
|
|
1299
|
+
{
|
|
1300
|
+
return n.raw;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// Graph-intrinsic queries mirroring GenericGraphTraits<ICFG*>, so a
|
|
1304
|
+
// graph-parameterised analysis resolves the right behaviour from the type.
|
|
1305
|
+
//@{
|
|
1306
|
+
static const ICFGNode* getFunEntry(const SlicedICFGView* g, const FunObjVar* fun)
|
|
1307
|
+
{
|
|
1308
|
+
return g->getFunEntry(fun);
|
|
1309
|
+
}
|
|
1310
|
+
static void getFunICFGNodes(const SlicedICFGView* g, const FunObjVar* fun,
|
|
1311
|
+
std::vector<const ICFGNode*>& out)
|
|
1312
|
+
{
|
|
1313
|
+
g->getFunICFGNodes(fun, out);
|
|
1314
|
+
}
|
|
1315
|
+
static void getSuccNodes(const SlicedICFGView* g, const ICFGNode* n,
|
|
1316
|
+
std::vector<const ICFGNode*>& out)
|
|
1317
|
+
{
|
|
1318
|
+
g->getSuccNodes(n, out);
|
|
1319
|
+
}
|
|
1320
|
+
static void getPredNodes(const SlicedICFGView* g, const ICFGNode* n,
|
|
1321
|
+
std::vector<const ICFGNode*>& out)
|
|
1322
|
+
{
|
|
1323
|
+
g->getPredNodes(n, out);
|
|
1324
|
+
}
|
|
1325
|
+
static bool containsNode(const SlicedICFGView* g, const ICFGNode* n)
|
|
1326
|
+
{
|
|
1327
|
+
return g->isKeptNode(n);
|
|
1328
|
+
}
|
|
1329
|
+
//@}
|
|
1330
|
+
|
|
1331
|
+
static NodeRef getEntryNode(const SlicedICFGView*)
|
|
1332
|
+
{
|
|
1333
|
+
return NodeRef{};
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
static nodes_iterator nodes_begin(const SlicedICFGView* v)
|
|
1337
|
+
{
|
|
1338
|
+
return SlicedICFGNodeIter(v, v->getKeptNodes().begin());
|
|
1339
|
+
}
|
|
1340
|
+
static nodes_iterator nodes_end(const SlicedICFGView* v)
|
|
1341
|
+
{
|
|
1342
|
+
return SlicedICFGNodeIter(v, v->getKeptNodes().end());
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1346
|
+
{
|
|
1347
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1348
|
+
}
|
|
1349
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1350
|
+
{
|
|
1351
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1352
|
+
}
|
|
1353
|
+
static ChildIteratorType direct_child_begin(NodeRef n)
|
|
1354
|
+
{
|
|
1355
|
+
return child_begin(n);
|
|
1356
|
+
}
|
|
1357
|
+
static ChildIteratorType direct_child_end(NodeRef n)
|
|
1358
|
+
{
|
|
1359
|
+
return child_end(n);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1363
|
+
{
|
|
1364
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1365
|
+
}
|
|
1366
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1367
|
+
{
|
|
1368
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1372
|
+
{
|
|
1373
|
+
return e.dst;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
static unsigned graphSize(const SlicedICFGView* v)
|
|
1377
|
+
{
|
|
1378
|
+
return static_cast<unsigned>(v->getKeptNodes().size());
|
|
1379
|
+
}
|
|
1380
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1381
|
+
{
|
|
1382
|
+
return n.raw->getId();
|
|
1383
|
+
}
|
|
1384
|
+
static NodeRef getNode(const SlicedICFGView* v, NodeID id)
|
|
1385
|
+
{
|
|
1386
|
+
const ICFGNode* raw = v->getOriginalICFG()->getGNode(id);
|
|
1387
|
+
return NodeRef{v, (raw != nullptr && v->isKeptNode(raw)) ? raw : nullptr};
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
|
|
1391
|
+
// Inverse (reverse-traversal) traits for SlicedICFGView.
|
|
1392
|
+
template <>
|
|
1393
|
+
struct GenericGraphTraits<Inverse<const SlicedICFGView*>>
|
|
1394
|
+
{
|
|
1395
|
+
using NodeRef = SlicedICFGNodeRef;
|
|
1396
|
+
using EdgeRef = SlicedICFGEdgeRef;
|
|
1397
|
+
using ChildIteratorType = SlicedICFGChildIterImpl<false>;
|
|
1398
|
+
using ChildEdgeIteratorType = SlicedICFGEdgeIterImpl<false>;
|
|
1399
|
+
|
|
1400
|
+
static NodeRef getEntryNode(Inverse<const SlicedICFGView*>)
|
|
1401
|
+
{
|
|
1402
|
+
return NodeRef{};
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1406
|
+
{
|
|
1407
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1408
|
+
}
|
|
1409
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1410
|
+
{
|
|
1411
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1415
|
+
{
|
|
1416
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1417
|
+
}
|
|
1418
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1419
|
+
{
|
|
1420
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
// Inverse: the traversed "child" is the predecessor -> the edge source.
|
|
1424
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1425
|
+
{
|
|
1426
|
+
return e.src;
|
|
1427
|
+
}
|
|
1428
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1429
|
+
{
|
|
1430
|
+
return n.raw->getId();
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
// Forward traits for SlicedThreadCallGraphView.
|
|
1435
|
+
template <>
|
|
1436
|
+
struct GenericGraphTraits<const SlicedThreadCallGraphView*>
|
|
1437
|
+
{
|
|
1438
|
+
using NodeRef = SlicedCallGraphNodeRef;
|
|
1439
|
+
using EdgeRef = SlicedCallGraphEdgeRef;
|
|
1440
|
+
using nodes_iterator = SlicedCGNodeIter;
|
|
1441
|
+
using ChildIteratorType = SlicedCGChildIterImpl<true>;
|
|
1442
|
+
using ChildEdgeIteratorType = SlicedCGEdgeIterImpl<true>;
|
|
1443
|
+
|
|
1444
|
+
static const CallGraphNode* getRawNode(NodeRef n)
|
|
1445
|
+
{
|
|
1446
|
+
return n.raw;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// Graph-intrinsic queries mirroring GenericGraphTraits<CallGraph*>.
|
|
1450
|
+
//@{
|
|
1451
|
+
static void getInEdges(const SlicedThreadCallGraphView* g, const CallGraphNode* n,
|
|
1452
|
+
std::vector<const CallGraphEdge*>& out)
|
|
1453
|
+
{
|
|
1454
|
+
g->getInEdgesOf(n, out);
|
|
1455
|
+
}
|
|
1456
|
+
static const CallGraph* getCallGraph(const SlicedThreadCallGraphView* g)
|
|
1457
|
+
{
|
|
1458
|
+
return g->getOriginalCallGraph();
|
|
1459
|
+
}
|
|
1460
|
+
//@}
|
|
1461
|
+
|
|
1462
|
+
static NodeRef getEntryNode(const SlicedThreadCallGraphView*)
|
|
1463
|
+
{
|
|
1464
|
+
return NodeRef{};
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
static nodes_iterator nodes_begin(const SlicedThreadCallGraphView* v)
|
|
1468
|
+
{
|
|
1469
|
+
return SlicedCGNodeIter(v, v->getKeptNodes().begin());
|
|
1470
|
+
}
|
|
1471
|
+
static nodes_iterator nodes_end(const SlicedThreadCallGraphView* v)
|
|
1472
|
+
{
|
|
1473
|
+
return SlicedCGNodeIter(v, v->getKeptNodes().end());
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1477
|
+
{
|
|
1478
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1479
|
+
}
|
|
1480
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1481
|
+
{
|
|
1482
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1483
|
+
}
|
|
1484
|
+
static ChildIteratorType direct_child_begin(NodeRef n)
|
|
1485
|
+
{
|
|
1486
|
+
return child_begin(n);
|
|
1487
|
+
}
|
|
1488
|
+
static ChildIteratorType direct_child_end(NodeRef n)
|
|
1489
|
+
{
|
|
1490
|
+
return child_end(n);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1494
|
+
{
|
|
1495
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1496
|
+
}
|
|
1497
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1498
|
+
{
|
|
1499
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1503
|
+
{
|
|
1504
|
+
return e.dst;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
static unsigned graphSize(const SlicedThreadCallGraphView* v)
|
|
1508
|
+
{
|
|
1509
|
+
return static_cast<unsigned>(v->getKeptNodes().size());
|
|
1510
|
+
}
|
|
1511
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1512
|
+
{
|
|
1513
|
+
return n.raw->getId();
|
|
1514
|
+
}
|
|
1515
|
+
static NodeRef getNode(const SlicedThreadCallGraphView* v, NodeID id)
|
|
1516
|
+
{
|
|
1517
|
+
const CallGraphNode* raw = v->getOriginalCallGraph()->getGNode(id);
|
|
1518
|
+
return NodeRef{v, (raw != nullptr && v->isKeptNode(raw)) ? raw : nullptr};
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
// Inverse traits for SlicedThreadCallGraphView.
|
|
1523
|
+
template <>
|
|
1524
|
+
struct GenericGraphTraits<Inverse<const SlicedThreadCallGraphView*>>
|
|
1525
|
+
{
|
|
1526
|
+
using NodeRef = SlicedCallGraphNodeRef;
|
|
1527
|
+
using EdgeRef = SlicedCallGraphEdgeRef;
|
|
1528
|
+
using ChildIteratorType = SlicedCGChildIterImpl<false>;
|
|
1529
|
+
using ChildEdgeIteratorType = SlicedCGEdgeIterImpl<false>;
|
|
1530
|
+
|
|
1531
|
+
static NodeRef getEntryNode(Inverse<const SlicedThreadCallGraphView*>)
|
|
1532
|
+
{
|
|
1533
|
+
return NodeRef{};
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1537
|
+
{
|
|
1538
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1539
|
+
}
|
|
1540
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1541
|
+
{
|
|
1542
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1543
|
+
}
|
|
1544
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1545
|
+
{
|
|
1546
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1547
|
+
}
|
|
1548
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1549
|
+
{
|
|
1550
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1554
|
+
{
|
|
1555
|
+
return e.src;
|
|
1556
|
+
}
|
|
1557
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1558
|
+
{
|
|
1559
|
+
return n.raw->getId();
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
|
|
1563
|
+
// Forward traits for SlicedPAGView.
|
|
1564
|
+
template <>
|
|
1565
|
+
struct GenericGraphTraits<const SlicedPAGView*>
|
|
1566
|
+
{
|
|
1567
|
+
using NodeRef = SlicedPAGNodeRef;
|
|
1568
|
+
using EdgeRef = SlicedPAGEdgeRef;
|
|
1569
|
+
using nodes_iterator = SlicedPAGNodeIter;
|
|
1570
|
+
using ChildIteratorType = SlicedPAGChildIterImpl<true>;
|
|
1571
|
+
using ChildEdgeIteratorType = SlicedPAGEdgeIterImpl<true>;
|
|
1572
|
+
|
|
1573
|
+
static const SVFVar* getRawNode(NodeRef n)
|
|
1574
|
+
{
|
|
1575
|
+
return n.raw;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
static NodeRef getEntryNode(const SlicedPAGView*)
|
|
1579
|
+
{
|
|
1580
|
+
return NodeRef{};
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
static nodes_iterator nodes_begin(const SlicedPAGView* v)
|
|
1584
|
+
{
|
|
1585
|
+
return SlicedPAGNodeIter(v, v->getKeptNodeIds().begin());
|
|
1586
|
+
}
|
|
1587
|
+
static nodes_iterator nodes_end(const SlicedPAGView* v)
|
|
1588
|
+
{
|
|
1589
|
+
return SlicedPAGNodeIter(v, v->getKeptNodeIds().end());
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1593
|
+
{
|
|
1594
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1595
|
+
}
|
|
1596
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1597
|
+
{
|
|
1598
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1599
|
+
}
|
|
1600
|
+
static ChildIteratorType direct_child_begin(NodeRef n)
|
|
1601
|
+
{
|
|
1602
|
+
return child_begin(n);
|
|
1603
|
+
}
|
|
1604
|
+
static ChildIteratorType direct_child_end(NodeRef n)
|
|
1605
|
+
{
|
|
1606
|
+
return child_end(n);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1610
|
+
{
|
|
1611
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1612
|
+
}
|
|
1613
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1614
|
+
{
|
|
1615
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1619
|
+
{
|
|
1620
|
+
return e.dst;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
static unsigned graphSize(const SlicedPAGView* v)
|
|
1624
|
+
{
|
|
1625
|
+
return static_cast<unsigned>(v->getKeptNodeIds().size());
|
|
1626
|
+
}
|
|
1627
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1628
|
+
{
|
|
1629
|
+
return n.raw->getId();
|
|
1630
|
+
}
|
|
1631
|
+
static NodeRef getNode(const SlicedPAGView* v, NodeID id)
|
|
1632
|
+
{
|
|
1633
|
+
const bool kept = v->getKeptNodeIds().count(id) > 0;
|
|
1634
|
+
return NodeRef{v, kept ? v->getSVFIR()->getGNode(id) : nullptr};
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
|
|
1638
|
+
// Inverse traits for SlicedPAGView.
|
|
1639
|
+
template <>
|
|
1640
|
+
struct GenericGraphTraits<Inverse<const SlicedPAGView*>>
|
|
1641
|
+
{
|
|
1642
|
+
using NodeRef = SlicedPAGNodeRef;
|
|
1643
|
+
using EdgeRef = SlicedPAGEdgeRef;
|
|
1644
|
+
using ChildIteratorType = SlicedPAGChildIterImpl<false>;
|
|
1645
|
+
using ChildEdgeIteratorType = SlicedPAGEdgeIterImpl<false>;
|
|
1646
|
+
|
|
1647
|
+
static NodeRef getEntryNode(Inverse<const SlicedPAGView*>)
|
|
1648
|
+
{
|
|
1649
|
+
return NodeRef{};
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1653
|
+
{
|
|
1654
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1655
|
+
}
|
|
1656
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1657
|
+
{
|
|
1658
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1659
|
+
}
|
|
1660
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1661
|
+
{
|
|
1662
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1663
|
+
}
|
|
1664
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1665
|
+
{
|
|
1666
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1670
|
+
{
|
|
1671
|
+
return e.src;
|
|
1672
|
+
}
|
|
1673
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1674
|
+
{
|
|
1675
|
+
return n.raw->getId();
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
// Forward traits for SlicedSVFGView.
|
|
1680
|
+
template <>
|
|
1681
|
+
struct GenericGraphTraits<const SlicedSVFGView*>
|
|
1682
|
+
{
|
|
1683
|
+
using NodeRef = SlicedSVFGNodeRef;
|
|
1684
|
+
using EdgeRef = SlicedSVFGEdgeRef;
|
|
1685
|
+
using nodes_iterator = SlicedSVFGNodeIter;
|
|
1686
|
+
using ChildIteratorType = SlicedSVFGChildIterImpl<true>;
|
|
1687
|
+
using ChildEdgeIteratorType = SlicedSVFGEdgeIterImpl<true>;
|
|
1688
|
+
|
|
1689
|
+
static const SVFGNode* getRawNode(NodeRef n)
|
|
1690
|
+
{
|
|
1691
|
+
return n.raw;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
/// Whether n is retained by this sliced SVFG (the solver's restriction test).
|
|
1695
|
+
static bool containsNode(const SlicedSVFGView* g, const SVFGNode* n)
|
|
1696
|
+
{
|
|
1697
|
+
return g->isKeptNode(n);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
static NodeRef getEntryNode(const SlicedSVFGView*)
|
|
1701
|
+
{
|
|
1702
|
+
return NodeRef{};
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
static nodes_iterator nodes_begin(const SlicedSVFGView* v)
|
|
1706
|
+
{
|
|
1707
|
+
assert(v->getSVFG() && "SlicedSVFGView: bind the SVFG before iterating nodes");
|
|
1708
|
+
return SlicedSVFGNodeIter(v, v->getSVFG()->begin(), v->getSVFG()->end());
|
|
1709
|
+
}
|
|
1710
|
+
static nodes_iterator nodes_end(const SlicedSVFGView* v)
|
|
1711
|
+
{
|
|
1712
|
+
assert(v->getSVFG() && "SlicedSVFGView: bind the SVFG before iterating nodes");
|
|
1713
|
+
return SlicedSVFGNodeIter(v, v->getSVFG()->end(), v->getSVFG()->end());
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1717
|
+
{
|
|
1718
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1719
|
+
}
|
|
1720
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1721
|
+
{
|
|
1722
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1723
|
+
}
|
|
1724
|
+
static ChildIteratorType direct_child_begin(NodeRef n)
|
|
1725
|
+
{
|
|
1726
|
+
return child_begin(n);
|
|
1727
|
+
}
|
|
1728
|
+
static ChildIteratorType direct_child_end(NodeRef n)
|
|
1729
|
+
{
|
|
1730
|
+
return child_end(n);
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1734
|
+
{
|
|
1735
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1736
|
+
}
|
|
1737
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1738
|
+
{
|
|
1739
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1743
|
+
{
|
|
1744
|
+
return e.dst;
|
|
1745
|
+
}
|
|
1746
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1747
|
+
{
|
|
1748
|
+
return n.raw->getId();
|
|
1749
|
+
}
|
|
1750
|
+
static NodeRef getNode(const SlicedSVFGView* v, NodeID id)
|
|
1751
|
+
{
|
|
1752
|
+
const SVFGNode* raw =
|
|
1753
|
+
(v->getSVFG() != nullptr) ? v->getSVFG()->getGNode(id) : nullptr;
|
|
1754
|
+
return NodeRef{v, (raw != nullptr && v->isKeptNode(raw)) ? raw : nullptr};
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
// Inverse traits for SlicedSVFGView.
|
|
1759
|
+
template <>
|
|
1760
|
+
struct GenericGraphTraits<Inverse<const SlicedSVFGView*>>
|
|
1761
|
+
{
|
|
1762
|
+
using NodeRef = SlicedSVFGNodeRef;
|
|
1763
|
+
using EdgeRef = SlicedSVFGEdgeRef;
|
|
1764
|
+
using ChildIteratorType = SlicedSVFGChildIterImpl<false>;
|
|
1765
|
+
using ChildEdgeIteratorType = SlicedSVFGEdgeIterImpl<false>;
|
|
1766
|
+
|
|
1767
|
+
static NodeRef getEntryNode(Inverse<const SlicedSVFGView*>)
|
|
1768
|
+
{
|
|
1769
|
+
return NodeRef{};
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
static ChildIteratorType child_begin(NodeRef n)
|
|
1773
|
+
{
|
|
1774
|
+
return ChildIteratorType(ChildEdgeIteratorType::begin(n.view, n.raw));
|
|
1775
|
+
}
|
|
1776
|
+
static ChildIteratorType child_end(NodeRef n)
|
|
1777
|
+
{
|
|
1778
|
+
return ChildIteratorType(ChildEdgeIteratorType::end(n.view, n.raw));
|
|
1779
|
+
}
|
|
1780
|
+
static ChildEdgeIteratorType child_edge_begin(NodeRef n)
|
|
1781
|
+
{
|
|
1782
|
+
return ChildEdgeIteratorType::begin(n.view, n.raw);
|
|
1783
|
+
}
|
|
1784
|
+
static ChildEdgeIteratorType child_edge_end(NodeRef n)
|
|
1785
|
+
{
|
|
1786
|
+
return ChildEdgeIteratorType::end(n.view, n.raw);
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
static NodeRef edge_dest(const EdgeRef& e)
|
|
1790
|
+
{
|
|
1791
|
+
return e.src;
|
|
1792
|
+
}
|
|
1793
|
+
static inline unsigned getNodeID(NodeRef n)
|
|
1794
|
+
{
|
|
1795
|
+
return n.raw->getId();
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
|
|
1799
|
+
} // End namespace SVF
|
|
1800
|
+
|
|
1801
|
+
#endif // GRAPHS_SLICEDGRAPHS_H
|