svf-lib 1.0.1111 → 1.0.1114

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.
@@ -30,7 +30,7 @@
30
30
  #ifndef PROGSLICE_H_
31
31
  #define PROGSLICE_H_
32
32
 
33
- #include "SABER/PathCondAllocator.h"
33
+ #include "SABER/SaberCondAllocator.h"
34
34
  #include "Util/WorkList.h"
35
35
  #include "Graphs/SVFG.h"
36
36
  #include "Util/DPItem.h"
@@ -44,14 +44,14 @@ class ProgSlice
44
44
  public:
45
45
  typedef Set<const SVFGNode*> SVFGNodeSet;
46
46
  typedef SVFGNodeSet::const_iterator SVFGNodeSetIter;
47
- typedef PathCondAllocator::Condition Condition;
48
- typedef Map<const SVFGNode*, Condition*> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
47
+ typedef SaberCondAllocator::Condition Condition;
48
+ typedef Map<const SVFGNode*, Condition> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
49
49
 
50
50
  typedef FIFOWorkList<const SVFGNode*> VFWorkList; ///< worklist for value-flow guard computation
51
51
  typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
52
52
 
53
53
  /// Constructor
54
- ProgSlice(const SVFGNode* src, PathCondAllocator* pa, const SVFG* graph):
54
+ ProgSlice(const SVFGNode* src, SaberCondAllocator* pa, const SVFG* graph):
55
55
  root(src), partialReachable(false), fullReachable(false), reachGlob(false),
56
56
  pathAllocator(pa), _curSVFGNode(nullptr), finalCond(pa->getFalseCond()), svfg(graph)
57
57
  {
@@ -168,27 +168,27 @@ public:
168
168
 
169
169
  /// Condition operations
170
170
  //@{
171
- inline Condition* condAnd(Condition* lhs, Condition* rhs)
171
+ inline Condition condAnd(const Condition &lhs, const Condition &rhs)
172
172
  {
173
173
  return pathAllocator->condAnd(lhs,rhs);
174
174
  }
175
- inline Condition* condOr(Condition* lhs, Condition* rhs)
175
+ inline Condition condOr(const Condition &lhs, const Condition &rhs)
176
176
  {
177
177
  return pathAllocator->condOr(lhs,rhs);
178
178
  }
179
- inline Condition* condNeg(Condition* cond)
179
+ inline Condition condNeg(const Condition &cond)
180
180
  {
181
181
  return pathAllocator->condNeg(cond);
182
182
  }
183
- inline Condition* getTrueCond() const
183
+ inline Condition getTrueCond() const
184
184
  {
185
185
  return pathAllocator->getTrueCond();
186
186
  }
187
- inline Condition* getFalseCond() const
187
+ inline Condition getFalseCond() const
188
188
  {
189
189
  return pathAllocator->getFalseCond();
190
190
  }
191
- inline std::string dumpCond(Condition* cond) const
191
+ inline std::string dumpCond(const Condition& cond) const
192
192
  {
193
193
  return pathAllocator->dumpCond(cond);
194
194
  }
@@ -210,13 +210,13 @@ protected:
210
210
  /// Clear Control flow conditions before each VF computation
211
211
  inline void clearCFCond()
212
212
  {
213
- /// TODO: how to clean bdd memory
213
+ /// TODO: how to clean z3 memory
214
214
  pathAllocator->clearCFCond();
215
215
  }
216
216
 
217
217
  /// Get/set VF (value-flow) and CF (control-flow) conditions
218
218
  //@{
219
- inline Condition* getVFCond(const SVFGNode* node) const
219
+ inline Condition getVFCond(const SVFGNode* node) const
220
220
  {
221
221
  SVFGNodeToCondMap::const_iterator it = svfgNodeToCondMap.find(node);
222
222
  if(it==svfgNodeToCondMap.end())
@@ -225,7 +225,7 @@ protected:
225
225
  }
226
226
  return it->second;
227
227
  }
228
- inline bool setVFCond(const SVFGNode* node, Condition* cond)
228
+ inline bool setVFCond(const SVFGNode* node, const Condition &cond)
229
229
  {
230
230
  SVFGNodeToCondMap::iterator it = svfgNodeToCondMap.find(node);
231
231
  // until a fixed-point is reached (condition is not changed)
@@ -239,21 +239,21 @@ protected:
239
239
 
240
240
  /// Compute guards for value-flows
241
241
  //@{
242
- inline Condition* ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
242
+ inline Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
243
243
  {
244
244
  return pathAllocator->ComputeIntraVFGGuard(src,dst);
245
245
  }
246
- inline Condition* ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
246
+ inline Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
247
247
  {
248
248
  return pathAllocator->ComputeInterCallVFGGuard(src,dst,callBB);
249
249
  }
250
- inline Condition* ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
250
+ inline Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
251
251
  {
252
252
  return pathAllocator->ComputeInterRetVFGGuard(src,dst,retBB);
253
253
  }
254
254
  //@}
255
255
 
256
- inline bool isEquivalentBranchCond(const Condition *lhs, const Condition *rhs) const
256
+ inline bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
257
257
  {
258
258
  return pathAllocator->isEquivalentBranchCond(lhs, rhs);
259
259
  };
@@ -284,7 +284,7 @@ protected:
284
284
  }
285
285
  //@}
286
286
  /// Set final condition after all path reachability analysis
287
- inline void setFinalCond(Condition* cond)
287
+ inline void setFinalCond(const Condition &cond)
288
288
  {
289
289
  finalCond = cond;
290
290
  }
@@ -298,9 +298,9 @@ private:
298
298
  bool partialReachable; ///< reachable from some paths
299
299
  bool fullReachable; ///< reachable from all paths
300
300
  bool reachGlob; ///< Whether slice reach a global
