Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | List of all members
SVF::SemiSparseAbstractInterpretation Class Reference

#include <SparseAbstractInterpretation.h>

Inheritance diagram for SVF::SemiSparseAbstractInterpretation:
SVF::AbstractInterpretation SVF::FullSparseAbstractInterpretation

Public Member Functions

 SemiSparseAbstractInterpretation ()
 
 ~SemiSparseAbstractInterpretation () override=default
 
- Public Member Functions inherited from SVF::AbstractInterpretation
virtual void runOnModule ()
 
virtual ~AbstractInterpretation ()
 Destructor.
 
void analyse ()
 Program entry.
 
void analyzeFromAllProgEntries ()
 Analyze all entry points (functions without callers)
 
std::deque< const FunObjVar * > collectProgEntryFuns ()
 Get all entry point functions (functions without callers)
 
void addDetector (std::unique_ptr< AEDetector > detector)
 
const SVFVargetSVFVar (NodeID varId) const
 Retrieve SVFVar given its ID; asserts if no such variable exists.
 
AbstractStategetAbsState (const ICFGNode *node)
 
bool hasAbsState (const ICFGNode *node)
 
void getAbsState (const Set< const ValVar * > &vars, AbstractState &result, const ICFGNode *node)
 
void getAbsState (const Set< const ObjVar * > &vars, AbstractState &result, const ICFGNode *node)
 
void getAbsState (const Set< const SVFVar * > &vars, AbstractState &result, const ICFGNode *node)
 
IntervalValue getGepElementIndex (const GepStmt *gep)
 
IntervalValue getGepByteOffset (const GepStmt *gep)
 
AddressValue getGepObjAddrs (const ValVar *pointer, IntervalValue offset)
 
AbstractValue loadValue (const ValVar *pointer, const ICFGNode *node)
 
void storeValue (const ValVar *pointer, const AbstractValue &val, const ICFGNode *node)
 
const SVFTypegetPointeeElement (const ObjVar *var, const ICFGNode *node)
 
u32_t getAllocaInstByteSize (const AddrStmt *addr)
 
Map< const ICFGNode *, AbstractState > & getTrace ()
 
AbstractStateoperator[] (const ICFGNode *node)
 

Protected Member Functions

AbstractState getFullCycleHeadState (const ICFGCycleWTO *cycle) override
 
bool widenCycleState (const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle) override
 
bool narrowCycleState (const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle) override
 
const AbstractValuegetAbsValue (const ValVar *var, const ICFGNode *node) override
 
bool hasAbsValue (const ValVar *var, const ICFGNode *node) const override
 Side-effect-free existence check.
 
void updateAbsValue (const ValVar *var, const AbstractValue &val, const ICFGNode *node) override
 
void updateAbsState (const ICFGNode *node, const AbstractState &state) override
 
void joinStates (AbstractState &dst, const AbstractState &src) override
 
const ICFGNodegetICFGNode (const ValVar *var) const
 
virtual const AbstractValuegetAbsValue (const ValVar *var, const ICFGNode *node)
 
virtual const AbstractValuegetAbsValue (const ObjVar *var, const ICFGNode *node)
 
virtual const AbstractValuegetAbsValue (const SVFVar *var, const ICFGNode *node)
 
virtual bool hasAbsValue (const ValVar *var, const ICFGNode *node) const
 Side-effect-free existence check.
 
virtual bool hasAbsValue (const ObjVar *var, const ICFGNode *node) const
 
virtual bool hasAbsValue (const SVFVar *var, const ICFGNode *node) const
 
virtual void updateAbsValue (const ValVar *var, const AbstractValue &val, const ICFGNode *node)
 
virtual void updateAbsValue (const ObjVar *var, const AbstractValue &val, const ICFGNode *node)
 
virtual void updateAbsValue (const SVFVar *var, const AbstractValue &val, const ICFGNode *node)
 
- Protected Member Functions inherited from SVF::AbstractInterpretation
 AbstractInterpretation ()
 
bool shouldApplyNarrowing (const FunObjVar *fun)
 Check if narrowing should be applied: always for regular loops, mode-dependent for recursion.
 

Additional Inherited Members

- Public Types inherited from SVF::AbstractInterpretation
enum  AESparsity { Dense , SemiSparse , Sparse }
 
enum  HandleRecur { TOP , WIDEN_ONLY , WIDEN_NARROW }
 
- Static Public Member Functions inherited from SVF::AbstractInterpretation
static AbstractInterpretationgetAEInstance ()
 
- Protected Attributes inherited from SVF::AbstractInterpretation
SVFIRsvfir {nullptr}
 Data and helpers reachable from SparseAbstractInterpretation.
 
AEWTOpreAnalysis {nullptr}
 
Map< const ICFGNode *, AbstractStateabstractTrace
 per-node trace; owned here
 

