svf-lib 1.0.2539 → 1.0.2541

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.
Binary file
@@ -74,22 +74,8 @@ public:
74
74
 
75
75
  virtual ~AbstractState() = default;
76
76
 
77
- // getGepObjAddrs
78
- AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset);
79
-
80
77
  // initObjVar
81
78
  void initObjVar(const ObjVar* objVar);
82
- // getElementIndex
83
- IntervalValue getElementIndex(const GepStmt* gep);
84
- // getByteOffset
85
- IntervalValue getByteOffset(const GepStmt* gep);
86
- // printAbstractState
87
- // loadValue
88
- AbstractValue loadValue(NodeID varId);
89
- // storeValue
90
- void storeValue(NodeID varId, AbstractValue val);
91
-
92
- u32_t getAllocaInstByteSize(const AddrStmt *addr);
93
79
 
94
80
 
95
81
  /// The physical address starts with 0x7f...... + idx
@@ -275,6 +261,14 @@ public:
275
261
  /// domain join with other, important! other widen this.
276
262
  void joinWith(const AbstractState&other);
277
263
 
264
+
265
+ /// Replace address-taken (ObjVar) state with other's, preserving ValVar state.
266
+ void updateAddrStateOnly(const AbstractState& other)
267
+ {
268
+ _addrToAbsVal = other._addrToAbsVal;
269
+ _freedAddrs = other._freedAddrs;
270
+ }
271
+
278
272
  /// domain meet with other, important! other widen this.
279
273
  void meetWith(const AbstractState&other);
280
274
 
@@ -289,15 +283,6 @@ public:
289
283
  }
290
284
 
291
285
 
292
- /**
293
- * if this NodeID in SVFIR is a pointer, get the pointee type
294
- * e.g arr = (int*) malloc(10*sizeof(int))
295
- * getPointeeType(arr) -> return int
296
- * we can set arr[0]='c', arr[1]='c', arr[2]='\0'
297
- * @param call callnode of memset like api
298
- */
299
- const SVFType* getPointeeElement(NodeID id);
300
-
301
286
  void printAbstractState() const;
302
287
 
303
288
  std::string toString() const;
@@ -363,6 +348,16 @@ public:
363
348
  _freedAddrs.clear();
364
349
  }
365
350
 
351
+ /// Drop all top-level variables (ValVars), keeping ObjVar storage and
352
+ /// freed addresses intact. Used when building a cycle snapshot so the
353
+ /// ValVar set is controlled by the caller rather than whatever was
354
+ /// cached at the seed node.
355
+ void clearVars()
356
+ {
357
+ _varToAbsVal.clear();
358
+ }
359
+
360
+
366
361
  };
367
362
 
368
363
  }
@@ -174,11 +174,12 @@ public:
174
174
  return _addrs.count(id);
175
175
  }
176
176
 
177
- bool hasIntersect(const AddressValue &other)
177
+ bool hasIntersect(const AddressValue &other) const
178
178
  {
179
- AddressValue v = *this;
180
- v.meet_with(other);
181
- return !v.empty();
179
+ for (const auto& addr : _addrs)
180
+ if (other._addrs.count(addr))
181
+ return true;
182
+ return false;
182
183
  }
183
184
 
184
185
  inline bool isBottom() const
@@ -32,6 +32,10 @@
32
32
 
33
33
  namespace SVF
34
34
  {
35
+
36
+ class AbstractInterpretation;
37
+ class AbstractStateManager;
38
+
35
39
  /**
36
40
  * @class AEDetector
37
41
  * @brief Base class for all detectors.
@@ -75,7 +79,7 @@ public:
75
79
  * @param as Reference to the abstract state.
76
80
  * @param node Pointer to the ICFG node.
77
81
  */
78
- virtual void detect(AbstractState& as, const ICFGNode* node) = 0;
82
+ virtual void detect(const ICFGNode* node) = 0;
79
83
 
80
84
  /**
81
85
  * @brief Pure virtual function for handling stub external API calls. (e.g. UNSAFE_BUFACCESS)
@@ -167,7 +171,7 @@ public:
167
171
  * @param objAddrs Address value for the object.
168
172
  * @param offset The interval value of the offset.
169
173
  */
170
- void updateGepObjOffsetFromBase(AbstractState& as,
174
+ void updateGepObjOffsetFromBase(const ICFGNode* node,
171
175
  AddressValue gepAddrs,
172
176
  AddressValue objAddrs,
173
177
  IntervalValue offset);
@@ -177,14 +181,14 @@ public:
177
181
  * @param as Reference to the abstract state.
178
182
  * @param node Pointer to the ICFG node.
179
183
  */
180
- void detect(AbstractState& as, const ICFGNode*);
184
+ void detect(const ICFGNode*) override;
181
185
 
182
186
 
183
187
  /**
184
188
  * @brief Handles external API calls related to buffer overflow detection.
185
189
  * @param call Pointer to the call ICFG node.
186
190
  */
187
- void handleStubFunctions(const CallICFGNode*);
191
+ void handleStubFunctions(const CallICFGNode*) override;
188
192
 
189
193
  /**
190
194
  * @brief Adds an offset to a GEP object.
@@ -229,7 +233,7 @@ public:
229
233
  * @param gep Pointer to the GEP statement.
230
234
  * @return The interval value of the access offset.
231
235
  */
232
- IntervalValue getAccessOffset(AbstractState& as, NodeID objId, const GepStmt* gep);
236
+ IntervalValue getAccessOffset(NodeID objId, const GepStmt* gep);
233
237
 
234
238
  /**
235
239
  * @brief Adds a bug to the reporter based on an exception.
@@ -268,7 +272,7 @@ public:
268
272
  /**
269
273
  * @brief Reports all detected buffer overflow bugs.
270
274
  */
271
- void reportBug()
275
+ void reportBug() override
272
276
  {
273
277
  if (!nodeToBugInfo.empty())
274
278
  {
@@ -292,33 +296,31 @@ public:
292
296
  * @param as Reference to the abstract state.
293
297
  * @param call Pointer to the call ICFG node.
294
298
  */
295
- void detectExtAPI(AbstractState& as, const CallICFGNode *call);
299
+ void detectExtAPI(const CallICFGNode *call);
296
300
 
297
301
  /**
298
302
  * @brief Checks if memory can be safely accessed.
299
- * @param as Reference to the abstract state.
300
303
  * @param value Pointer to the SVF var.
301
304
  * @param len The interval value representing the length of the memory access.
305
+ * @param node The ICFG node providing context.
302
306
  * @return True if the memory access is safe, false otherwise.
303
307
  */
304
- bool canSafelyAccessMemory(AbstractState& as, const SVFVar *value, const IntervalValue &len);
308
+ bool canSafelyAccessMemory(const ValVar *value, const IntervalValue &len, const ICFGNode* node);
305
309
 
306
310
  private:
307
311
  /**
308
312
  * @brief Detects buffer overflow in 'strcat' function calls.
309
- * @param as Reference to the abstract state.
310
313
  * @param call Pointer to the call ICFG node.
311
314
  * @return True if a buffer overflow is detected, false otherwise.
312
315
  */
313
- bool detectStrcat(AbstractState& as, const CallICFGNode *call);
316
+ bool detectStrcat(const CallICFGNode *call);
314
317
 
315
318
  /**
316
319
  * @brief Detects buffer overflow in 'strcpy' function calls.
317
- * @param as Reference to the abstract state.
318
320
  * @param call Pointer to the call ICFG node.
319
321
  * @return True if a buffer overflow is detected, false otherwise.
320
322
  */
321
- bool detectStrcpy(AbstractState& as, const CallICFGNode *call);
323
+ bool detectStrcpy(const CallICFGNode *call);
322
324
 
323
325
  private:
324
326
  Map<const GepObjVar*, IntervalValue> gepObjOffsetFromBase; ///< Maps GEP objects to their offsets from the base.
@@ -348,13 +350,13 @@ public:
348
350
  * @param as Reference to the abstract state.
349
351
  * @param node Pointer to the ICFG node.
350
352
  */
351
- void detect(AbstractState& as, const ICFGNode* node);
353
+ void detect(const ICFGNode* node) override;
352
354
 
353
355
  /**
354
356
  * @brief Handles external API calls related to nullptr dereferences.
355
357
  * @param call Pointer to the call ICFG node.
356
358
  */
357
- void handleStubFunctions(const CallICFGNode* call);
359
+ void handleStubFunctions(const CallICFGNode* call) override;
358
360
 
359
361
  /**
360
362
  * @brief Checks if an Abstract Value is uninitialized.
@@ -401,7 +403,7 @@ public:
401
403
  /**
402
404
  * @brief Reports all detected nullptr dereference bugs.
403
405
  */
404
- void reportBug()
406
+ void reportBug() override
405
407
  {
406
408
  if (!nodeToBugInfo.empty())
407
409
  {
@@ -420,7 +422,7 @@ public:
420
422
  * @param as Reference to the abstract state.
421
423
  * @param call Pointer to the call ICFG node.
422
424
  */
423
- void detectExtAPI(AbstractState& as, const CallICFGNode* call);
425
+ void detectExtAPI(const CallICFGNode* call);
424
426
 
425
427
 
426
428
  /**
@@ -433,7 +435,7 @@ public:
433
435
  return !v.isAddr() && !v.isInterval();
434
436
  }
435
437
 
436
- bool canSafelyDerefPtr(AbstractState& as, const SVFVar* ptr);
438
+ bool canSafelyDerefPtr(const ValVar* ptr, const ICFGNode* node);
437
439
 
438
440
  private:
439
441
  Set<std::string> bugLoc; ///< Set of locations where bugs have been reported.
@@ -33,8 +33,8 @@
33
33
  namespace SVF
34
34
  {
35
35
 
36
- // Forward declaration of AbstractInterpretation class
37
36
  class AbstractInterpretation;
37
+ class AbstractStateManager;
38
38
 
39
39
  /**
40
40
  * @class AbsExtAPI
@@ -51,9 +51,9 @@ public:
51
51
 
52
52
  /**
53
53
  * @brief Constructor for AbsExtAPI.
54
- * @param abstractTrace Reference to a map of ICFG nodes to abstract states.
54
+ * @param ae Reference to the AbstractInterpretation instance.
55
55
  */
56
- AbsExtAPI(Map<const ICFGNode*, AbstractState>& traces);
56
+ AbsExtAPI(AbstractStateManager* mgr);
57
57
 
58
58
  /**
59
59
  * @brief Initializes the external function map.
@@ -66,7 +66,7 @@ public:
66
66
  * @param rhs Pointer to the SVF variable representing the string.
67
67
  * @return The string value.
68
68
  */
69
- std::string strRead(AbstractState& as, const SVFVar* rhs);
69
+ std::string strRead(const ValVar* rhs, const ICFGNode* node);
70
70
 
71
71
  /**
72
72
  * @brief Handles an external API call.
@@ -77,21 +77,21 @@ public:
77
77
  // --- Shared primitives used by string/memory handlers ---
78
78
 
79
79
  /// Get the byte size of each element for a pointer/array variable.
80
- u32_t getElementSize(AbstractState& as, const SVFVar* var);
80
+ u32_t getElementSize(const ValVar* var);
81
81
 
82
82
  /// Check if an interval length is usable (not bottom, not unbounded).
83
83
  static bool isValidLength(const IntervalValue& len);
84
84
 
85
85
  /// Calculate the length of a null-terminated string in abstract state.
86
- IntervalValue getStrlen(AbstractState& as, const SVF::SVFVar *strValue);
86
+ IntervalValue getStrlen(const ValVar *strValue, const ICFGNode* node);
87
87
 
88
88
  // --- String/memory operation handlers ---
89
89
 
90
90
  void handleStrcpy(const CallICFGNode *call);
91
91
  void handleStrcat(const CallICFGNode *call);
92
92
  void handleStrncat(const CallICFGNode *call);
93
- void handleMemcpy(AbstractState& as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx);
94
- void handleMemset(AbstractState& as, const SVFVar* dst, IntervalValue elem, IntervalValue len);
93
+ void handleMemcpy(const ValVar *dst, const ValVar *src, const IntervalValue& len, u32_t start_idx, const ICFGNode* node);
94
+ void handleMemset(const ValVar* dst, const IntervalValue& elem, const IntervalValue& len, const ICFGNode* node);
95
95
 
96
96
  /**
97
97
  * @brief Gets the range limit from a type.
@@ -114,9 +114,9 @@ public:
114
114
  Set<const CallICFGNode*> checkpoints; // for CI check
115
115
 
116
116
  protected:
117
+ AbstractStateManager* mgr; ///< Pointer to the state manager.
117
118
  SVFIR* svfir; ///< Pointer to the SVF intermediate representation.
118
119
  ICFG* icfg; ///< Pointer to the interprocedural control flow graph.
119
- Map<const ICFGNode*, AbstractState>& abstractTrace; ///< Map of ICFG nodes to abstract states.
120
120
  Map<std::string, std::function<void(const CallICFGNode*)>> func_map; ///< Map of function names to handlers.
121
121
  };
122
122
 
@@ -31,6 +31,7 @@
31
31
  #pragma once
32
32
  #include "AE/Core/AbstractState.h"
33
33
  #include "AE/Core/ICFGWTO.h"
34
+ #include "AE/Svfexe/AbstractStateManager.h"
34
35
  #include "AE/Svfexe/AEDetector.h"
35
36
  #include "AE/Svfexe/PreAnalysis.h"
36
37
  #include "AE/Svfexe/AbsExtAPI.h"
@@ -73,6 +74,13 @@ public:
73
74
  * if set WIDEN_ONLY, result = [10000, +oo] since only widening is applied at the cycle head of recursive functions without narrowing.
74
75
  * if set WIDEN_NARROW, result = [10000, 10000] since both widening and narrowing are applied at the cycle head of recursive functions.
75
76
  * */
77
+ enum AESparsity
78
+ {
79
+ Dense,
80
+ SemiSparse,
81
+ Sparse
82
+ };
83
+
76
84
  enum HandleRecur
77
85
  {
78
86
  TOP,
@@ -115,43 +123,45 @@ public:
115
123
  return svfir->getSVFVar(varId);
116
124
  }
117
125
 
118
- /// Retrieve abstract value for a top-level variable at a given ICFG node
119
- const AbstractValue& getAbstractValue(const ValVar* var);
126
+ /// Get the state manager instance.
127
+ AbstractStateManager* getStateMgr()
128
+ {
129
+ return svfStateMgr;
130
+ }
120
131
 
121
- /// Retrieve abstract value for an address-taken variable at a given ICFG node
122
- const AbstractValue& getAbstractValue(const ICFGNode* node, const ObjVar* var);
132
+ // ---------------------------------------------------------------
133
+ // Convenience wrappers around AbstractStateManager
134
+ // ---------------------------------------------------------------
135
+ /// Read-only access to a node's AbstractState. Mutations must go through
136
+ /// updateAbsState (to replace) or updateAbsValue (to update one variable).
137
+ inline const AbstractState& getAbsState(const ICFGNode* node) const
138
+ {
139
+ return svfStateMgr->getAbstractState(node);
140
+ }
123
141
 
124
- /// Retrieve abstract value for any SVF variable at a given ICFG node
125
- const AbstractValue& getAbstractValue(const ICFGNode* node, const SVFVar* var);
142
+ inline bool hasAbsState(const ICFGNode* node)
143
+ {
144
+ return svfStateMgr->hasAbstractState(node);
145
+ }
126
146
 
127
- /// Set abstract value for a top-level variable at a given ICFG node
128
- void updateAbstractValue(const ValVar* var, const AbstractValue& val);
147
+ inline void updateAbsState(const ICFGNode* node, const AbstractState& state)
148
+ {
149
+ svfStateMgr->updateAbstractState(node, state);
150
+ }
129
151
 
130
- /// Set abstract value for an address-taken variable at a given ICFG node
131
- void updateAbstractValue(const ICFGNode* node, const ObjVar* var, const AbstractValue& val);
152
+ inline const AbstractValue& getAbsValue(const SVFVar* var, const ICFGNode* node)
153
+ {
154
+ return svfStateMgr->getAbstractValue(var, node);
155
+ }
132
156
 
133
- /// Set abstract value for any SVF variable at a given ICFG node
134
- void updateAbstractValue(const ICFGNode* node, const SVFVar* var, const AbstractValue& val);
157
+ inline void updateAbsValue(const SVFVar* var, const AbstractValue& val, const ICFGNode* node)
158
+ {
159
+ svfStateMgr->updateAbstractValue(var, val, node);
160
+ }
135
161
 
136
- /// Propagate an ObjVar's abstract value from defSite to all its use-site ICFGNodes via SVFG
162
+ /// Propagate an ObjVar's abstract value from defSite to all its use-sites.
137
163
  void propagateObjVarAbsVal(const ObjVar* var, const ICFGNode* defSite);
138
164
 
139
- /// Retrieve the abstract state from the trace for a given ICFG node; asserts if no trace exists
140
- AbstractState& getAbstractState(const ICFGNode* node);
141
-
142
- /// Check if an abstract state exists in the trace for a given ICFG node
143
- bool hasAbstractState(const ICFGNode* node);
144
-
145
- /// Retrieve abstract state filtered to specific top-level variables
146
- void getAbstractState(const ICFGNode* node, const Set<const ValVar*>& vars, AbstractState& result);
147
-
148
- /// Retrieve abstract state filtered to specific address-taken variables
149
- void getAbstractState(const ICFGNode* node, const Set<const ObjVar*>& vars, AbstractState& result);
150
-
151
- /// Retrieve abstract state filtered to specific SVF variables
152
- void getAbstractState(const ICFGNode* node, const Set<const SVFVar*>& vars, AbstractState& result);
153
-
154
-
155
165
  private:
156
166
  /// Initialize abstract state for the global ICFG node and process global statements
157
167
  virtual void handleGlobalNode();
@@ -161,8 +171,8 @@ private:
161
171
  /// abstractTrace[node]. Returns true if at least one predecessor had state.
162
172
  bool mergeStatesFromPredecessors(const ICFGNode* node);
163
173
 
164
- /// Check if the branch on intraEdge is feasible under abstract state as
165
- bool isBranchFeasible(const IntraCFGEdge* intraEdge, AbstractState& as);
174
+ /// Returns true if the branch is reachable; narrows as in-place.
175
+ bool isBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
166
176
 
167
177
  /// Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling
168
178
  virtual void handleCallSite(const ICFGNode* node);
@@ -179,15 +189,11 @@ private:
179
189
  /// Dispatch an SVF statement (Addr/Binary/Cmp/Load/Store/Copy/Gep/Select/Phi/Call/Ret) to its handler
180
190
  virtual void handleSVFStatement(const SVFStmt* stmt);
181
191
 
182
- /// Set all store targets and return value to TOP for a recursive call node
183
- virtual void setTopToObjInRecursion(const CallICFGNode* callnode);
192
+ /// Returns true if the cmp-conditional branch is feasible; narrows as in-place.
193
+ bool isCmpBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
184
194
 
185
- /// Check if cmpStmt with successor value succ is feasible; refine intervals in as accordingly
186
- bool isCmpBranchFeasible(const CmpStmt* cmpStmt, s64_t succ,
187
- AbstractState& as);
188
-
189
- /// Check if switch branch with case value succ is feasible; refine intervals in as accordingly
190
- bool isSwitchBranchFeasible(const SVFVar* var, s64_t succ, AbstractState& as);
195
+ /// Returns true if the switch branch is feasible; narrows as in-place.
196
+ bool isSwitchBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
191
197
 
192
198
  void updateStateOnAddr(const AddrStmt *addr);
193
199
 
@@ -211,7 +217,6 @@ private:
211
217
 
212
218
  void updateStateOnPhi(const PhiStmt *phi);
213
219
 
214
-
215
220
  /// protected data members, also used in subclasses
216
221
  SVFIR* svfir;
217
222
  /// Execution State, used to store the Interval Value of every SVF variable
@@ -232,7 +237,7 @@ private:
232
237
  virtual bool isExtCall(const CallICFGNode* callNode);
233
238
  virtual void handleExtCall(const CallICFGNode* callNode);
234
239
  virtual bool isRecursiveFun(const FunObjVar* fun);
235
- virtual void handleRecursiveCall(const CallICFGNode *callNode);
240
+ virtual void skipRecursionWithTop(const CallICFGNode *callNode);
236
241
  virtual bool isRecursiveCallSite(const CallICFGNode* callNode, const FunObjVar *);
237
242
  virtual void handleFunCall(const CallICFGNode* callNode);
238
243
 
@@ -243,60 +248,13 @@ private:
243
248
  // there data should be shared with subclasses
244
249
  Map<std::string, std::function<void(const CallICFGNode*)>> func_map;
245
250
 
246
- Map<const ICFGNode*, AbstractState> abstractTrace; // abstract states for nodes
251
+ AbstractStateManager* svfStateMgr{nullptr}; // state management (owns abstractTrace)
247
252
  Set<const ICFGNode*> allAnalyzedNodes; // All nodes ever analyzed (across all entry points)
248
253
  std::string moduleName;
249
254
 
250
255
  std::vector<std::unique_ptr<AEDetector>> detectors;
251
256
  AbsExtAPI* utils;
252
257
 
253
- // according to varieties of cmp insts,
254
- // maybe var X var, var X const, const X var, const X const
255
- // we accept 'var X const' 'var X var' 'const X const'
256
- // if 'const X var', we need to reverse op0 op1 and its predicate 'var X' const'
257
- // X' is reverse predicate of X
258
- // == -> !=, != -> ==, > -> <=, >= -> <, < -> >=, <= -> >
259
-
260
- Map<s32_t, s32_t> _reverse_predicate =
261
- {
262
- {CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_ONE}, // == -> !=
263
- {CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UNE}, // == -> !=
264
- {CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLE}, // > -> <=
265
- {CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLT}, // >= -> <
266
- {CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGE}, // < -> >=
267
- {CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGT}, // <= -> >
268
- {CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_OEQ}, // != -> ==
269
- {CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UEQ}, // != -> ==
270
- {CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_NE}, // == -> !=
271
- {CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_EQ}, // != -> ==
272
- {CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULE}, // > -> <=
273
- {CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGE}, // < -> >=
274
- {CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULT}, // >= -> <
275
- {CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLE}, // > -> <=
276
- {CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGE}, // < -> >=
277
- {CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLT}, // >= -> <
278
- };
279
-
280
-
281
- Map<s32_t, s32_t> _switch_lhsrhs_predicate =
282
- {
283
- {CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_OEQ}, // == -> ==
284
- {CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UEQ}, // == -> ==
285
- {CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLT}, // > -> <
286
- {CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLE}, // >= -> <=
287
- {CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGT}, // < -> >
288
- {CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGE}, // <= -> >=
289
- {CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_ONE}, // != -> !=
290
- {CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UNE}, // != -> !=
291
- {CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_EQ}, // == -> ==
292
- {CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_NE}, // != -> !=
293
- {CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULT}, // > -> <
294
- {CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGT}, // < -> >
295
- {CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULE}, // >= -> <=
296
- {CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLT}, // > -> <
297
- {CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGT}, // < -> >
298
- {CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLE}, // >= -> <=
299
- };
300
258
 
301
259
  };
302
260
  }