301
- PathCondAllocator* pathAllocator; ///< path condition allocator
301
+ SaberCondAllocator* pathAllocator; ///< path condition allocator
302
302
  const SVFGNode* _curSVFGNode; ///< current svfg node during guard computation
303
- Condition* finalCond; ///< final condition
303
+ Condition finalCond; ///< final condition
304
304
  const SVFG* svfg; ///< SVFG
305
305
  };
306
306
 
@@ -0,0 +1,305 @@
1
+ //===- SaberCondAllocator.h -- Path condition manipulation---------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2017> <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
+ * PathAllocator.h
25
+ *
26
+ * Created on: Apr 3, 2014
27
+ * Author: Yulei Sui
28
+ */
29
+
30
+ #ifndef PATHALLOCATOR_H_
31
+ #define PATHALLOCATOR_H_
32
+
33
+ #include "Util/SVFModule.h"
34
+ #include "SVF-FE/DataFlowUtil.h"
35
+ #include "SVF-FE/BasicTypes.h"
36
+ #include "Util/WorkList.h"
37
+ #include "Graphs/SVFG.h"
38
+ #include "Util/Z3Expr.h"
39
+
40
+
41
+ namespace SVF
42
+ {
43
+
44
+ /**
45
+ * SaberCondAllocator allocates conditions for each basic block of a certain CFG.
46
+ */
47
+ class SaberCondAllocator
48
+ {
49
+
50
+ public:
51
+
52
+ typedef Z3Expr Condition; /// z3 condition
53
+ typedef Map<u32_t, const Instruction *> IndexToTermInstMap; /// id to instruction map for z3
54
+ typedef Map<u32_t,Condition> CondPosMap; ///< map a branch to its Condition
55
+ typedef Map<const BasicBlock*, CondPosMap > BBCondMap; /// map bb to a Condition
56
+ typedef Set<const BasicBlock*> BasicBlockSet;
57
+ typedef Map<const Function*, BasicBlockSet> FunToExitBBsMap; ///< map a function to all its basic blocks calling program exit
58
+ typedef Map<const BasicBlock*, Condition> BBToCondMap; ///< map a basic block to its condition during control-flow guard computation
59
+ typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
60
+
61
+
62
+ /// Constructor
63
+ SaberCondAllocator();
64
+
65
+ /// Destructor
66
+ virtual ~SaberCondAllocator()
67
+ {
68
+ }
69
+ /// Statistics
70
+ //@{
71
+ inline std::string getMemUsage()
72
+ {
73
+ return "";
74
+ }
75
+ inline u32_t getCondNum()
76
+ {
77
+ return totalCondNum;
78
+ }
79
+ //@}
80
+
81
+ /// Condition operations
82
+ //@{
83
+ inline Condition condAnd(const Condition& lhs, const Condition& rhs)
84
+ {
85
+ return Condition::AND(lhs,rhs);
86
+ }
87
+ inline Condition condOr(const Condition& lhs, const Condition& rhs)
88
+ {
89
+ return Condition::OR(lhs,rhs);
90
+ }
91
+ inline Condition condNeg(const Condition& cond)
92
+ {
93
+ return Condition::NEG(cond);
94
+ }
95
+ inline Condition getTrueCond() const
96
+ {
97
+ return Condition::getTrueCond();
98
+ }
99
+ inline Condition getFalseCond() const
100
+ {
101
+ return Condition::getFalseCond();
102
+ }
103
+ /// Iterator every element of the condition
104
+ inline NodeBS exactCondElem(const Condition& cond)
105
+ {
106
+ NodeBS elems;
107
+ extractSubConds(cond, elems);
108
+ return elems;
109
+ }
110
+
111
+ inline std::string dumpCond(const Condition& cond) const
112
+ {
113
+ return Condition::dumpStr(cond);
114
+ }
115
+
116
+ /// Allocate a new condition
117
+ Condition newCond(const Instruction* inst);
118
+
119
+ /// Perform path allocation
120
+ void allocate(const SVFModule* module);
121
+
122
+ /// Get/Set instruction based on Z3 expression id
123
+ //{@
124
+ inline const Instruction *getCondInst(u32_t id) const
125
+ {
126
+ IndexToTermInstMap::const_iterator it = idToTermInstMap.find(id);
127
+ assert(it != idToTermInstMap.end() && "this should be a fresh condition");
128
+ return it->second;
129
+ }
130
+
131
+ inline void setCondInst(const Condition &condition, const Instruction *inst)
132
+ {
133
+ assert(idToTermInstMap.find(condition.id()) == idToTermInstMap.end() && "this should be a fresh condition");
134
+ idToTermInstMap[condition.id()] = inst;
135
+ }
136
+ //@}
137
+
138
+ bool isNegCond(u32_t id) const
139
+ {
140
+ return negConds.test(id);
141
+ }
142
+
143
+ /// Get dominators
144
+ inline DominatorTree* getDT(const Function* fun)
145
+ {
146
+ return cfInfoBuilder.getDT(fun);
147
+ }
148
+ /// Get Postdominators
149
+ inline PostDominatorTree* getPostDT(const Function* fun)
150
+ {
151
+ return cfInfoBuilder.getPostDT(fun);
152
+ }
153
+ /// Get LoopInfo
154
+ inline LoopInfo* getLoopInfo(const Function* f)
155
+ {
156
+ return cfInfoBuilder.getLoopInfo(f);
157
+ }
158
+
159
+
160
+ /// Guard Computation for a value-flow (between two basic blocks)
161
+ //@{
162
+ virtual Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst);
163
+ virtual Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB);
164
+ virtual Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB);
165
+
166
+ /// Get complement condition (from B1 to B0) according to a complementBB (BB2) at a phi
167
+ /// e.g., B0: dstBB; B1:incomingBB; B2:complementBB
168
+ virtual Condition getPHIComplementCond(const BasicBlock* BB1, const BasicBlock* BB2, const BasicBlock* BB0);
169
+
170
+ inline void clearCFCond()
171
+ {
172
+ bbToCondMap.clear();
173
+ }
174
+ /// Set current value for branch condition evaluation
175
+ inline void setCurEvalSVFGNode(const SVFGNode* node)
176
+ {
177
+ curEvalSVFGNode = node;
178
+ }
179
+ /// Get current value for branch condition evaluation
180
+ inline const SVFGNode* getCurEvalSVFGNode() const
181
+ {
182
+ return curEvalSVFGNode;
183
+ }
184
+ //@}
185
+
186
+ /// Print out the path condition information
187
+ void printPathCond();
188
+
189
+ /// whether condition is satisfiable
190
+ bool isSatisfiable(const Condition& condition);
191
+
192
+ /// whether condition is satisfiable for all possible boolean guards
193
+ inline bool isAllPathReachable(Condition& condition)
194
+ {
195
+ return isEquivalentBranchCond(condition, Condition::getTrueCond());
196
+ }
197
+
198
+ /// Whether lhs and rhs are equivalent branch conditions
199
+ bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const;
200
+
201
+ inline ICFG* getICFG() const
202
+ {
203
+ return PAG::getPAG()->getICFG();
204
+ }
205
+
206
+ /// Get/Set control-flow conditions
207
+ //@{
208
+ inline bool setCFCond(const BasicBlock* bb, const Condition& cond)
209
+ {
210
+ BBToCondMap::iterator it = bbToCondMap.find(bb);
211
+ // until a fixed-point is reached (condition is not changed)
212
+ if(it!=bbToCondMap.end() && isEquivalentBranchCond(it->second, cond))
213
+ return false;
214
+
215
+ bbToCondMap[bb] = cond;
216
+ return true;
217
+ }
218
+ inline Condition getCFCond(const BasicBlock* bb) const
219
+ {
220
+ BBToCondMap::const_iterator it = bbToCondMap.find(bb);
221
+ if(it==bbToCondMap.end())
222
+ {
223
+ return getFalseCond();
224
+ }
225
+ return it->second;
226
+ }
227
+ //@}
228
+
229
+
230
+ /// mark neg Z3 expression
231
+ inline void setNegCondInst(const Condition &condition, const Instruction *inst)
232
+ {
233
+ setCondInst(condition, inst);
234
+ negConds.set(condition.id());
235
+ }
236
+ private:
237
+
238
+ /// Allocate path condition for every basic block
239
+ virtual void allocateForBB(const BasicBlock& bb);
240
+
241
+ /// Get/Set a branch condition, and its terminator instruction
242
+ //@{
243
+ /// Set branch condition
244
+ void setBranchCond(const BasicBlock *bb, const BasicBlock *succ, const Condition& cond);
245
+ /// Get branch condition
246
+ Condition getBranchCond(const BasicBlock * bb, const BasicBlock *succ) const;
247
+ ///Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
248
+ Condition getEvalBrCond(const BasicBlock * bb, const BasicBlock *succ);
249
+ //@}
250
+ /// Evaluate branch conditions
251
+ //@{
252
+ /// Evaluate the branch condtion
253
+ Condition evaluateBranchCond(const BasicBlock * bb, const BasicBlock *succ) ;
254
+ /// Evaluate loop exit branch
255
+ Condition evaluateLoopExitBranch(const BasicBlock * bb, const BasicBlock *succ);
256
+ /// Return branch condition after evaluating test null like expression
257
+ Condition evaluateTestNullLikeExpr(const BranchStmt* branchStmt, const BasicBlock *succ);
258
+ /// Return condition when there is a branch calls program exit
259
+ Condition evaluateProgExit(const BranchStmt* branchStmt, const BasicBlock *succ);
260
+ /// Collect basic block contains program exit function call
261
+ void collectBBCallingProgExit(const BasicBlock& bb);
262
+ bool isBBCallsProgExit(const BasicBlock* bb);
263
+ //@}
264
+
265
+ /// Evaluate test null/not null like expressions
266
+ //@{
267
+ /// Return true if the predicate of this compare instruction is equal
268
+ bool isEQCmp(const CmpInst* cmp) const;
269
+ /// Return true if the predicate of this compare instruction is not equal
270
+ bool isNECmp(const CmpInst* cmp) const;
271
+ /// Return true if this is a test null expression
272
+ bool isTestNullExpr(const Value* test) const;
273
+ /// Return true if this is a test not null expression
274
+ bool isTestNotNullExpr(const Value* test) const;
275
+ /// Return true if two values on the predicate are what we want
276
+ bool isTestContainsNullAndTheValue(const CmpInst* cmp) const;
277
+ //@}
278
+
279
+ /// Release memory
280
+ void destroy()
281
+ {
282
+
283
+ }
284
+
285
+ /// extract subexpression from a Z3 expression
286
+ void extractSubConds(const Condition &condition, NodeBS &support) const;
287
+
288
+
289
+ PTACFInfoBuilder cfInfoBuilder; ///< map a function to its loop info
290
+ FunToExitBBsMap funToExitBBsMap; ///< map a function to all its basic blocks calling program exit
291
+ BBToCondMap bbToCondMap; ///< map a basic block to its path condition starting from root
292
+ const SVFGNode* curEvalSVFGNode{}; ///< current llvm value to evaluate branch condition when computing guards
293
+ IndexToTermInstMap idToTermInstMap; ///key: z3 expression id, value: instruction
294
+ NodeBS negConds; ///bit vector for distinguish neg
295
+ std::vector<Condition> conditionVec; /// vector storing z3expression
296
+ static u32_t totalCondNum; /// a counter for fresh condition
297
+
298
+ protected:
299
+ BBCondMap bbConds; ///< map basic block to its successors/predecessors branch conditions
300
+
301
+ };
302
+
303
+ } // End namespace SVF
304
+
305
+ #endif /* PATHALLOCATOR_H_ */
@@ -62,7 +62,7 @@ private:
62
62
  ProgSlice* _curSlice; /// current program slice