Detailed Description

Abstract Interpretation for Options::AESparsity::SemiSparse.

ValVars live at their SVFG-style def-sites: reads pull from there, writes go there, state merges replace only the ObjVar map and skip the ValVar map, and the cycle helpers gather/scatter cycle ValVars around each widening iteration.

Definition at line 39 of file SparseAbstractInterpretation.h.

Constructor & Destructor Documentation

◆ SemiSparseAbstractInterpretation()

SVF::SemiSparseAbstractInterpretation::SemiSparseAbstractInterpretation ( )
inline

Definition at line 42 of file SparseAbstractInterpretation.h.

◆ ~SemiSparseAbstractInterpretation()

SVF::SemiSparseAbstractInterpretation::~SemiSparseAbstractInterpretation ( )
overridedefault

Member Function Documentation

◆ getAbsValue() [1/4]

const AbstractValue & AbstractInterpretation::getAbsValue ( const ObjVar var,
const ICFGNode node 
)
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 137 of file AbstractStateManager.cpp.

91{
94 return as.load(addr);
95}
unsigned u32_t
Definition CommandLine.h:18
AbstractState & getAbsState(const ICFGNode *node)
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ getAbsValue() [2/4]

const AbstractValue & AbstractInterpretation::getAbsValue ( const SVFVar var,
const ICFGNode node 
)
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 138 of file AbstractStateManager.cpp.

98{
99 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
100 return getAbsValue(objVar, node);
101 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
102 return getAbsValue(valVar, node);
103 assert(false && "Unknown SVFVar kind");
104 abort();
105}
const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node) override

◆ getAbsValue() [3/4]

const AbstractValue & AbstractInterpretation::getAbsValue ( const ValVar var,
const ICFGNode node 
)
protectedvirtual

Read a top-level variable's abstract value. Dense base does a direct trace lookup; sparse subclasses override with their own resolution chain (def-site walk, call-result fallback, etc.). All three overloads are virtual so full-sparse can route ObjVar reads through the SVFG.

Dense base: direct trace lookup, with a top sentinel for genuinely missing entries (e.g. function parameters like argc, never written before first read). Sparse subclasses override with a def-site resolution chain.

The "in map" check is a raw map.count — NOT inVarToValTable / inVarToAddrsTable, which gate on isInterval / isAddr. SVF canonically represents uninit and null-pointer shapes as (interval=bottom ∧ addrs=∅); those predicates would falsely report such an entry as "not present", and the top fallback below would then clobber the very signal NullptrDerefDetector::isUninit keys off.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 136 of file AbstractStateManager.cpp.

81{
82 u32_t id = var->getId();
84 if (as.getVarToVal().count(id))
85 return as[id];
86 as[id] = IntervalValue::top();
87 return as[id];
88}
Map< const ICFGNode *, AbstractState > abstractTrace
per-node trace; owned here
static IntervalValue top()
Create the IntervalValue [-inf, +inf].

◆ getAbsValue() [4/4]

const AbstractValue & SemiSparseAbstractInterpretation::getAbsValue ( const ValVar var,
const ICFGNode node 
)
overrideprotectedvirtual

Read a top-level variable's abstract value. Dense base does a direct trace lookup; sparse subclasses override with their own resolution chain (def-site walk, call-result fallback, etc.). All three overloads are virtual so full-sparse can route ObjVar reads through the SVFG.

Dense base: direct trace lookup, with a top sentinel for genuinely missing entries (e.g. function parameters like argc, never written before first read). Sparse subclasses override with a def-site resolution chain.

The "in map" check is a raw map.count — NOT inVarToValTable / inVarToAddrsTable, which gate on isInterval / isAddr. SVF canonically represents uninit and null-pointer shapes as (interval=bottom ∧ addrs=∅); those predicates would falsely report such an entry as "not present", and the top fallback below would then clobber the very signal NullptrDerefDetector::isUninit keys off.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 447 of file AbstractStateManager.cpp.

449{
451}
virtual const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node)
const ICFGNode * getICFGNode(const ValVar *var) const

◆ getFullCycleHeadState()

AbstractState SemiSparseAbstractInterpretation::getFullCycleHeadState ( const ICFGCycleWTO cycle)
overrideprotectedvirtual

Build a full cycle-head AbstractState. Dense default: trace[cycle_head] as-is. Semi-sparse subclass: also pull cycle ValVars from def-sites.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 129 of file SparseAbstractInterpretation.cpp.

