svf-lib 1.0.2676 → 1.0.2677

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.
Files changed (28) hide show
  1. package/SVF-linux-aarch64/bin/mta +0 -0
  2. package/SVF-linux-aarch64/bin/svf-ex +0 -0
  3. package/SVF-linux-aarch64/include/Graphs/CallGraph.h +18 -0
  4. package/SVF-linux-aarch64/include/Graphs/DOTGraphTraits.h +33 -20
  5. package/SVF-linux-aarch64/include/Graphs/GraphPrinter.h +1 -1
  6. package/SVF-linux-aarch64/include/Graphs/GraphWriter.h +6 -7
  7. package/SVF-linux-aarch64/include/Graphs/ICFG.h +40 -0
  8. package/SVF-linux-aarch64/include/Graphs/SVFG.h +8 -0
  9. package/SVF-linux-aarch64/include/Graphs/SlicedGraphs.h +1801 -0
  10. package/SVF-linux-aarch64/include/Graphs/ThreadCallGraph.h +13 -4
  11. package/SVF-linux-aarch64/include/MSSA/MemRegion.h +17 -0
  12. package/SVF-linux-aarch64/include/MSSA/MemSSA.h +7 -5
  13. package/SVF-linux-aarch64/include/MSSA/SVFGBuilder.h +6 -0
  14. package/SVF-linux-aarch64/include/MTA/FSMPTA.h +91 -0
  15. package/SVF-linux-aarch64/include/MTA/LockAnalysis.h +40 -25
  16. package/SVF-linux-aarch64/include/MTA/MHP.h +54 -21
  17. package/SVF-linux-aarch64/include/MTA/MTA.h +186 -3
  18. package/SVF-linux-aarch64/include/MTA/MTASVFGBuilder.h +176 -0
  19. package/SVF-linux-aarch64/include/MTA/MTASlicer.h +275 -0
  20. package/SVF-linux-aarch64/include/MTA/MTAStat.h +0 -2
  21. package/SVF-linux-aarch64/include/MTA/TCT.h +70 -29
  22. package/SVF-linux-aarch64/include/Util/CommandLine.h +5 -0
  23. package/SVF-linux-aarch64/include/Util/CxtStmt.h +29 -19
  24. package/SVF-linux-aarch64/include/Util/Options.h +12 -6
  25. package/SVF-linux-aarch64/include/Util/ThreadAPI.h +12 -0
  26. package/SVF-linux-aarch64/lib/cmake/SVF/SVFTargets.cmake +1 -1
  27. package/SVF-linux-aarch64/lib/libSvfCore.so.3.4 +0 -0
  28. 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