63
63
  SVFGNodeSet sources; /// source nodes
64
64
  SVFGNodeSet sinks; /// source nodes
65
- PathCondAllocator* pathCondAllocator;
65
+ SaberCondAllocator* saberCondAllocator;
66
66
  SVFGNodeToDPItemsMap nodeToDPItemsMap; ///< record forward visited dpitems
67
67
  SVFGNodeSet visitedSet; ///< record backward visited nodes
68
68
 
@@ -76,7 +76,7 @@ public:
76
76
  /// Constructor
77
77
  SrcSnkDDA() : _curSlice(nullptr), svfg(nullptr), ptaCallGraph(nullptr)
78
78
  {
79
- pathCondAllocator = new PathCondAllocator();
79
+ saberCondAllocator = new SaberCondAllocator();
80
80
  }
81
81
  /// Destructor
82
82
  virtual ~SrcSnkDDA()
@@ -232,10 +232,10 @@ public:
232
232
  }
233
233
  //@}
234
234
 
235
- /// Get path condition allocator
236
- PathCondAllocator* getPathAllocator() const
235
+ /// Get saber condition allocator
236
+ SaberCondAllocator* getSaberCondAllocator() const
237
237
  {
238
- return pathCondAllocator;
238
+ return saberCondAllocator;
239
239
  }