131{
132 // Start from the dense snapshot (ObjVars + any ValVars that happen to
133 // be cached at cycle_head's trace entry).
135
137 if (valVars.empty())
138 return snap; // no cycle ValVars known: nothing to pull
139
140 // Drop stale ValVar entries and pull each cycle ValVar from its
141 // def-site. ValVars without a genuine stored value are skipped to
142 // avoid getAbsValue's top-fallback contaminating body def-sites on
143 // the subsequent widen/narrow scatter.
144 snap.clearValVars();
145 for (const ValVar* v : valVars)
146 {
147 const ICFGNode* defSite = v->getICFGNode();
148 if (!defSite || !hasAbsValue(v, defSite))
149 continue;
150 snap[v->getId()] = getAbsValue(v, defSite);
151 }
152 return snap;
153}
const Set< const ValVar * > getCycleValVars(const ICFGCycleWTO *cycle) const
Definition AEWTO.h:83
virtual AbstractState getFullCycleHeadState(const ICFGCycleWTO *cycle)
bool hasAbsValue(const ValVar *var, const ICFGNode *node) const override
Side-effect-free existence check.

◆ getICFGNode()

const ICFGNode * SemiSparseAbstractInterpretation::getICFGNode ( const ValVar var) const
protected

Definition at line 428 of file AbstractStateManager.cpp.

429{
430 // const ValVars are all defined in global node
431 if (!var->getICFGNode())
432 {
433 return svfir->getICFG()->getGlobalICFGNode();
434 }
435 // for return value of callsite, use the ret-site as def-site
436 else if (SVFUtil::isa<CallICFGNode>(var->getICFGNode()) && SVFUtil::isa<RetValPN>(var))
437 {
438 return SVFUtil::dyn_cast<CallICFGNode>(var->getICFGNode())->getRetICFGNode();
439 }
440 // for other ValVars, use their def-site as the node to query abstract value.
441 else
442 {
443 return var->getICFGNode();
444 }
445}
SVFIR * svfir
Data and helpers reachable from SparseAbstractInterpretation.
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:244
ICFG * getICFG() const
Definition SVFIR.h:229

◆ hasAbsValue() [1/4]

bool AbstractInterpretation::hasAbsValue ( const ObjVar var,
const ICFGNode node 
) const
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 142 of file AbstractStateManager.cpp.

120{
121 auto it = abstractTrace.find(node);
122 if (it == abstractTrace.end())
123 return false;
124 return it->second.getLocToVal().count(var->getId()) != 0;
125}

◆ hasAbsValue() [2/4]

bool AbstractInterpretation::hasAbsValue ( const SVFVar var,
const ICFGNode node 
) const
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 143 of file AbstractStateManager.cpp.

128{
129 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
130 return hasAbsValue(objVar, node);
131 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
132 return hasAbsValue(valVar, node);
133 return false;
134}

◆ hasAbsValue() [3/4]

bool AbstractInterpretation::hasAbsValue ( const ValVar var,
const ICFGNode node 
) const
protectedvirtual

Side-effect-free existence check.

Dense base: direct existence check at node. Mirrors the simplified getAbsValue lookup — uses raw map.contains rather than inVar*Table predicates, which would falsely report neutral (interval=bottom ∧ addrs=∅) entries as "not present".

Reimplemented from SVF::AbstractInterpretation.

Definition at line 141 of file AbstractStateManager.cpp.

112{
113 auto it = abstractTrace.find(node);
114 if (it == abstractTrace.end())
115 return false;
116 return it->second.getVarToVal().count(var->getId()) != 0;
117}

◆ hasAbsValue() [4/4]

bool SemiSparseAbstractInterpretation::hasAbsValue ( const ValVar var,
const ICFGNode node 
) const
overrideprotectedvirtual

Side-effect-free existence check.

Dense base: direct existence check at node. Mirrors the simplified getAbsValue lookup — uses raw map.contains rather than inVar*Table predicates, which would falsely report neutral (interval=bottom ∧ addrs=∅) entries as "not present".

Reimplemented from SVF::AbstractInterpretation.

Definition at line 453 of file AbstractStateManager.cpp.

455{
457}
virtual bool hasAbsValue(const ValVar *var, const ICFGNode *node) const
Side-effect-free existence check.

◆ joinStates()

void SemiSparseAbstractInterpretation::joinStates ( AbstractState dst,
const AbstractState src 
)
overrideprotectedvirtual

Join src into dst with sparsity-aware semantics. Dense merges everything; semi-sparse skips ValVars.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 414 of file AbstractStateManager.cpp.

416{
417 // ValVars live at def-sites in semi-sparse mode; they don't flow
418 // through state merges. Snapshot dst's ValVar map, perform the full
419 // join, then restore the snapshot — leaving only ObjVars and freed
420 // addrs merged.
421 auto saved = dst.getVarToVal();
422 dst.joinWith(src);
423 dst.clearValVars();
424 for (const auto& [id, val] : saved)
425 dst[id] = val;
426}
const VarToAbsValMap & getVarToVal() const
get var2val map
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.

◆ narrowCycleState()

