svf-tools 1.0.642 → 1.0.644
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/package.json +1 -1
- package/svf/include/CFL/CFLAlias.h +0 -24
- package/svf/include/CFL/CFLSolver.h +318 -15
- package/svf/lib/CFL/CFLAlias.cpp +2 -21
- package/svf/lib/CFL/CFLSolver.cpp +88 -0
- package/svf-llvm/lib/LLVMModule.cpp +9 -3
- package/svf/include/CFL/CFLData.h +0 -316
- package/svf/include/CFL/CFLDataBuilder.h +0 -91
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.644",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -32,8 +32,6 @@
|
|
|
32
32
|
|
|
33
33
|
#include "CFL/CFLBase.h"
|
|
34
34
|
#include "CFL/CFLStat.h"
|
|
35
|
-
#include "CFL/CFLData.h"
|
|
36
|
-
#include "CFL/CFLDataBuilder.h"
|
|
37
35
|
|
|
38
36
|
namespace SVF
|
|
39
37
|
{
|
|
@@ -142,34 +140,12 @@ private:
|
|
|
142
140
|
class POCRAlias : public CFLAlias
|
|
143
141
|
{
|
|
144
142
|
public:
|
|
145
|
-
static double timeOfBuildCFLData; // Time of building CFLData from CFLGraph
|
|
146
|
-
|
|
147
143
|
POCRAlias(SVFIR* ir) : CFLAlias(ir)
|
|
148
144
|
{
|
|
149
|
-
if (!_cflData)
|
|
150
|
-
_cflData = new CFLData();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/// Destructor
|
|
154
|
-
virtual ~POCRAlias()
|
|
155
|
-
{
|
|
156
|
-
delete _cflData;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
CFLData* cflData()
|
|
160
|
-
{
|
|
161
|
-
return _cflData;
|
|
162
145
|
}
|
|
163
146
|
|
|
164
147
|
/// Initialize the grammar, graph, CFLData, solver
|
|
165
148
|
virtual void initialize();
|
|
166
|
-
|
|
167
|
-
/// Init CFLData
|
|
168
|
-
virtual void buildCFLData();
|
|
169
|
-
|
|
170
|
-
private:
|
|
171
|
-
/// Graph dataset
|
|
172
|
-
CFLData* _cflData;
|
|
173
149
|
};
|
|
174
150
|
} // End namespace SVF
|
|
175
151
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* CFLSolver.h
|
|
25
25
|
*
|
|
26
26
|
* Created on: March 5, 2022
|
|
27
|
-
* Author: Yulei Sui
|
|
27
|
+
* Author: Yulei Sui, Yuxiang Lei
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
30
|
#ifndef INCLUDE_CFL_CFLSolver_H_
|
|
@@ -33,12 +33,285 @@
|
|
|
33
33
|
#include "Graphs/CFLGraph.h"
|
|
34
34
|
#include "CFL/CFLGrammar.h"
|
|
35
35
|
#include "Util/WorkList.h"
|
|
36
|
-
#include "CFL/CFLData.h"
|
|
37
36
|
|
|
37
|
+
using namespace std;
|
|
38
38
|
|
|
39
39
|
namespace SVF
|
|
40
40
|
{
|
|
41
41
|
|
|
42
|
+
typedef GrammarBase::Symbol Label;
|
|
43
|
+
/*!
|
|
44
|
+
* Adjacency-list graph representation
|
|
45
|
+
*/
|
|
46
|
+
class CFLData
|
|
47
|
+
{
|
|
48
|
+
public:
|
|
49
|
+
typedef std::map<const Label, NodeBS> TypeMap; // Label with SparseBitVector of NodeID
|
|
50
|
+
typedef std::unordered_map<NodeID, TypeMap> DataMap; // Each Node has a TypeMap
|
|
51
|
+
typedef typename DataMap::iterator iterator; // iterator for each node
|
|
52
|
+
typedef typename DataMap::const_iterator const_iterator; // const iterator
|
|
53
|
+
|
|
54
|
+
protected:
|
|
55
|
+
DataMap succMap; // succ map for nodes contains Label: Edgeset
|
|
56
|
+
DataMap predMap; // pred map for nodes contains Label: edgeset
|
|
57
|
+
const NodeBS emptyData; // ??
|
|
58
|
+
NodeBS diff; // ??
|
|
59
|
+
|
|
60
|
+
// union/add data
|
|
61
|
+
//@{
|
|
62
|
+
inline bool addPred(const NodeID key, const NodeID src, const Label ty)
|
|
63
|
+
{
|
|
64
|
+
return predMap[key][ty].test_and_set(src);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
inline bool addSucc(const NodeID key, const NodeID dst, const Label ty)
|
|
68
|
+
{
|
|
69
|
+
return succMap[key][ty].test_and_set(dst);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
inline bool addPreds(const NodeID key, const NodeBS& data, const Label ty)
|
|
73
|
+
{
|
|
74
|
+
if (data.empty())
|
|
75
|
+
return false;
|
|
76
|
+
return predMap[key][ty] |= data; // union of sparsebitvector (add to LHS)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
inline bool addSuccs(const NodeID key, const NodeBS& data, const Label ty)
|
|
80
|
+
{
|
|
81
|
+
if (data.empty())
|
|
82
|
+
return false;
|
|
83
|
+
return succMap[key][ty] |= data; // // union of sparsebitvector (add to LHS)
|
|
84
|
+
}
|
|
85
|
+
//@}
|
|
86
|
+
|
|
87
|
+
public:
|
|
88
|
+
// Constructor
|
|
89
|
+
CFLData()
|
|
90
|
+
{}
|
|
91
|
+
|
|
92
|
+
// Destructor
|
|
93
|
+
virtual ~CFLData()
|
|
94
|
+
{}
|
|
95
|
+
|
|
96
|
+
virtual void clear()
|
|
97
|
+
{
|
|
98
|
+
succMap.clear();
|
|
99
|
+
predMap.clear();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
inline const_iterator begin() const
|
|
103
|
+
{
|
|
104
|
+
return succMap.begin();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
inline const_iterator end() const
|
|
108
|
+
{
|
|
109
|
+
return succMap.end();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
inline iterator begin()
|
|
113
|
+
{
|
|
114
|
+
return succMap.begin();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
inline iterator end()
|
|
118
|
+
{
|
|
119
|
+
return succMap.end();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
inline DataMap& getSuccMap()
|
|
123
|
+
{
|
|
124
|
+
return succMap;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
inline DataMap& getPredMap()
|
|
128
|
+
{
|
|
129
|
+
return predMap;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
inline TypeMap& getSuccMap(const NodeID key)
|
|
133
|
+
{
|
|
134
|
+
return succMap[key];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
inline TypeMap& getPredMap(const NodeID key)
|
|
138
|
+
{
|
|
139
|
+
return predMap[key];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
inline NodeBS& getSuccs(const NodeID key, const Label ty)
|
|
143
|
+
{
|
|
144
|
+
return succMap[key][ty];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
inline NodeBS& getPreds(const NodeID key, const Label ty)
|
|
148
|
+
{
|
|
149
|
+
return predMap[key][ty];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Alias data operations
|
|
153
|
+
//@{
|
|
154
|
+
inline bool addEdge(const NodeID src, const NodeID dst, const Label ty)
|
|
155
|
+
{
|
|
156
|
+
addSucc(src, dst, ty);
|
|
157
|
+
return addPred(dst, src, ty);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// add edges and return the set of added edges (dst) for src
|
|
161
|
+
inline NodeBS addEdges(const NodeID src, const NodeBS& dstData, const Label ty)
|
|
162
|
+
{
|
|
163
|
+
NodeBS newDsts;
|
|
164
|
+
if (addSuccs(src, dstData, ty))
|
|
165
|
+
{
|
|
166
|
+
for (const NodeID datum: dstData)
|
|
167
|
+
if (addPred(datum, src, ty))
|
|
168
|
+
newDsts.set(datum);
|
|
169
|
+
}
|
|
170
|
+
return newDsts;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// add edges and return the set of added edges (src) for dst
|
|
174
|
+
inline NodeBS addEdges(const NodeBS& srcData, const NodeID dst, const Label ty)
|
|
175
|
+
{
|
|
176
|
+
NodeBS newSrcs;
|
|
177
|
+
if (addPreds(dst, srcData, ty))
|
|
178
|
+
{
|
|
179
|
+
for (const NodeID datum: srcData)
|
|
180
|
+
if (addSucc(datum, dst, ty))
|
|
181
|
+
newSrcs.set(datum);
|
|
182
|
+
}
|
|
183
|
+
return newSrcs;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/// find src -> find src[ty] -> find dst in set
|
|
187
|
+
inline bool hasEdge(const NodeID src, const NodeID dst, const Label ty)
|
|
188
|
+
{
|
|
189
|
+
const_iterator iter1 = succMap.find(src);
|
|
190
|
+
if (iter1 == succMap.end())
|
|
191
|
+
return false;
|
|
192
|
+
|
|
193
|
+
auto iter2 = iter1->second.find(ty);
|
|
194
|
+
if (iter2 == iter1->second.end())
|
|
195
|
+
return false;
|
|
196
|
+
|
|
197
|
+
return iter2->second.test(dst);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* This is a dataset version, to be modified to a cflData version */
|
|
201
|
+
inline void clearEdges(const NodeID key)
|
|
202
|
+
{
|
|
203
|
+
succMap[key].clear();
|
|
204
|
+
predMap[key].clear();
|
|
205
|
+
}
|
|
206
|
+
//@}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/*!
|
|
210
|
+
* Hybrid graph representation for transitive relations
|
|
211
|
+
* The implementation is based on
|
|
212
|
+
* Yuxiang Lei, Yulei Sui, Shuo Ding, and Qirun Zhang.
|
|
213
|
+
* Taming Transitive Redundancy for Context-Free Language Reachability.
|
|
214
|
+
* ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications
|
|
215
|
+
*/
|
|
216
|
+
class HybridData
|
|
217
|
+
{
|
|
218
|
+
public:
|
|
219
|
+
struct TreeNode
|
|
220
|
+
{
|
|
221
|
+
NodeID id;
|
|
222
|
+
std::unordered_set<TreeNode*> children;
|
|
223
|
+
|
|
224
|
+
TreeNode(NodeID nId) : id(nId)
|
|
225
|
+
{}
|
|
226
|
+
|
|
227
|
+
~TreeNode()
|
|
228
|
+
{
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
inline bool operator==(const TreeNode& rhs) const
|
|
232
|
+
{
|
|
233
|
+
return id == rhs.id;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
inline bool operator<(const TreeNode& rhs) const
|
|
237
|
+
{
|
|
238
|
+
return id < rhs.id;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
public:
|
|
244
|
+
Map<NodeID, std::unordered_map<NodeID, TreeNode*>> indMap; // indMap[v][u] points to node v in tree(u)
|
|
245
|
+
|
|
246
|
+
HybridData()
|
|
247
|
+
{}
|
|
248
|
+
|
|
249
|
+
~HybridData()
|
|
250
|
+
{
|
|
251
|
+
for (auto iter1: indMap)
|
|
252
|
+
{
|
|
253
|
+
for (auto iter2: iter1.second)
|
|
254
|
+
{
|
|
255
|
+
delete iter2.second;
|
|
256
|
+
iter2.second = NULL;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
bool hasInd(NodeID src, NodeID dst)
|
|
262
|
+
{
|
|
263
|
+
auto it = indMap.find(dst);
|
|
264
|
+
if (it == indMap.end())
|
|
265
|
+
return false;
|
|
266
|
+
return (it->second.find(src) != it->second.end());
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/// Add a node dst to tree(src)
|
|
270
|
+
TreeNode* addInd(NodeID src, NodeID dst)
|
|
271
|
+
{
|
|
272
|
+
auto resIns = indMap[dst].insert(std::make_pair(src, new TreeNode(dst)));
|
|
273
|
+
if (resIns.second)
|
|
274
|
+
return resIns.first->second;
|
|
275
|
+
return nullptr;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// Get the node dst in tree(src)
|
|
279
|
+
TreeNode* getNode(NodeID src, NodeID dst)
|
|
280
|
+
{
|
|
281
|
+
return indMap[dst][src];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/// add v into desc(x) as a child of u
|
|
285
|
+
void insertEdge(TreeNode* u, TreeNode* v)
|
|
286
|
+
{
|
|
287
|
+
u->children.insert(v);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
void addArc(NodeID src, NodeID dst)
|
|
291
|
+
{
|
|
292
|
+
if (!hasInd(src, dst))
|
|
293
|
+
{
|
|
294
|
+
for (auto iter: indMap[src])
|
|
295
|
+
{
|
|
296
|
+
meld(iter.first, getNode(iter.first, src), getNode(dst, dst));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
void meld(NodeID x, TreeNode* uNode, TreeNode* vNode)
|
|
302
|
+
{
|
|
303
|
+
TreeNode* newVNode = addInd(x, vNode->id);
|
|
304
|
+
if (!newVNode)
|
|
305
|
+
return;
|
|
306
|
+
|
|
307
|
+
insertEdge(uNode, newVNode);
|
|
308
|
+
for (TreeNode* vChild: vNode->children)
|
|
309
|
+
{
|
|
310
|
+
meld(x, newVNode, vChild);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
42
315
|
class CFLSolver
|
|
43
316
|
{
|
|
44
317
|
|
|
@@ -54,20 +327,20 @@ public:
|
|
|
54
327
|
{
|
|
55
328
|
}
|
|
56
329
|
|
|
57
|
-
~CFLSolver()
|
|
330
|
+
virtual ~CFLSolver()
|
|
58
331
|
{
|
|
59
332
|
delete graph;
|
|
60
333
|
delete grammar;
|
|
61
334
|
}
|
|
62
335
|
|
|
63
336
|
/// Initialize worklist
|
|
64
|
-
void initialize();
|
|
337
|
+
virtual void initialize();
|
|
65
338
|
|
|
66
339
|
/// Process CFLEdge
|
|
67
|
-
void processCFLEdge(const CFLEdge* Y_edge);
|
|
340
|
+
virtual void processCFLEdge(const CFLEdge* Y_edge);
|
|
68
341
|
|
|
69
342
|
/// Start solving
|
|
70
|
-
void solve();
|
|
343
|
+
virtual void solve();
|
|
71
344
|
|
|
72
345
|
/// Return CFL Graph
|
|
73
346
|
inline const CFLGraph* getGraph() const
|
|
@@ -80,11 +353,11 @@ public:
|
|
|
80
353
|
{
|
|
81
354
|
return grammar;
|
|
82
355
|
}
|
|
83
|
-
inline bool pushIntoWorklist(const CFLEdge* item)
|
|
356
|
+
virtual inline bool pushIntoWorklist(const CFLEdge* item)
|
|
84
357
|
{
|
|
85
358
|
return worklist.push(item);
|
|
86
359
|
}
|
|
87
|
-
inline bool isWorklistEmpty()
|
|
360
|
+
virtual inline bool isWorklistEmpty()
|
|
88
361
|
{
|
|
89
362
|
return worklist.empty();
|
|
90
363
|
}
|
|
@@ -103,7 +376,7 @@ protected:
|
|
|
103
376
|
}
|
|
104
377
|
//@}
|
|
105
378
|
|
|
106
|
-
|
|
379
|
+
protected:
|
|
107
380
|
CFLGraph* graph;
|
|
108
381
|
CFLGrammar* grammar;
|
|
109
382
|
/// Worklist for resolution
|
|
@@ -114,22 +387,52 @@ private:
|
|
|
114
387
|
/// Solver Utilize CFLData
|
|
115
388
|
class POCRSolver : public CFLSolver
|
|
116
389
|
{
|
|
390
|
+
public:
|
|
391
|
+
POCRSolver(CFLGraph* _graph, CFLGrammar* _grammar) : CFLSolver(_graph, _grammar), cflData(NULL)
|
|
392
|
+
{
|
|
393
|
+
if (!cflData)
|
|
394
|
+
{
|
|
395
|
+
cflData = new CFLData();
|
|
396
|
+
// Build CFL Data
|
|
397
|
+
buildCFLData();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
117
400
|
/// Destructor
|
|
118
401
|
virtual ~POCRSolver()
|
|
119
402
|
{
|
|
120
|
-
delete
|
|
403
|
+
delete cflData;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/// Process CFLEdge
|
|
407
|
+
virtual void processCFLEdge(const CFLEdge* Y_edge);
|
|
408
|
+
|
|
409
|
+
/// Init CFLData
|
|
410
|
+
virtual void buildCFLData();
|
|
411
|
+
|
|
412
|
+
virtual bool addEdge(const CFLNode* src, const CFLNode* dst, const Label ty)
|
|
413
|
+
{
|
|
414
|
+
return cflData->addEdge(src->getId(), dst->getId(), ty);
|
|
121
415
|
}
|
|
122
416
|
|
|
123
|
-
|
|
417
|
+
virtual bool addEdge(const NodeID srcId, const NodeID dstId, const Label ty)
|
|
124
418
|
{
|
|
125
|
-
return
|
|
419
|
+
return cflData->addEdge(srcId, dstId, ty);
|
|
126
420
|
}
|
|
127
421
|
|
|
128
|
-
|
|
422
|
+
virtual void initialize();
|
|
129
423
|
|
|
130
|
-
|
|
131
|
-
|
|
424
|
+
virtual NodeBS addEdges(const NodeID srcId, const NodeBS& dstData, const Label ty)
|
|
425
|
+
{
|
|
426
|
+
return cflData->addEdges(srcId, dstData, ty);
|
|
427
|
+
}
|
|
132
428
|
|
|
429
|
+
|
|
430
|
+
virtual NodeBS addEdges(const NodeBS& srcData, const NodeID dstId, const Label ty)
|
|
431
|
+
{
|
|
432
|
+
return cflData->addEdges(srcData, dstId, ty);
|
|
433
|
+
}
|
|
434
|
+
private:
|
|
435
|
+
CFLData* cflData;
|
|
133
436
|
};
|
|
134
437
|
}
|
|
135
438
|
|
package/svf/lib/CFL/CFLAlias.cpp
CHANGED
|
@@ -238,8 +238,6 @@ void CFLAlias::solve()
|
|
|
238
238
|
timeOfSolving += (end - start) / TIMEINTERVAL;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
double POCRAlias::timeOfBuildCFLData = 0; // Time of building CFLData from CFLGraph
|
|
242
|
-
|
|
243
241
|
void POCRAlias::initialize()
|
|
244
242
|
{
|
|
245
243
|
stat = new CFLStat(this);
|
|
@@ -250,26 +248,9 @@ void POCRAlias::initialize()
|
|
|
250
248
|
// Build CFL Graph
|
|
251
249
|
buildCFLGraph();
|
|
252
250
|
|
|
253
|
-
// Build CFL Data
|
|
254
|
-
buildCFLData();
|
|
255
|
-
|
|
256
251
|
// Normalize CFL Grammar
|
|
257
252
|
normalizeCFLGrammar();
|
|
258
253
|
|
|
259
|
-
// Initialize
|
|
260
|
-
solver = new
|
|
254
|
+
// Initialize POCRSolver
|
|
255
|
+
solver = new POCRSolver(graph, grammar);
|
|
261
256
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
void POCRAlias::buildCFLData()
|
|
265
|
-
{
|
|
266
|
-
// Start building CFLGraph
|
|
267
|
-
double start = stat->getClk(true);
|
|
268
|
-
|
|
269
|
-
CFLDataBuilder cflDataBuilder = CFLDataBuilder(graph);
|
|
270
|
-
_cflData = cflDataBuilder.build();
|
|
271
|
-
|
|
272
|
-
// Get time of build graph
|
|
273
|
-
double end = stat->getClk(true);
|
|
274
|
-
timeOfBuildCFLData += (end - start) / TIMEINTERVAL;
|
|
275
|
-
}
|
|
@@ -127,4 +127,92 @@ void CFLSolver::solve()
|
|
|
127
127
|
const CFLEdge* Y_edge = popFromWorklist();
|
|
128
128
|
processCFLEdge(Y_edge);
|
|
129
129
|
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
void POCRSolver::buildCFLData()
|
|
133
|
+
{
|
|
134
|
+
for (CFLEdge* edge: graph->getCFLEdges())
|
|
135
|
+
addEdge(edge->getSrcID(), edge->getDstID(), edge->getEdgeKind());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
void POCRSolver::processCFLEdge(const CFLEdge* Y_edge)
|
|
139
|
+
{
|
|
140
|
+
CFLNode* i = Y_edge->getSrcNode();
|
|
141
|
+
CFLNode* j = Y_edge->getDstNode();
|
|
142
|
+
|
|
143
|
+
/// For each production X -> Y
|
|
144
|
+
/// add X(i,j) if not exist to E and to worklist
|
|
145
|
+
Symbol Y = Y_edge->getEdgeKind();
|
|
146
|
+
if (grammar->hasProdsFromSingleRHS(Y))
|
|
147
|
+
for(const Production& prod : grammar->getProdsFromSingleRHS(Y))
|
|
148
|
+
{
|
|
149
|
+
Symbol X = grammar->getLHSSymbol(prod);
|
|
150
|
+
numOfChecks++;
|
|
151
|
+
if (addEdge(i->getId(), j->getId(), X))
|
|
152
|
+
{
|
|
153
|
+
const CFLEdge* newEdge = graph->addCFLEdge(Y_edge->getSrcNode(), Y_edge->getDstNode(), X);
|
|
154
|
+
pushIntoWorklist(newEdge);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/// For each production X -> Y Z
|
|
160
|
+
/// Foreach outgoing edge Z(j,k) from node j do
|
|
161
|
+
/// add X(i,k) if not exist to E and to worklist
|
|
162
|
+
if (grammar->hasProdsFromFirstRHS(Y))
|
|
163
|
+
for(const Production& prod : grammar->getProdsFromFirstRHS(Y))
|
|
164
|
+
{
|
|
165
|
+
Symbol X = grammar->getLHSSymbol(prod);
|
|
166
|
+
NodeBS diffDsts = addEdges(i->getId(), cflData->getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)], X);
|
|
167
|
+
numOfChecks += cflData->getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)].count();
|
|
168
|
+
for (NodeID diffDst: diffDsts)
|
|
169
|
+
{
|
|
170
|
+
const CFLEdge* newEdge = graph->addCFLEdge(i, graph->getGNode(diffDst), X);
|
|
171
|
+
pushIntoWorklist(newEdge);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// For each production X -> Z Y
|
|
176
|
+
/// Foreach incoming edge Z(k,i) to node i do
|
|
177
|
+
/// add X(k,j) if not exist to E and to worklist
|
|
178
|
+
if(grammar->hasProdsFromSecondRHS(Y))
|
|
179
|
+
for(const Production& prod : grammar->getProdsFromSecondRHS(Y))
|
|
180
|
+
{
|
|
181
|
+
Symbol X = grammar->getLHSSymbol(prod);
|
|
182
|
+
NodeBS diffSrcs = addEdges(cflData->getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)], j->getId(), X);
|
|
183
|
+
numOfChecks += cflData->getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)].count();
|
|
184
|
+
for (NodeID diffSrc: diffSrcs)
|
|
185
|
+
{
|
|
186
|
+
const CFLEdge* newEdge = graph->addCFLEdge(graph->getGNode(diffSrc), j, X);
|
|
187
|
+
pushIntoWorklist(newEdge);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
void POCRSolver::initialize()
|
|
193
|
+
{
|
|
194
|
+
for(auto it = graph->begin(); it!= graph->end(); it++)
|
|
195
|
+
{
|
|
196
|
+
for(const CFLEdge* edge : (*it).second->getOutEdges())
|
|
197
|
+
{
|
|
198
|
+
pushIntoWorklist(edge);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// Foreach production X -> epsilon
|
|
203
|
+
/// add X(i,i) if not exist to E and to worklist
|
|
204
|
+
for(const Production& prod : grammar->getEpsilonProds())
|
|
205
|
+
{
|
|
206
|
+
for(auto IDMap : cflData->getSuccMap())
|
|
207
|
+
{
|
|
208
|
+
Symbol X = grammar->getLHSSymbol(prod);
|
|
209
|
+
if (cflData->addEdge(IDMap.first, IDMap.first, X))
|
|
210
|
+
{
|
|
211
|
+
CFLNode* i = graph->getGNode(IDMap.first);
|
|
212
|
+
const CFLEdge* newEdge = graph->addCFLEdge(i, i, X);
|
|
213
|
+
pushIntoWorklist(newEdge);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
}
|
|
130
218
|
}
|
|
@@ -883,9 +883,15 @@ SVFConstantData* LLVMModuleSet::getSVFConstantData(const ConstantData* cd)
|
|
|
883
883
|
SVFConstantData* svfcd = nullptr;
|
|
884
884
|
if(const ConstantInt* cint = SVFUtil::dyn_cast<ConstantInt>(cd))
|
|
885
885
|
{
|
|
886
|
-
/// bool true will be translated to -1
|
|
887
|
-
|
|
888
|
-
|
|
886
|
+
/// bitwidth == 1 : cint has value from getZExtValue() because `bool true` will be translated to -1 using sign extension (i.e., getSExtValue).
|
|
887
|
+
/// bitwidth <=64 1 : cint has value from getSExtValue()
|
|
888
|
+
/// bitwidth >64 1 : cint has value 0 because it represents an invalid int
|
|
889
|
+
if(cint->getBitWidth() == 1)
|
|
890
|
+
svfcd = new SVFConstantInt(cd->getName().str(), getSVFType(cint->getType()), cint->getZExtValue(), cint->getZExtValue());
|
|
891
|
+
else if(cint->getBitWidth() <= 64 && cint->getBitWidth() > 1)
|
|
892
|
+
svfcd = new SVFConstantInt(cd->getName().str(), getSVFType(cint->getType()), cint->getZExtValue(), cint->getSExtValue());
|
|
893
|
+
else
|
|
894
|
+
svfcd = new SVFConstantInt(cd->getName().str(), getSVFType(cint->getType()), 0, 0);
|
|
889
895
|
}
|
|
890
896
|
else if(const ConstantFP* cfp = SVFUtil::dyn_cast<ConstantFP>(cd))
|
|
891
897
|
{
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
//===----- CFLData.h -- Context Free Language Reachability Graph Data Structure--------------//
|
|
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 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 General Public License for more details.
|
|
17
|
-
|
|
18
|
-
// You should have received a copy of the GNU General Public License
|
|
19
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
-
//
|
|
21
|
-
//===----------------------------------------------------------------------===//
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
* CFLData.h
|
|
25
|
-
*
|
|
26
|
-
* Created on: Nov 22, 2019
|
|
27
|
-
* Author: Yuxiang Lei
|
|
28
|
-
*
|
|
29
|
-
* The implementation is based on
|
|
30
|
-
* Yuxiang Lei, Yulei Sui, Shuo Ding, and Qirun Zhang.
|
|
31
|
-
* Taming Transitive Redundancy for Context-Free Language Reachability.
|
|
32
|
-
* ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
#ifndef INCLUDE_CFL_CFGDATA_H_
|
|
36
|
-
#define INCLUDE_CFL_CFGDATA_H_
|
|
37
|
-
|
|
38
|
-
#include "Util/WorkList.h"
|
|
39
|
-
#include "CFL/CFLGrammar.h"
|
|
40
|
-
|
|
41
|
-
namespace SVF
|
|
42
|
-
{
|
|
43
|
-
typedef GrammarBase::Symbol Label;
|
|
44
|
-
/*!
|
|
45
|
-
* Adjacency-list graph representation
|
|
46
|
-
*/
|
|
47
|
-
class CFLData
|
|
48
|
-
{
|
|
49
|
-
public:
|
|
50
|
-
typedef std::map<const Label, NodeBS> TypeMap; // Label with SparseBitVector of NodeID
|
|
51
|
-
typedef std::unordered_map<NodeID, TypeMap> DataMap; // Each Node has a TypeMap
|
|
52
|
-
typedef typename DataMap::iterator iterator; // iterator for each node
|
|
53
|
-
typedef typename DataMap::const_iterator const_iterator; // const iterator
|
|
54
|
-
|
|
55
|
-
protected:
|
|
56
|
-
DataMap succMap; // succ map for nodes contains Label: Edgeset
|
|
57
|
-
DataMap predMap; // pred map for nodes contains Label: edgeset
|
|
58
|
-
const NodeBS emptyData; // ??
|
|
59
|
-
NodeBS diff; // ??
|
|
60
|
-
|
|
61
|
-
// union/add data
|
|
62
|
-
//@{
|
|
63
|
-
inline bool addPred(const NodeID key, const NodeID src, const Label ty)
|
|
64
|
-
{
|
|
65
|
-
return predMap[key][ty].test_and_set(src);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
inline bool addSucc(const NodeID key, const NodeID dst, const Label ty)
|
|
69
|
-
{
|
|
70
|
-
return succMap[key][ty].test_and_set(dst);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
inline bool addPreds(const NodeID key, const NodeBS& data, const Label ty)
|
|
74
|
-
{
|
|
75
|
-
if (data.empty())
|
|
76
|
-
return false;
|
|
77
|
-
return predMap[key][ty] |= data; // union of sparsebitvector (add to LHS)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
inline bool addSuccs(const NodeID key, const NodeBS& data, const Label ty)
|
|
81
|
-
{
|
|
82
|
-
if (data.empty())
|
|
83
|
-
return false;
|
|
84
|
-
return succMap[key][ty] |= data; // // union of sparsebitvector (add to LHS)
|
|
85
|
-
}
|
|
86
|
-
//@}
|
|
87
|
-
|
|
88
|
-
public:
|
|
89
|
-
// Constructor
|
|
90
|
-
CFLData()
|
|
91
|
-
{}
|
|
92
|
-
|
|
93
|
-
// Destructor
|
|
94
|
-
virtual ~CFLData()
|
|
95
|
-
{}
|
|
96
|
-
|
|
97
|
-
virtual void clear()
|
|
98
|
-
{
|
|
99
|
-
succMap.clear();
|
|
100
|
-
predMap.clear();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
inline const_iterator begin() const
|
|
104
|
-
{
|
|
105
|
-
return succMap.begin();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
inline const_iterator end() const
|
|
109
|
-
{
|
|
110
|
-
return succMap.end();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
inline iterator begin()
|
|
114
|
-
{
|
|
115
|
-
return succMap.begin();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
inline iterator end()
|
|
119
|
-
{
|
|
120
|
-
return succMap.end();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
inline DataMap& getSuccMap()
|
|
124
|
-
{
|
|
125
|
-
return succMap;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
inline DataMap& getPredMap()
|
|
129
|
-
{
|
|
130
|
-
return predMap;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
inline TypeMap& getSuccMap(const NodeID key)
|
|
134
|
-
{
|
|
135
|
-
return succMap[key];
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
inline TypeMap& getPredMap(const NodeID key)
|
|
139
|
-
{
|
|
140
|
-
return predMap[key];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
inline NodeBS& getSuccs(const NodeID key, const Label ty)
|
|
144
|
-
{
|
|
145
|
-
return succMap[key][ty];
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
inline NodeBS& getPreds(const NodeID key, const Label ty)
|
|
149
|
-
{
|
|
150
|
-
return predMap[key][ty];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Alias data operations
|
|
154
|
-
//@{
|
|
155
|
-
inline bool addEdge(const NodeID src, const NodeID dst, const Label ty)
|
|
156
|
-
{
|
|
157
|
-
addSucc(src, dst, ty);
|
|
158
|
-
return addPred(dst, src, ty);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/// add edges and return the set of added edges (dst) for src
|
|
162
|
-
inline NodeBS addEdges(const NodeID src, const NodeBS& dstData, const Label ty)
|
|
163
|
-
{
|
|
164
|
-
NodeBS newDsts;
|
|
165
|
-
if (addSuccs(src, dstData, ty))
|
|
166
|
-
{
|
|
167
|
-
for (const NodeID datum: dstData)
|
|
168
|
-
if (addPred(datum, src, ty))
|
|
169
|
-
newDsts.set(datum);
|
|
170
|
-
}
|
|
171
|
-
return newDsts;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/// add edges and return the set of added edges (src) for dst
|
|
175
|
-
inline NodeBS addEdges(const NodeBS& srcData, const NodeID dst, const Label ty)
|
|
176
|
-
{
|
|
177
|
-
NodeBS newSrcs;
|
|
178
|
-
if (addPreds(dst, srcData, ty))
|
|
179
|
-
{
|
|
180
|
-
for (const NodeID datum: srcData)
|
|
181
|
-
if (addSucc(datum, dst, ty))
|
|
182
|
-
newSrcs.set(datum);
|
|
183
|
-
}
|
|
184
|
-
return newSrcs;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/// find src -> find src[ty] -> find dst in set
|
|
188
|
-
inline bool hasEdge(const NodeID src, const NodeID dst, const Label ty)
|
|
189
|
-
{
|
|
190
|
-
const_iterator iter1 = succMap.find(src);
|
|
191
|
-
if (iter1 == succMap.end())
|
|
192
|
-
return false;
|
|
193
|
-
|
|
194
|
-
auto iter2 = iter1->second.find(ty);
|
|
195
|
-
if (iter2 == iter1->second.end())
|
|
196
|
-
return false;
|
|
197
|
-
|
|
198
|
-
return iter2->second.test(dst);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/* This is a dataset version, to be modified to a cflData version */
|
|
202
|
-
inline void clearEdges(const NodeID key)
|
|
203
|
-
{
|
|
204
|
-
succMap[key].clear();
|
|
205
|
-
predMap[key].clear();
|
|
206
|
-
}
|
|
207
|
-
//@}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
/*!
|
|
212
|
-
* Hybrid graph representation for transitive relations
|
|
213
|
-
*/
|
|
214
|
-
class HybridData
|
|
215
|
-
{
|
|
216
|
-
public:
|
|
217
|
-
struct TreeNode
|
|
218
|
-
{
|
|
219
|
-
NodeID id;
|
|
220
|
-
std::unordered_set<TreeNode*> children;
|
|
221
|
-
|
|
222
|
-
TreeNode(NodeID nId) : id(nId)
|
|
223
|
-
{}
|
|
224
|
-
|
|
225
|
-
~TreeNode()
|
|
226
|
-
{
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
inline bool operator==(const TreeNode& rhs) const
|
|
230
|
-
{
|
|
231
|
-
return id == rhs.id;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
inline bool operator<(const TreeNode& rhs) const
|
|
235
|
-
{
|
|
236
|
-
return id < rhs.id;
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
public:
|
|
242
|
-
Map<NodeID, std::unordered_map<NodeID, TreeNode*>> indMap; // indMap[v][u] points to node v in tree(u)
|
|
243
|
-
|
|
244
|
-
HybridData()
|
|
245
|
-
{}
|
|
246
|
-
|
|
247
|
-
~HybridData()
|
|
248
|
-
{
|
|
249
|
-
for (auto iter1: indMap)
|
|
250
|
-
{
|
|
251
|
-
for (auto iter2: iter1.second)
|
|
252
|
-
{
|
|
253
|
-
delete iter2.second;
|
|
254
|
-
iter2.second = NULL;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
bool hasInd(NodeID src, NodeID dst)
|
|
260
|
-
{
|
|
261
|
-
auto it = indMap.find(dst);
|
|
262
|
-
if (it == indMap.end())
|
|
263
|
-
return false;
|
|
264
|
-
return (it->second.find(src) != it->second.end());
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/// Add a node dst to tree(src)
|
|
268
|
-
TreeNode* addInd(NodeID src, NodeID dst)
|
|
269
|
-
{
|
|
270
|
-
auto resIns = indMap[dst].insert(std::make_pair(src, new TreeNode(dst)));
|
|
271
|
-
if (resIns.second)
|
|
272
|
-
return resIns.first->second;
|
|
273
|
-
return nullptr;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/// Get the node dst in tree(src)
|
|
277
|
-
TreeNode* getNode(NodeID src, NodeID dst)
|
|
278
|
-
{
|
|
279
|
-
return indMap[dst][src];
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/// add v into desc(x) as a child of u
|
|
283
|
-
void insertEdge(TreeNode* u, TreeNode* v)
|
|
284
|
-
{
|
|
285
|
-
u->children.insert(v);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
void addArc(NodeID src, NodeID dst)
|
|
289
|
-
{
|
|
290
|
-
if (!hasInd(src, dst))
|
|
291
|
-
{
|
|
292
|
-
for (auto iter: indMap[src])
|
|
293
|
-
{
|
|
294
|
-
meld(iter.first, getNode(iter.first, src), getNode(dst, dst));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
void meld(NodeID x, TreeNode* uNode, TreeNode* vNode)
|
|
300
|
-
{
|
|
301
|
-
TreeNode* newVNode = addInd(x, vNode->id);
|
|
302
|
-
if (!newVNode)
|
|
303
|
-
return;
|
|
304
|
-
|
|
305
|
-
insertEdge(uNode, newVNode);
|
|
306
|
-
for (TreeNode* vChild: vNode->children)
|
|
307
|
-
{
|
|
308
|
-
meld(x, newVNode, vChild);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
} // end namespace SVF
|
|
315
|
-
|
|
316
|
-
#endif
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
//===----- CFLDataBuilder.h -- CFL Data Builder --------------//
|
|
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 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 General Public License for more details.
|
|
17
|
-
|
|
18
|
-
// You should have received a copy of the GNU General Public License
|
|
19
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
-
//
|
|
21
|
-
//===----------------------------------------------------------------------===//
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
* CFLGraphBuilder.h
|
|
25
|
-
*
|
|
26
|
-
* Created on: Nov 6, 2022
|
|
27
|
-
* Author: Pei Xu
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
#ifndef INCLUDE_CFL_CFLDATABUILDER_H_
|
|
31
|
-
#define INCLUDE_CFL_CFLDATABUILDER_H_
|
|
32
|
-
|
|
33
|
-
#include "CFL/CFLData.h"
|
|
34
|
-
#include "Graphs/CFLGraph.h"
|
|
35
|
-
|
|
36
|
-
namespace SVF
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
/*!
|
|
40
|
-
* Build CFLData from CFL graph
|
|
41
|
-
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
class CFLDataBuilder
|
|
45
|
-
{
|
|
46
|
-
protected:
|
|
47
|
-
CFLData* _cflData;
|
|
48
|
-
CFLGraph* _graph;
|
|
49
|
-
|
|
50
|
-
public:
|
|
51
|
-
/// Constructor
|
|
52
|
-
CFLDataBuilder(CFLGraph* cflgraph) : _cflData(NULL), _graph(cflgraph)
|
|
53
|
-
{
|
|
54
|
-
if (!_cflData)
|
|
55
|
-
_cflData = new CFLData();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/// Destructor
|
|
59
|
-
virtual ~CFLDataBuilder()
|
|
60
|
-
{
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
CFLData* cflData()
|
|
64
|
-
{
|
|
65
|
-
return _cflData;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//CFL data operations
|
|
69
|
-
//@{
|
|
70
|
-
virtual bool addEdge(const NodeID srcId, const NodeID dstId, const Label ty)
|
|
71
|
-
{
|
|
72
|
-
return cflData()->addEdge(srcId, dstId, ty);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
virtual NodeBS addEdges(const NodeID srcId, const NodeBS& dstData, const Label ty)
|
|
76
|
-
{
|
|
77
|
-
return cflData()->addEdges(srcId, dstData, ty);
|
|
78
|
-
}
|
|
79
|
-
//@}
|
|
80
|
-
CFLData* build()
|
|
81
|
-
{
|
|
82
|
-
for (CFLEdge* edge: _graph->getCFLEdges())
|
|
83
|
-
addEdge(edge->getSrcID(), edge->getDstID(), edge->getEdgeKind());
|
|
84
|
-
return cflData();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
};
|
|
89
|
-
}// SVF
|
|
90
|
-
|
|
91
|
-
#endif /* INCLUDE_CFL_CFLGRAPHBUILDER_H_*/
|