240
240
 
241
241
  protected:
@@ -307,7 +307,7 @@ protected:
307
307
  //@{
308
308
  void dumpSlices();
309
309
  void annotateSlice(ProgSlice* slice);
310
- void printBDDStat();
310
+ void printZ3Stat();
311
311
  //@}
312
312
 
313
313
  };
@@ -30,7 +30,6 @@
30
30
  #ifndef DPITEM_H_
31
31
  #define DPITEM_H_
32
32
 
33
- #include "Util/BDDExpr.h"
34
33
  #include "MemoryModel/ConditionalPT.h"
35
34
  #include <algorithm> // std::sort
36
35
 
@@ -218,9 +218,9 @@ public:
218
218
  static const llvm::cl::opt<bool> SymTabPrint;
219
219
 
220
220
  // Conditions.cpp
221
- static const llvm::cl::opt<unsigned> MaxBddSize;
221
+ static const llvm::cl::opt<unsigned> MaxZ3Size;
222
222
 
223
- // PathCondAllocator.cpp
223
+ // SaberCondAllocator.cpp
224
224
  static const llvm::cl::opt<bool> PrintPathCond;
225
225
 
226
226
  // SVFUtil.cpp
@@ -39,6 +39,7 @@ class Z3Expr
39
39
  {
40
40
  public:
41
41
  static z3::context *ctx;
42
+ static z3::solver* solver;
42
43
 
43
44
  private:
44
45
  z3::expr e;
@@ -80,22 +81,18 @@ public:
80
81
  return e;
81
82
  }
82
83
 
84
+ /// Get z3 solver, singleton design here to make sure we only have one context
85
+ static z3::solver &getSolver();
86
+
83
87
  /// Get z3 context, singleton design here to make sure we only have one context
84
- static z3::context &getContext()
85
- {
86
- if (ctx == nullptr)
87
- {
88
- ctx = new z3::context();
89
- }
90
- return *ctx;
91
- }
88
+ static z3::context &getContext();
92
89
 
93
90
  /// release z3 context
94
- static void releaseContext()
95
- {
96
- delete ctx;
97
- ctx = nullptr;
98
- }
91
+ static void releaseContext();
92
+
93
+ /// release z3 solver
94
+ static void releaseSolver();
95
+
99
96
 
100
97
  /// null expression
101
98
  static z3::expr nullExpr()
@@ -109,6 +106,12 @@ public:
109
106
  return e.id();
110
107
  }
111
108
 
109
+ /// get hash id
110
+ inline u32_t hash() const
111
+ {
112
+ return e.hash();
113
+ }
114
+
112
115
  inline const std::string to_string() const
113
116
  {
114
117
  return e.to_string();
@@ -245,7 +248,7 @@ public:
245
248
  return !lhs.getExpr();
246
249
  }
247
250
 
248
- friend Z3Expr ite(const Z3Expr& cond, const Z3Expr& lhs, const Z3Expr& rhs)
251
+ friend Z3Expr ite(const Z3Expr &cond, const Z3Expr &lhs, const Z3Expr &rhs)
249
252
  {
250
253
  return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
251
254
  }
@@ -266,6 +269,38 @@ public:
266
269
  return getExpr().get_sort();
267
270
  }
268
271
  //%}
272
+
273
+ /// output Z3 expression as a string
274
+ static std::string dumpStr(const Z3Expr &z3Expr);
275
+
276
+
277
+ /// get the number of subexpression of a Z3 expression
278
+ static u32_t getExprSize(const Z3Expr &z3Expr);
279
+
280
+ /// Return the unique true condition
281
+ static inline Z3Expr getTrueCond()
282
+ {
283
+ return getContext().bool_val(true);
284
+ }
285
+
286
+
287
+ /// Return the unique false condition
288
+ static inline Z3Expr getFalseCond()
289
+ {
290
+ return getContext().bool_val(false);
291
+ }
292
+
293
+ /// compute NEG
294
+ static inline Z3Expr NEG(const Z3Expr &z3Expr)
295
+ {
296
+ return !z3Expr;
297
+ }
298
+
299
+ /// compute AND, used for branch condition
300
+ static Z3Expr AND(const Z3Expr &lhs, const Z3Expr &rhs);
301
+
302
+ /// compute OR, used for branch condition
303
+ static Z3Expr OR(const Z3Expr &lhs, const Z3Expr &rhs);
269
304
  };
270
305
  }
271
306
 
Binary file
@@ -30,7 +30,7 @@
30
30
  #ifndef PROGSLICE_H_
31
31
  #define PROGSLICE_H_
32
32
 
33
- #include "SABER/PathCondAllocator.h"
33
+ #include "SABER/SaberCondAllocator.h"
34
34
  #include "Util/WorkList.h"
35
35
  #include "Graphs/SVFG.h"
36
36
  #include "Util/DPItem.h"
@@ -44,14 +44,14 @@ class ProgSlice
44
44
  public:
45
45
  typedef Set<const SVFGNode*> SVFGNodeSet;
46
46
  typedef SVFGNodeSet::const_iterator SVFGNodeSetIter;
47
- typedef PathCondAllocator::Condition Condition;
48
- typedef Map<const SVFGNode*, Condition*> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
47
+ typedef SaberCondAllocator::Condition Condition;
48
+ typedef Map<const SVFGNode*, Condition> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
49
49
 
50
50
  typedef FIFOWorkList<const SVFGNode*> VFWorkList; ///< worklist for value-flow guard computation
51
51
  typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
52
52
 
53
53
  /// Constructor
54
- ProgSlice(const SVFGNode* src, PathCondAllocator* pa, const SVFG* graph):
54
+ ProgSlice(const SVFGNode* src, SaberCondAllocator* pa, const SVFG* graph):
55
55
  root(src), partialReachable(false), fullReachable(false), reachGlob(false),
56
56
  pathAllocator(pa), _curSVFGNode(nullptr), finalCond(pa->getFalseCond()), svfg(graph)
57
57
  {
@@ -168,27 +168,27 @@ public:
168
168
 
169
169
  /// Condition operations
170
170
  //@{
171
- inline Condition* condAnd(Condition* lhs, Condition* rhs)
171
+ inline Condition condAnd(const Condition &lhs, const Condition &rhs)
172
172
  {
173
173
  return pathAllocator->condAnd(lhs,rhs);
174
174
  }
175
- inline Condition* condOr(Condition* lhs, Condition* rhs)
175
+ inline Condition condOr(const Condition &lhs, const Condition &rhs)
176
176
  {
177
177
  return pathAllocator->condOr(lhs,rhs);
178
178
  }
179
- inline Condition* condNeg(Condition* cond)
179
+ inline Condition condNeg(const Condition &cond)
180
180
  {
181
181
  return pathAllocator->condNeg(cond);
182
182
  }
183
- inline Condition* getTrueCond() const
183
+ inline Condition getTrueCond() const
184
184
  {
185
185
  return pathAllocator->getTrueCond();
186
186
  }
187
- inline Condition* getFalseCond() const
187
+ inline Condition getFalseCond() const
188
188
  {
189
189
  return pathAllocator->getFalseCond();
190
190
  }
191
- inline std::string dumpCond(Condition* cond) const
191
+ inline std::string dumpCond(const Condition& cond) const
192
192
  {
193
193
  return pathAllocator->dumpCond(cond);
194
194
  }
@@ -210,13 +210,13 @@ protected:
210
210
  /// Clear Control flow conditions before each VF computation
211
211
  inline void clearCFCond()
212
212
  {
213
- /// TODO: how to clean bdd memory
213
+ /// TODO: how to clean z3 memory
214
214
  pathAllocator->clearCFCond();
215
215
  }
216
216
 
217
217
  /// Get/set VF (value-flow) and CF (control-flow) conditions
218
218
  //@{
219
- inline Condition* getVFCond(const SVFGNode* node) const
219
+ inline Condition getVFCond(const SVFGNode* node) const
220
220
  {
221
221
  SVFGNodeToCondMap::const_iterator it = svfgNodeToCondMap.find(node);
222
222
  if(it==svfgNodeToCondMap.end())
@@ -225,7 +225,7 @@ protected:
225
225
  }
226
226
  return it->second;
227
227
  }
228
- inline bool setVFCond(const SVFGNode* node, Condition* cond)
228
+ inline bool setVFCond(const SVFGNode* node, const Condition &cond)
229
229
  {
230
230
  SVFGNodeToCondMap::iterator it = svfgNodeToCondMap.find(node);
231
231
  // until a fixed-point is reached (condition is not changed)
@@ -239,21 +239,21 @@ protected:
239
239
 
240
240
  /// Compute guards for value-flows
241
241
  //@{
242
- inline Condition* ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
242
+ inline Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
243
243
  {
244
244
  return pathAllocator->ComputeIntraVFGGuard(src,dst);
245
245
  }
246
- inline Condition* ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
246
+ inline Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
247
247
  {
248
248
  return pathAllocator->ComputeInterCallVFGGuard(src,dst,callBB);
249
249
  }
250
- inline Condition* ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
250
+ inline Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
251
251
  {
252
252
  return pathAllocator->ComputeInterRetVFGGuard(src,dst,retBB);
253
253
  }
254
254
  //@}
255
255
 
256
- inline bool isEquivalentBranchCond(const Condition *lhs, const Condition *rhs) const
256
+ inline bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
257
257
  {
258
258
  return pathAllocator->isEquivalentBranchCond(lhs, rhs);
259
259
  };
@@ -284,7 +284,7 @@ protected:
284
284
  }
285
285
  //@}
286
286
  /// Set final condition after all path reachability analysis
287
- inline void setFinalCond(Condition* cond)
287
+ inline void setFinalCond(const Condition &cond)
288
288
  {
289
289
  finalCond = cond;
290
290
  }
@@ -298,9 +298,9 @@ private:
298
298
  bool partialReachable; ///< reachable from some paths
299
299
  bool fullReachable; ///< reachable from all paths
300
300
  bool reachGlob; ///< Whether slice reach a global
301
- PathCondAllocator* pathAllocator; ///< path condition allocator
301
+ SaberCondAllocator* pathAllocator; ///< path condition allocator
302
302
  const SVFGNode* _curSVFGNode; ///< current svfg node during guard computation