bool SemiSparseAbstractInterpretation::narrowCycleState ( const AbstractState prev,
const AbstractState cur,
const ICFGCycleWTO cycle 
)
overrideprotectedvirtual

Narrow prev with cur; write the narrowed state back. Returns true when narrowing is disabled or the narrowed state equals prev. Semi-sparse subclass scatters the narrowed ValVars on non-fixpoint.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 173 of file SparseAbstractInterpretation.cpp.

175{
176 // Delegate to base. It returns true on the two non-scatter cases
177 // (narrowing disabled, or narrow fixpoint); we preserve the original
178 // "skip scatter at fixpoint" semantics by bailing early here.
180 if (fixpoint)
181 return true;
182
183 // Non-fixpoint: base wrote the narrowed state to trace. Scatter the
184 // narrowed ValVars back to def-sites.
185 const ICFGNode* cycle_head = cycle->head()->getICFGNode();
187 for (const auto& [id, val] : next.getVarToVal())
189 return false;
190}
item next
Definition cJSON.cpp:2224
newitem prev
Definition cJSON.cpp:2285
virtual bool narrowCycleState(const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle)
const SVFVar * getSVFVar(NodeID varId) const
Retrieve SVFVar given its ID; asserts if no such variable exists.
void updateAbsValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node) override

◆ updateAbsState()

void SemiSparseAbstractInterpretation::updateAbsState ( const ICFGNode node,
const AbstractState state 
)
overrideprotectedvirtual

Replace the state at node. Sparse subclasses replace only the ObjVar map (ValVars live at def-sites).

Reimplemented from SVF::AbstractInterpretation.

Definition at line 406 of file AbstractStateManager.cpp.

408{
409 // Only replace ObjVar state. ValVars live at their def-sites and
410 // must not be overwritten when the predecessor's state is merged in.
411 abstractTrace[node].updateAddrStateOnly(state);
412}

◆ updateAbsValue() [1/4]

void AbstractInterpretation::updateAbsValue ( const ObjVar var,
const AbstractValue val,
const ICFGNode node 
)
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 148 of file AbstractStateManager.cpp.

142{
145 as.store(addr, val);
146}

◆ updateAbsValue() [2/4]

void AbstractInterpretation::updateAbsValue ( const SVFVar var,
const AbstractValue val,
const ICFGNode node 
)
protectedvirtual

Reimplemented from SVF::AbstractInterpretation.

Definition at line 149 of file AbstractStateManager.cpp.

149{
150 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
151 updateAbsValue(objVar, val, node);
152 else if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
153 updateAbsValue(valVar, val, node);
154 else
155 assert(false && "Unknown SVFVar kind");
156}

◆ updateAbsValue() [3/4]

void AbstractInterpretation::updateAbsValue ( const ValVar var,
const AbstractValue val,
const ICFGNode node 
)
protectedvirtual

Write a variable's abstract value. Sparse subclasses re-route ValVar writes to the def-site.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 147 of file AbstractStateManager.cpp.

137{
138 abstractTrace[node][var->getId()] = val;
139}

◆ updateAbsValue() [4/4]

void SemiSparseAbstractInterpretation::updateAbsValue ( const ValVar var,
const AbstractValue val,
const ICFGNode node 
)
overrideprotectedvirtual

Write a variable's abstract value. Sparse subclasses re-route ValVar writes to the def-site.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 459 of file AbstractStateManager.cpp.

461{
462 // Write to the var's def-site so getAbsValue stays consistent.
463 const ICFGNode* defNode = var->getICFGNode();
464 abstractTrace[defNode ? defNode : node][var->getId()] = val;
465}

◆ widenCycleState()

bool SemiSparseAbstractInterpretation::widenCycleState ( const AbstractState prev,
const AbstractState cur,
const ICFGCycleWTO cycle 
)
overrideprotectedvirtual

Widen prev with cur; write the widened state to trace[cycle_head]. Returns true when next == prev (fixpoint). Semi-sparse subclass additionally scatters ValVars to their def-sites.

Reimplemented from SVF::AbstractInterpretation.

Definition at line 155 of file SparseAbstractInterpretation.cpp.

157{
158 // Base widens, writes trace[cycle_head], and returns fixpoint bool.
160
161 // Scatter the widened ValVars back to their def-sites so body nodes
162 // observe the widened values on the next iteration. Matches the
163 // pre-refactor semantics: scatter unconditionally, including at
164 // widening fixpoint (see the narrowing-starts-with-stale-body issue
165 // fixed by always writing widened state back).
166 const ICFGNode* cycle_head = cycle->head()->getICFGNode();
168 for (const auto& [id, val] : next.getVarToVal())
170 return fixpoint;
171}
virtual bool widenCycleState(const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle)

The documentation for this class was generated from the following files: