Static Value-Flow Analysis
Loading...
Searching...
No Matches
Functions
AbstractInterpretation.cpp File Reference
#include "AE/Svfexe/AbstractInterpretation.h"
#include "AE/Svfexe/SparseAbstractInterpretation.h"
#include "AE/Svfexe/AbsExtAPI.h"
#include "SVFIR/SVFIR.h"
#include "Util/Options.h"
#include "Util/WorkList.h"
#include "Graphs/CallGraph.h"
#include "WPA/Andersen.h"
#include <cmath>
#include <memory>

Go to the source code of this file.

Functions

static const LoadStmt * findBackingLoad (const SVFVar *var)
 
static IntervalValue computeCmpConstraint (s32_t predicate, s64_t succ, bool isLHS, const IntervalValue &self, const IntervalValue &other)
 

Function Documentation

◆ computeCmpConstraint()

static IntervalValue computeCmpConstraint ( s32_t  predicate,
s64_t  succ,
bool  isLHS,
const IntervalValue &  self,
const IntervalValue &  other 
)
static

Compute the interval constraint on one cmp operand given the predicate, branch direction (succ), which side it is on, and the other operand's interval. Returns top if no useful narrowing is possible.

Called from applyBranchRefinement for each non-constant operand that has a backing load. Given a branch condition like:

cmp = icmp sgt a, 5 ; a > 5 br i1 cmp, label T, F

On the true branch (succ=1), operand a (isLHS=true) is constrained to [6, +inf). On the false branch (succ=0), a is constrained to (-inf, 5]. The result is used to narrow the ObjVar behind a's load.

Definition at line 377 of file AbstractInterpretation.cpp.

380{
381 // Normalize: always reason from the LHS perspective.
382 // If we are the RHS operand, swap the predicate direction.
383 if (!isLHS)
384 {
385 // a > b from b's perspective: b < a
386 static const Map<s32_t, s32_t> swapPred =
387 {
410 };
411 auto it = swapPred.find(predicate);
412 if (it == swapPred.end()) return IntervalValue::top();
413 predicate = it->second;
414 }
415
416 // If false branch, negate the predicate.
417 if (succ == 0)
418 {
419 static const Map<s32_t, s32_t> negPred =
420 {
443 };
444 auto it = negPred.find(predicate);
445 if (it == negPred.end()) return IntervalValue::top();
446 predicate = it->second;
447 }
448
449 // Now compute the constraint on LHS given: LHS <predicate> other
451 switch (predicate)
452 {
453 case CmpStmt::ICMP_EQ:
456 result.meet_with(other);
457 break;
458 case CmpStmt::ICMP_NE:
463 return IntervalValue::top(); // no useful narrowing
468 result.meet_with(IntervalValue(other.lb() + 1, IntervalValue::plus_infinity()));
469 break;
475 break;
480 result.meet_with(IntervalValue(IntervalValue::minus_infinity(), other.ub() - 1));
481 break;
487 break;
488 default:
489 return IntervalValue::top();
490 }
491 return result;
492}
@ ICMP_SGT
signed greater than
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_UGE
unsigned greater or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_NE
not equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_ULT
unsigned less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ ICMP_SLT
signed less than
@ ICMP_UGT
unsigned greater than
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
static BoundedInt minus_infinity()
Get minus infinity -inf.
const BoundedInt & ub() const
Return the upper bound.
static BoundedInt plus_infinity()
Get plus infinity +inf.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ findBackingLoad()

static const LoadStmt * findBackingLoad ( const SVFVar *  var)
static

Given a cmp operand, walk its SSA def edge to find the LoadStmt that produced it. This lets us trace back to the ObjVar in memory so that branch narrowing can refine the stored value.

Example: for cmp = icmp sgt a, 5 where a = load i32, ptr p, calling findBackingLoad(a) returns the LoadStmt, and we can then narrow the ObjVar behind p.

Follows one level of CopyStmt (e.g., zext/sext) if the load is not directly on the cmp operand. Returns nullptr if no load is found.

Definition at line 348 of file AbstractInterpretation.cpp.

349{
350 if (var->getInEdges().empty())
351 return nullptr;
352 SVFStmt* inStmt = *var->getInEdges().begin();
353 if (const LoadStmt* ls = SVFUtil::dyn_cast<LoadStmt>(inStmt))
354 return ls;
355 if (const CopyStmt* cs = SVFUtil::dyn_cast<CopyStmt>(inStmt))
356 {
357 const SVFVar* src = cs->getRHSVar();
358 if (!src->getInEdges().empty())
359 return SVFUtil::dyn_cast<LoadStmt>(*src->getInEdges().begin());
360 }
361 return nullptr;
362}
const GEdgeSetTy & getInEdges() const