303
- Condition* finalCond; ///< final condition
303
+ Condition finalCond; ///< final condition
304
304
  const SVFG* svfg; ///< SVFG
305
305
  };
306
306
 
@@ -0,0 +1,305 @@
1
+ //===- SaberCondAllocator.h -- Path condition manipulation---------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2017> <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
+ * PathAllocator.h
25
+ *
26
+ * Created on: Apr 3, 2014
27
+ * Author: Yulei Sui
28
+ */
29
+
30
+ #ifndef PATHALLOCATOR_H_
31
+ #define PATHALLOCATOR_H_
32
+
33
+ #include "Util/SVFModule.h"
34
+ #include "SVF-FE/DataFlowUtil.h"
35
+ #include "SVF-FE/BasicTypes.h"
36
+ #include "Util/WorkList.h"
37
+ #include "Graphs/SVFG.h"
38
+ #include "Util/Z3Expr.h"
39
+
40
+
41
+ namespace SVF
42
+ {
43
+
44
+ /**
45
+ * SaberCondAllocator allocates conditions for each basic block of a certain CFG.
46
+ */
47
+ class SaberCondAllocator
48
+ {
49
+
50
+ public:
51
+
52
+ typedef Z3Expr Condition; /// z3 condition
53
+ typedef Map<u32_t, const Instruction *> IndexToTermInstMap; /// id to instruction map for z3
54
+ typedef Map<u32_t,Condition> CondPosMap; ///< map a branch to its Condition
55
+ typedef Map<const BasicBlock*, CondPosMap > BBCondMap; /// map bb to a Condition
56
+ typedef Set<const BasicBlock*> BasicBlockSet;
57
+ typedef Map<const Function*, BasicBlockSet> FunToExitBBsMap; ///< map a function to all its basic blocks calling program exit
58
+ typedef Map<const BasicBlock*, Condition> BBToCondMap; ///< map a basic block to its condition during control-flow guard computation
59
+ typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
60
+
61
+
62
+ /// Constructor
63
+ SaberCondAllocator();
64
+
65
+ /// Destructor
66
+ virtual ~SaberCondAllocator()
67
+ {
68
+ }
69
+ /// Statistics
70
+ //@{
71
+ inline std::string getMemUsage()
72
+ {
73
+ return "";
74
+ }
75
+ inline u32_t getCondNum()
76
+ {
77
+ return totalCondNum;
78
+ }
79
+ //@}
80
+
81
+ /// Condition operations
82
+ //@{
83
+ inline Condition condAnd(const Condition& lhs, const Condition& rhs)
84
+ {
85
+ return Condition::AND(lhs,rhs);
86
+ }
87
+ inline Condition condOr(const Condition& lhs, const Condition& rhs)
88
+ {
89
+ return Condition::OR(lhs,rhs);
90
+ }
91
+ inline Condition condNeg(const Condition& cond)
92
+ {
93
+ return Condition::NEG(cond);
94
+ }
95
+ inline Condition getTrueCond() const
96
+ {
97
+ return Condition::getTrueCond();
98
+ }
99
+ inline Condition getFalseCond() const
100
+ {
101
+ return Condition::getFalseCond();
102
+ }
103
+ /// Iterator every element of the condition
104
+ inline NodeBS exactCondElem(const Condition& cond)
105
+ {
106
+ NodeBS elems;
107
+ extractSubConds(cond, elems);
108
+ return elems;
109
+ }
110
+
111
+ inline std::string dumpCond(const Condition& cond) const
112
+ {
113
+ return Condition::dumpStr(cond);
114
+ }
115
+
116
+ /// Allocate a new condition
117
+ Condition newCond(const Instruction* inst);
118
+
119
+ /// Perform path allocation
120
+ void allocate(const SVFModule* module);
121
+
122
+ /// Get/Set instruction based on Z3 expression id
123
+ //{@
124
+ inline const Instruction *getCondInst(u32_t id) const
125
+ {
126
+ IndexToTermInstMap::const_iterator it = idToTermInstMap.find(id);
127
+ assert(it != idToTermInstMap.end() && "this should be a fresh condition");
128
+ return it->second;
129
+ }
130
+
131
+ inline void setCondInst(const Condition &condition, const Instruction *inst)
132
+ {
133
+ assert(idToTermInstMap.find(condition.id()) == idToTermInstMap.end() && "this should be a fresh condition");
134
+ idToTermInstMap[condition.id()] = inst;
135
+ }
136
+ //@}
137
+
138
+ bool isNegCond(u32_t id) const
139
+ {
140
+ return negConds.test(id);
141
+ }
142
+
143
+ /// Get dominators
144
+ inline DominatorTree* getDT(const Function* fun)
145
+ {
146
+ return cfInfoBuilder.getDT(fun);
147
+ }
148
+ /// Get Postdominators
149
+ inline PostDominatorTree* getPostDT(const Function* fun)
150
+ {
151
+ return cfInfoBuilder.getPostDT(fun);
152
+ }
153
+ /// Get LoopInfo
154
+ inline LoopInfo* getLoopInfo(const Function* f)
155
+ {
156
+ return cfInfoBuilder.getLoopInfo(f);
157
+ }
158
+
159
+
160
+ /// Guard Computation for a value-flow (between two basic blocks)
161
+ //@{
162
+ virtual Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst);
163
+ virtual Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB);
164
+ virtual Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB);
165
+
166
+ /// Get complement condition (from B1 to B0) according to a complementBB (BB2) at a phi
167
+ /// e.g., B0: dstBB; B1:incomingBB; B2:complementBB
168
+ virtual Condition getPHIComplementCond(const BasicBlock* BB1, const BasicBlock* BB2, const BasicBlock* BB0);
169
+
170
+ inline void clearCFCond()
171
+ {
172
+ bbToCondMap.clear();
173
+ }
174
+ /// Set current value for branch condition evaluation
175
+ inline void setCurEvalSVFGNode(const SVFGNode* node)
176
+ {
177
+ curEvalSVFGNode = node;
178
+ }
179
+ /// Get current value for branch condition evaluation
180
+ inline const SVFGNode* getCurEvalSVFGNode() const
181
+ {
182
+ return curEvalSVFGNode;
183
+ }
184
+ //@}
185
+
186
+ /// Print out the path condition information
187
+ void printPathCond();
188
+
189
+ /// whether condition is satisfiable
190
+ bool isSatisfiable(const Condition& condition);
191
+
192
+ /// whether condition is satisfiable for all possible boolean guards
193
+ inline bool isAllPathReachable(Condition& condition)
194
+ {
195
+ return isEquivalentBranchCond(condition, Condition::getTrueCond());
196
+ }
197
+
198
+ /// Whether lhs and rhs are equivalent branch conditions
199
+ bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const;
200
+
201
+ inline ICFG* getICFG() const
202
+ {
203
+ return PAG::getPAG()->getICFG();
204
+ }
205
+
206
+ /// Get/Set control-flow conditions
207
+ //@{
208
+ inline bool setCFCond(const BasicBlock* bb, const Condition& cond)
209
+ {
210
+ BBToCondMap::iterator it = bbToCondMap.find(bb);
211
+ // until a fixed-point is reached (condition is not changed)
212
+ if(it!=bbToCondMap.end() && isEquivalentBranchCond(it->second, cond))
213
+ return false;
214
+
215
+ bbToCondMap[bb] = cond;
216
+ return true;
217
+ }
218
+ inline Condition getCFCond(const BasicBlock* bb) const
219
+ {
220
+ BBToCondMap::const_iterator it = bbToCondMap.find(bb);
221
+ if(it==bbToCondMap.end())
222
+ {
223
+ return getFalseCond();
224
+ }
225
+ return it->second;
226
+ }
227
+ //@}
228
+
229
+
230
+ /// mark neg Z3 expression
231
+ inline void setNegCondInst(const Condition &condition, const Instruction *inst)
232
+ {
233
+ setCondInst(condition, inst);
234
+ negConds.set(condition.id());
235
+ }
236
+ private:
237
+
238
+ /// Allocate path condition for every basic block
239
+ virtual void allocateForBB(const BasicBlock& bb);
240
+
241
+ /// Get/Set a branch condition, and its terminator instruction
242
+ //@{
243
+ /// Set branch condition
244
+ void setBranchCond(const BasicBlock *bb, const BasicBlock *succ, const Condition& cond);
245
+ /// Get branch condition
246
+ Condition getBranchCond(const BasicBlock * bb, const BasicBlock *succ) const;
247
+ ///Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
248
+ Condition getEvalBrCond(const BasicBlock * bb, const BasicBlock *succ);
249
+ //@}
250
+ /// Evaluate branch conditions
251
+ //@{
252
+ /// Evaluate the branch condtion
253
+ Condition evaluateBranchCond(const BasicBlock * bb, const BasicBlock *succ) ;
254
+ /// Evaluate loop exit branch
255
+ Condition evaluateLoopExitBranch(const BasicBlock * bb, const BasicBlock *succ);
256
+ /// Return branch condition after evaluating test null like expression
257
+ Condition evaluateTestNullLikeExpr(const BranchStmt* branchStmt, const BasicBlock *succ);
258
+ /// Return condition when there is a branch calls program exit
259
+ Condition evaluateProgExit(const BranchStmt* branchStmt, const BasicBlock *succ);
260
+ /// Collect basic block contains program exit function call
261
+ void collectBBCallingProgExit(const BasicBlock& bb);
262
+ bool isBBCallsProgExit(const BasicBlock* bb);
263
+ //@}
264
+
265
+ /// Evaluate test null/not null like expressions
266
+ //@{
267
+ /// Return true if the predicate of this compare instruction is equal
268
+ bool isEQCmp(const CmpInst* cmp) const;
269
+ /// Return true if the predicate of this compare instruction is not equal
270
+ bool isNECmp(const CmpInst* cmp) const;
271
+ /// Return true if this is a test null expression
272
+ bool isTestNullExpr(const Value* test) const;
273
+ /// Return true if this is a test not null expression
274
+ bool isTestNotNullExpr(const Value* test) const;
275
+ /// Return true if two values on the predicate are what we want
276
+ bool isTestContainsNullAndTheValue(const CmpInst* cmp) const;
277
+ //@}
278
+
279
+ /// Release memory
280
+ void destroy()
281
+ {
282
+
283
+ }
284
+
285
+ /// extract subexpression from a Z3 expression
286
+ void extractSubConds(const Condition &condition, NodeBS &support) const;
287
+
288
+
289
+ PTACFInfoBuilder cfInfoBuilder; ///< map a function to its loop info
290
+ FunToExitBBsMap funToExitBBsMap; ///< map a function to all its basic blocks calling program exit
291
+ BBToCondMap bbToCondMap; ///< map a basic block to its path condition starting from root
292
+ const SVFGNode* curEvalSVFGNode{}; ///< current llvm value to evaluate branch condition when computing guards
293
+ IndexToTermInstMap idToTermInstMap; ///key: z3 expression id, value: instruction
294
+ NodeBS negConds; ///bit vector for distinguish neg
295
+ std::vector<Condition> conditionVec; /// vector storing z3expression
296
+ static u32_t totalCondNum; /// a counter for fresh condition
297
+
298
+ protected:
299
+ BBCondMap bbConds; ///< map basic block to its successors/predecessors branch conditions
300
+
301
+ };
302
+
303
+ } // End namespace SVF
304
+
305
+ #endif /* PATHALLOCATOR_H_ */
@@ -62,7 +62,7 @@ private:
62
62
  ProgSlice* _curSlice; /// current program slice
63
63
  SVFGNodeSet sources; /// source nodes
64
64
  SVFGNodeSet sinks; /// source nodes
65
- PathCondAllocator* pathCondAllocator;
65
+ SaberCondAllocator* saberCondAllocator;
66
66
  SVFGNodeToDPItemsMap nodeToDPItemsMap; ///< record forward visited dpitems
67
67
  SVFGNodeSet visitedSet; ///< record backward visited nodes
68
68
 
@@ -76,7 +76,7 @@ public:
76
76
  /// Constructor
77
77
  SrcSnkDDA() : _curSlice(nullptr), svfg(nullptr), ptaCallGraph(nullptr)
78
78
  {
79
- pathCondAllocator = new PathCondAllocator();
79
+ saberCondAllocator = new SaberCondAllocator();
80
80
  }
81
81
  /// Destructor
82
82
  virtual ~SrcSnkDDA()
@@ -232,10 +232,10 @@ public:
232
232
  }
233
233
  //@}
234
234
 
235
- /// Get path condition allocator
236
- PathCondAllocator* getPathAllocator() const
235
+ /// Get saber condition allocator
236
+ SaberCondAllocator* getSaberCondAllocator() const
237
237
  {
238
- return pathCondAllocator;
238
+ return saberCondAllocator;
239
239
  }
240
240
 
241
241
  protected:
@@ -307,7 +307,7 @@ protected:
307
307
  //@{
308
308
  void dumpSlices();
309
309
  void annotateSlice(ProgSlice* slice);
310
- void printBDDStat();
310
+ void printZ3Stat();
311
311
  //@}
312
312
 
313
313
  };
@@ -30,7 +30,6 @@
30
30
  #ifndef DPITEM_H_
31
31
  #define DPITEM_H_
32
32
 
33
- #include "Util/BDDExpr.h"
34
33
  #include "MemoryModel/ConditionalPT.h"
35
34
  #include <algorithm> // std::sort
36
35
 
@@ -218,9 +218,9 @@ public:
218
218
  static const llvm::cl::opt<bool> SymTabPrint;
219
219
 
220
220
  // Conditions.cpp
221
- static const llvm::cl::opt<unsigned> MaxBddSize;
221
+ static const llvm::cl::opt<unsigned> MaxZ3Size;
222
222
 
223
- // PathCondAllocator.cpp
223
+ // SaberCondAllocator.cpp
224
224
  static const llvm::cl::opt<bool> PrintPathCond;
225
225
 
226
226
  // SVFUtil.cpp
@@ -39,6 +39,7 @@ class Z3Expr
39
39
  {
40
40
  public:
41
41
  static z3::context *ctx;
42
+ static std::unique_ptr<z3::solver> solver;
42
43
 
43
44
  private:
44
45
  z3::expr e;
@@ -80,22 +81,15 @@ public:
80
81
  return e;
81
82
  }
82
83
 
84
+ /// Get z3 solver, singleton design here to make sure we only have one context
85
+ static z3::solver &getSolver();
86
+
83
87
  /// Get z3 context, singleton design here to make sure we only have one context
84
- static z3::context &getContext()
85
- {
86
- if (ctx == nullptr)
87
- {
88
- ctx = new z3::context();
89
- }
90
- return *ctx;
91
- }
88
+ static z3::context &getContext();
92
89
 
93
90
  /// release z3 context
94
- static void releaseContext()
95
- {
96
- delete ctx;
97
- ctx = nullptr;
98
- }
91
+ static void releaseContext();
92
+
99
93
 
100
94
  /// null expression
101
95
  static z3::expr nullExpr()
@@ -109,6 +103,12 @@ public:
109
103
  return e.id();
110
104
  }
111
105
 
106
+ /// get hash id
107
+ inline u32_t hash() const
108
+ {
109
+ return e.hash();
110
+ }
111
+
112
112
  inline const std::string to_string() const
113
113
  {
114
114
  return e.to_string();
@@ -245,7 +245,7 @@ public:
245
245
  return !lhs.getExpr();
246
246
  }
247
247
 
248
- friend Z3Expr ite(const Z3Expr& cond, const Z3Expr& lhs, const Z3Expr& rhs)
248
+ friend Z3Expr ite(const Z3Expr &cond, const Z3Expr &lhs, const Z3Expr &rhs)
249
249
  {
250
250
  return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
251
251
  }
@@ -266,6 +266,38 @@ public:
266
266
  return getExpr().get_sort();
267
267
  }
268
268
  //%}
269
+
270
+ /// output Z3 expression as a string
271
+ static std::string dumpStr(const Z3Expr &z3Expr);
272
+
273
+
274
+ /// get the number of subexpression of a Z3 expression
275
+ static u32_t getExprSize(const Z3Expr &z3Expr);
276
+
277
+ /// Return the unique true condition
278
+ static inline Z3Expr getTrueCond()
279
+ {
280
+ return getContext().bool_val(true);
281
+ }
282
+
283
+
284
+ /// Return the unique false condition
285
+ static inline Z3Expr getFalseCond()
286
+ {
287
+ return getContext().bool_val(false);
288
+ }
289
+
290
+ /// compute NEG
291
+ static inline Z3Expr NEG(const Z3Expr &z3Expr)
292
+ {
293
+ return !z3Expr;
294
+ }
295
+
296
+ /// compute AND, used for branch condition
297
+ static Z3Expr AND(const Z3Expr &lhs, const Z3Expr &rhs);
298
+
299
+ /// compute OR, used for branch condition
300
+ static Z3Expr OR(const Z3Expr &lhs, const Z3Expr &rhs);
269
301
  };
270
302
  }
271
303
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-lib",
3
- "version": "1.0.1111",
3
+ "version": "1.0.1114",
4
4
  "description": "SVF's npm support",
5
5
  "main": "index.js",
6
6
  "scripts": {