[cfe-commits] r64787 - /cfe/trunk/lib/Analysis/RangeConstraintManager.cpp
Ted Kremenek
kremenek at apple.com
Tue Feb 17 11:28:04 PST 2009
Author: kremenek
Date: Tue Feb 17 13:28:04 2009
New Revision: 64787
URL: http://llvm.org/viewvc/llvm-project?rev=64787&view=rev
Log:
Revised RangeConstraintManager based on several discussions with Ben Laurie and
Zhongxing Xu. The resultant code is less than 1/2 the size of the original.
Key highlights:
- All CouldBeXXX methods have been removed. Checking for feasibility is now just
done in the AddXXX methods.
- RangeSets now represent "all possible values" explicitly as the range set {
[min, max] } instead of the empty set. The empty set now represents "no
feasible values". This change consolidated much of the core algorithm to only
have one code path instead of alternate paths that considered the empty set to
represent "all possible falues."
Modified:
cfe/trunk/lib/Analysis/RangeConstraintManager.cpp
Modified: cfe/trunk/lib/Analysis/RangeConstraintManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RangeConstraintManager.cpp?rev=64787&r1=64786&r2=64787&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RangeConstraintManager.cpp (original)
+++ cfe/trunk/lib/Analysis/RangeConstraintManager.cpp Tue Feb 17 13:28:04 2009
@@ -25,379 +25,203 @@
using namespace clang;
-namespace { class VISIBILITY_HIDDEN ConstRange {}; }
+namespace { class VISIBILITY_HIDDEN ConstraintRange {}; }
+static int ConstraintRangeIndex = 0;
-static int ConstRangeIndex = 0;
-
-// A Range represents the closed range [from, to]. The caller must
-// guarantee that from <= to. Note that Range is immutable, so as not
-// to subvert RangeSet's immutability.
-class Range : public std::pair<llvm::APSInt, llvm::APSInt> {
+/// A Range represents the closed range [from, to]. The caller must
+/// guarantee that from <= to. Note that Range is immutable, so as not
+/// to subvert RangeSet's immutability.
+class Range : public std::pair<const llvm::APSInt*, const llvm::APSInt*> {
public:
Range(const llvm::APSInt &from, const llvm::APSInt &to)
- : std::pair<llvm::APSInt, llvm::APSInt>(from, to) {
+ : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) {
assert(from <= to);
}
bool Includes(const llvm::APSInt &v) const {
- return first <= v && v <= second;
+ return *first <= v && v <= *second;
}
const llvm::APSInt &From() const {
- return first;
+ return *first;
}
const llvm::APSInt &To() const {
- return second;
+ return *second;
}
- const llvm::APSInt *HasConcreteValue() const {
- return From() == To() ? &From() : NULL;
+ const llvm::APSInt *getConcreteValue() const {
+ return &From() == &To() ? &From() : NULL;
}
void Profile(llvm::FoldingSetNodeID &ID) const {
- From().Profile(ID);
- To().Profile(ID);
- }
-};
-
-struct RangeCmp {
- bool operator()(const Range &r1, const Range &r2) {
- if (r1.From() < r2.From()) {
- assert(!r1.Includes(r2.From()));
- assert(!r2.Includes(r1.To()));
- return true;
- } else if (r1.From() > r2.From()) {
- assert(!r1.Includes(r2.To()));
- assert(!r2.Includes(r1.From()));
- return false;
- } else
- assert(!"Ranges should never be equal in the same set");
+ ID.AddPointer(&From());
+ ID.AddPointer(&To());
}
};
-typedef llvm::ImmutableSet<Range> PrimRangeSet;
-
-class RangeSet;
-std::ostream &operator<<(std::ostream &os, const RangeSet &r);
-
-
-// A RangeSet contains a set of ranges. If the set is empty, then
-// noValues -> Nothing matches.
-// !noValues -> Everything (in range of the bit representation) matches.
+/// RangeSet contains a set of ranges. If the set is empty, then
+/// there the value of a symbol is overly constrained and there are no
+/// possible values for that symbol.
class RangeSet {
+ typedef llvm::ImmutableSet<Range> PrimRangeSet;
PrimRangeSet ranges; // no need to make const, since it is an
// ImmutableSet - this allows default operator=
- // to work.
- bool noValues; // if true, no value is possible (should never happen)
-
- static const llvm::APSInt Max(const llvm::APSInt &v) {
- return llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned());
- }
- static const llvm::APSInt Min(const llvm::APSInt &v) {
- return llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned());
- }
- static const llvm::APSInt One(const llvm::APSInt &v) {
- return llvm::APSInt(llvm::APInt(v.getBitWidth(), 1), v.isUnsigned());
- }
-
+ // to work.
public:
- // Create a RangeSet that allows all possible values.
- RangeSet(PrimRangeSet::Factory *factory) : ranges(factory->GetEmptySet()),
- noValues(false) {
- }
- // Note that if the empty set is passed, then there are no possible
- // values. To create a RangeSet that covers all values when the
- // empty set is passed, use RangeSet(r, false).
- RangeSet(const PrimRangeSet &r) : ranges(r), noValues(r.isEmpty()) {
- }
- // Allow an empty set to be passed meaning "all values" instead of
- // "no values".
- RangeSet(const PrimRangeSet &r, bool n) : ranges(r), noValues(n) {
- assert(!n);
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ranges.Profile(ID);
- ID.AddBoolean(noValues);
- }
+ typedef PrimRangeSet::Factory Factory;
+ typedef PrimRangeSet::iterator iterator;
- const llvm::APSInt *HasConcreteValue() const {
- if (!ranges.isSingleton())
- return NULL;
- return ranges.begin()->HasConcreteValue();
- }
-
- bool CouldBeNE(const llvm::APSInt &ne) const {
- DOUT << "CouldBeNE(" << ne.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- const llvm::APSInt *v = HasConcreteValue();
- if (v && *v == ne)
- return false;
- return true;
- }
-
- bool CouldBeEQ(const llvm::APSInt &eq) const {
- DOUT << "CouldBeEQ(" << eq.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- if (ranges.isEmpty())
- return true;
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
- if (i->Includes(eq))
- return true;
- return false;
- }
-
- bool CouldBeLT(const llvm::APSInt <) const {
- DOUT << "CouldBeLT(" << lt.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- // FIXME: should test if lt == min -> false here, since that's
- // impossible to meet.
- if (ranges.isEmpty())
- return true;
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
- if (i->From() < lt)
- return true;
- return false;
- }
-
- bool CouldBeLE(const llvm::APSInt &le) const {
- DOUT << "CouldBeLE(" << le.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- if (ranges.isEmpty())
- return true;
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
- if (i->From() <= le)
- return true;
- return false;
- }
-
- bool CouldBeGT(const llvm::APSInt >) const {
- DOUT << "CouldBeGT(" << gt.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- // FIXME: should we test if gt == max -> false here, since that's
- // impossible to meet.
- if (ranges.isEmpty())
- return true;
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
- if (i->To() > gt)
- return true;
- return false;
- }
-
- bool CouldBeGE(const llvm::APSInt &ge) const {
- DOUT << "CouldBeGE(" << ge.toString(10) << ") " << *this << std::endl;
- assert(!noValues);
- if (ranges.isEmpty())
- return true;
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
- if (i->To() >= ge)
- return true;
- return false;
- }
-
- // Make all existing ranges fall within this new range
- RangeSet Restrict(PrimRangeSet::Factory *factory, const llvm::APSInt &from,
- const llvm::APSInt &to) const {
- if (ranges.isEmpty())
- return factory->Add(ranges, Range(from, to));;
-
- PrimRangeSet newRanges = factory->GetEmptySet();
-
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- if (i->Includes(from)) {
- if (i->Includes(to)) {
- newRanges = factory->Add(newRanges, Range(from, to));
- } else {
- newRanges = factory->Add(newRanges, Range(from, i->To()));
- }
- } else if (i->Includes(to)) {
- newRanges = factory->Add(newRanges, Range(i->From(), to));
- }
- }
- return RangeSet(newRanges);
- }
-
- // Create a new RangeSet with the additional constraint that the
- // range must be == eq. In other words the range becomes [eq,
- // eq]. Note that this RangeSet must have included eq in the first
- // place, or we shouldn't be here.
- RangeSet AddEQ(PrimRangeSet::Factory *factory, const llvm::APSInt &eq) {
- DOUT << "AddEQ(" << eq.toString(10) << ") " << *this << " -> ";
- assert(CouldBeEQ(eq));
- RangeSet r(factory->Add(factory->GetEmptySet(), Range(eq, eq)));
- DOUT << r << std::endl;
- return r;
- }
-
- RangeSet AddNE(PrimRangeSet::Factory *factory, const llvm::APSInt &ne) {
- DOUT << "AddNE(" << ne.toString(10) << ") " << *this << " -> ";
-
- const llvm::APSInt max = Max(ne);
- const llvm::APSInt min = Min(ne);
- const llvm::APSInt one = One(ne);
-
- PrimRangeSet newRanges = factory->GetEmptySet();
-
- if (ranges.isEmpty()) {
- if (ne != max)
- newRanges = factory->Add(newRanges, Range(ne + one, max));
- if (ne != min)
- newRanges = factory->Add(newRanges, Range(min, ne - one));
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
- }
+ RangeSet(PrimRangeSet RS) : ranges(RS) {}
+ RangeSet(Factory& F) : ranges(F.GetEmptySet()) {}
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- if (i->Includes(ne)) {
- if (ne != i->From())
- newRanges = factory->Add(newRanges, Range(i->From(), ne - one));
- if (ne != i->To())
- newRanges = factory->Add(newRanges, Range(ne + one, i->To()));
- } else {
- newRanges = factory->Add(newRanges, *i);
+ iterator begin() const { return ranges.begin(); }
+ iterator end() const { return ranges.end(); }
+
+ bool isEmpty() const { return ranges.isEmpty(); }
+
+ /// Construct a new RangeSet representing '{ [from, to] }'.
+ RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to)
+ : ranges(F.Add(F.GetEmptySet(), Range(from, to))) {}
+
+ /// Profile - Generates a hash profile of this RangeSet for use
+ /// by FoldingSet.
+ void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); }
+
+ /// getConcreteValue - If a symbol is contrained to equal a specific integer
+ /// constant then this method returns that value. Otherwise, it returns
+ /// NULL.
+ const llvm::APSInt* getConcreteValue() const {
+ return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : 0;
+ }
+
+ /// AddEQ - Create a new RangeSet with the additional constraint that the
+ /// value be equal to V.
+ RangeSet AddEQ(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ // Search for a range that includes 'V'. If so, return a new RangeSet
+ // representing { [V, V] }.
+ for (PrimRangeSet::iterator i = begin(), e = end(); i!=e; ++i)
+ if (i->Includes(V))
+ return RangeSet(F, V, V);
+
+ return RangeSet(F);
+ }
+
+ /// AddNE - Create a new RangeSet with the additional constraint that the
+ /// value be not be equal to V.
+ RangeSet AddNE(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ PrimRangeSet newRanges = ranges;
+
+ // FIXME: We can perhaps enhance ImmutableSet to do this search for us
+ // in log(N) time using the sorted property of the internal AVL tree.
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ if (i->Includes(V)) {
+ // Remove the old range.
+ newRanges = F.Remove(newRanges, *i);
+ // Split the old range into possibly one or two ranges.
+ if (V != i->From())
+ newRanges = F.Add(newRanges, Range(i->From(), BV.Sub1(V)));
+ if (V != i->To())
+ newRanges = F.Add(newRanges, Range(BV.Add1(V), i->To()));
+ // All of the ranges are non-overlapping, so we can stop.
+ break;
}
}
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
- }
-
- RangeSet AddLT(PrimRangeSet::Factory *factory, const llvm::APSInt <) {
- DOUT << "AddLT(" << lt.toString(10) << ") " << *this << " -> ";
- const llvm::APSInt min = Min(lt);
- const llvm::APSInt one = One(lt);
-
- if (ranges.isEmpty()) {
- PrimRangeSet pr = factory->GetEmptySet();
- if (lt != min)
- pr = factory->Add(pr, Range(min, lt - one));
- RangeSet r(pr, false);
- DOUT << r << std::endl;
- return r;
- }
-
- PrimRangeSet newRanges = factory->GetEmptySet();
-
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- if (i->Includes(lt) && i->From() < lt)
- newRanges = factory->Add(newRanges, Range(i->From(), lt - one));
- else if (i->To() < lt)
- newRanges = factory->Add(newRanges, *i);
- }
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
+
+ return newRanges;
}
- RangeSet AddLE(PrimRangeSet::Factory *factory, const llvm::APSInt &le) {
- DOUT << "AddLE(" << le.toString(10) << ") " << *this << " -> ";
- const llvm::APSInt min = Min(le);
-
- if (ranges.isEmpty()) {
- RangeSet r(factory->Add(ranges, Range(min, le)));
- DOUT << r << std::endl;
- return r;
+ /// AddNE - Create a new RangeSet with the additional constraint that the
+ /// value be less than V.
+ RangeSet AddLT(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ PrimRangeSet newRanges = F.GetEmptySet();
+
+ for (iterator i = begin(), e = end() ; i != e ; ++i) {
+ if (i->Includes(V) && i->From() < V)
+ newRanges = F.Add(newRanges, Range(i->From(), BV.Sub1(V)));
+ else if (i->To() < V)
+ newRanges = F.Add(newRanges, *i);
}
+
+ return newRanges;
+ }
- PrimRangeSet newRanges = factory->GetEmptySet();
+ RangeSet AddLE(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ PrimRangeSet newRanges = F.GetEmptySet();
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- // Strictly we should test for includes le + 1, but no harm is
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ // Strictly we should test for includes *V + 1, but no harm is
// done by this formulation
- if (i->Includes(le))
- newRanges = factory->Add(newRanges, Range(i->From(), le));
- else if (i->To() <= le)
- newRanges = factory->Add(newRanges, *i);
+ if (i->Includes(V))
+ newRanges = F.Add(newRanges, Range(i->From(), V));
+ else if (i->To() <= V)
+ newRanges = F.Add(newRanges, *i);
}
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
+
+ return newRanges;
}
- RangeSet AddGT(PrimRangeSet::Factory *factory, const llvm::APSInt >) {
- DOUT << "AddGT(" << gt.toString(10) << ") " << *this << " -> ";
- const llvm::APSInt max = Max(gt);
- const llvm::APSInt one = One(gt);
-
- if (ranges.isEmpty()) {
- RangeSet r(factory->Add(ranges, Range(gt + one, max)));
- DOUT << r << std::endl;
- return r;
- }
-
- PrimRangeSet newRanges = factory->GetEmptySet();
+ RangeSet AddGT(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ PrimRangeSet newRanges = F.GetEmptySet();
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- if (i->Includes(gt) && i->To() > gt)
- newRanges = factory->Add(newRanges, Range(gt + one, i->To()));
- else if (i->From() > gt)
- newRanges = factory->Add(newRanges, *i);
+ for (PrimRangeSet::iterator i = begin(), e = end(); i != e; ++i) {
+ if (i->Includes(V) && i->To() > V)
+ newRanges = F.Add(newRanges, Range(BV.Add1(V), i->To()));
+ else if (i->From() > V)
+ newRanges = F.Add(newRanges, *i);
}
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
+
+ return newRanges;
}
- RangeSet AddGE(PrimRangeSet::Factory *factory, const llvm::APSInt &ge) {
- DOUT << "AddGE(" << ge.toString(10) << ") " << *this << " -> ";
- const llvm::APSInt max = Max(ge);
-
- if (ranges.isEmpty()) {
- RangeSet r(factory->Add(ranges, Range(ge, max)));
- DOUT << r << std::endl;
- return r;
- }
-
- PrimRangeSet newRanges = factory->GetEmptySet();
+ RangeSet AddGE(BasicValueFactory &BV, Factory &F, const llvm::APSInt &V) {
+ PrimRangeSet newRanges = F.GetEmptySet();
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- // Strictly we should test for includes ge - 1, but no harm is
+ for (PrimRangeSet::iterator i = begin(), e = end(); i != e; ++i) {
+ // Strictly we should test for includes *V - 1, but no harm is
// done by this formulation
- if (i->Includes(ge))
- newRanges = factory->Add(newRanges, Range(ge, i->To()));
- else if (i->From() >= ge)
- newRanges = factory->Add(newRanges, *i);
+ if (i->Includes(V))
+ newRanges = F.Add(newRanges, Range(V, i->To()));
+ else if (i->From() >= V)
+ newRanges = F.Add(newRanges, *i);
}
- RangeSet r(newRanges);
- DOUT << r << std::endl;
- return r;
+ return newRanges;
}
void Print(std::ostream &os) const {
+ bool isFirst = true;
os << "{ ";
- if (noValues) {
- os << "**no values** }";
- return;
- }
- for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
- if (i != ranges.begin())
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ if (isFirst)
+ isFirst = false;
+ else
os << ", ";
+
os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
<< ']';
}
- os << " }";
+ os << " }";
+ }
-}
bool operator==(const RangeSet &other) const {
return ranges == other.ranges;
}
};
-std::ostream &operator<<(std::ostream &os, const RangeSet &r) {
- r.Print(os);
- return os;
-}
-
-typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstRangeTy;
+typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstraintRangeTy;
namespace clang {
template<>
-struct GRStateTrait<ConstRange> : public GRStatePartialTrait<ConstRangeTy> {
- static inline void* GDMIndex() { return &ConstRangeIndex; }
+struct GRStateTrait<ConstraintRange>
+ : public GRStatePartialTrait<ConstraintRangeTy> {
+ static inline void* GDMIndex() { return &ConstraintRangeIndex; }
};
}
namespace {
class VISIBILITY_HIDDEN RangeConstraintManager
: public SimpleConstraintManager {
+
+
+ RangeSet GetRange(GRStateRef state, SymbolRef sym);
+
public:
RangeConstraintManager(GRStateManager& statemgr)
: SimpleConstraintManager(statemgr) {}
@@ -420,38 +244,21 @@
const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
- const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- const GRState* AddLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- const GRState* AddLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- const GRState* AddGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- const GRState* AddGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
-
- // FIXME: these two are required because they are pure virtual, but
- // are they useful with ranges? Neither is used in this file.
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
- bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
-
- bool CouldBeEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
- bool CouldBeNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+
+ // FIXME: Refactor into SimpleConstraintManager?
+ bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const {
+ const llvm::APSInt *i = getSymVal(St, sym);
+ return i ? *i == V : false;
+ }
- bool CouldBeLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
- bool CouldBeLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
- bool CouldBeGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
- bool CouldBeGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
void print(const GRState* St, std::ostream& Out,
const char* nl, const char *sep);
private:
- PrimRangeSet::Factory factory;
- BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
+ RangeSet::Factory F;
};
} // end anonymous namespace
@@ -461,197 +268,10 @@
return new RangeConstraintManager(StateMgr);
}
-const GRState*
-RangeConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
- isFeasible = CouldBeNE(St, sym, V);
- if (isFeasible)
- return AddNE(St, sym, V);
- return St;
-}
-
-const GRState*
-RangeConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
- isFeasible = CouldBeEQ(St, sym, V);
- if (isFeasible)
- return AddEQ(St, sym, V);
- return St;
-}
-
-const GRState*
-RangeConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
- // Is 'V' the smallest possible value?
- if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
- // sym cannot be any value less than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
- }
-
- isFeasible = CouldBeLT(St, sym, V);
- if (isFeasible)
- return AddLT(St, sym, V);
-
- return St;
-}
-
-const GRState*
-RangeConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
- // Is 'V' the largest possible value?
- if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
- // sym cannot be any value greater than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
- }
-
- isFeasible = CouldBeGT(St, sym, V);
- if (isFeasible)
- return AddGT(St, sym, V);
-
- return St;
-}
-
-const GRState*
-RangeConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
- isFeasible = CouldBeGE(St, sym, V);
- if (isFeasible)
- return AddGE(St, sym, V);
-
- return St;
-}
-
-const GRState*
-RangeConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
- isFeasible = CouldBeLT(St, sym, V);
- if (isFeasible)
- return AddLE(St, sym, V);
-
- return St;
-}
-
-const GRState* RangeConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- // Create a new state with the old binding replaced.
- GRStateRef state(St, StateMgr);
- RangeSet R(&factory);
- R = R.AddEQ(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
-const GRState* RangeConstraintManager::AddNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
- ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
- RangeSet R(&factory);
- if (T)
- R = *T;
- R = R.AddNE(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
-const GRState* RangeConstraintManager::AddLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
- ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
- RangeSet R(&factory);
- if (T)
- R = *T;
- R = R.AddLT(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
-const GRState* RangeConstraintManager::AddLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
- ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
- RangeSet R(&factory);
- if (T)
- R = *T;
- R = R.AddLE(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
-const GRState* RangeConstraintManager::AddGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
- ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
- RangeSet R(&factory);
- if (T)
- R = *T;
- R = R.AddGT(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
-const GRState* RangeConstraintManager::AddGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
- ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
- RangeSet R(&factory);
- if (T)
- R = *T;
- R = R.AddGE(&factory, V);
- return state.set<ConstRange>(sym, R);
-}
-
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
SymbolRef sym) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->HasConcreteValue() : NULL;
-}
-
-bool RangeConstraintManager::CouldBeLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeLT(V) : true;
-}
-
-bool RangeConstraintManager::CouldBeLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeLE(V) : true;
-}
-
-bool RangeConstraintManager::CouldBeGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeGT(V) : true;
-}
-
-bool RangeConstraintManager::CouldBeGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeGE(V) : true;
-}
-
-bool RangeConstraintManager::CouldBeNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeNE(V) : true;
-}
-
-bool RangeConstraintManager::CouldBeEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
- return T ? T->CouldBeEQ(V) : true;
-}
-
-bool RangeConstraintManager::isEqual(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V) const {
- const llvm::APSInt *i = getSymVal(St, sym);
- return i ? *i == V : false;
+ const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
+ return T ? T->getConcreteValue() : NULL;
}
/// Scan all symbols referenced by the constraints. If the symbol is not alive
@@ -661,29 +281,70 @@
SymbolReaper& SymReaper) {
GRStateRef state(St, StateMgr);
- ConstRangeTy CR = state.get<ConstRange>();
- ConstRangeTy::Factory& CRFactory = state.get_context<ConstRange>();
+ ConstraintRangeTy CR = state.get<ConstraintRange>();
+ ConstraintRangeTy::Factory& CRFactory = state.get_context<ConstraintRange>();
- for (ConstRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
+ for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym))
CR = CRFactory.Remove(CR, sym);
}
- return state.set<ConstRange>(CR);
+ return state.set<ConstraintRange>(CR);
}
+//===------------------------------------------------------------------------===
+// AssumeSymX methods: public interface for RangeConstraintManager.
+//===------------------------------------------------------------------------===/
+
+RangeSet
+RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
+ if (ConstraintRangeTy::data_type* V = state.get<ConstraintRange>(sym))
+ return *V;
+
+ // Lazily generate a new RangeSet representing all possible values for the
+ // given symbol type.
+ QualType T = state.getSymbolManager().getType(sym);
+ BasicValueFactory& BV = state.getBasicVals();
+ return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
+}
+
+//===------------------------------------------------------------------------===
+// AssumeSymX methods: public interface for RangeConstraintManager.
+//===------------------------------------------------------------------------===/
+
+#define AssumeX(OP)\
+const GRState*\
+RangeConstraintManager::AssumeSym ## OP(const GRState* St, SymbolRef sym,\
+ const llvm::APSInt& V, bool& isFeasible){\
+ GRStateRef state(St, StateMgr);\
+ const RangeSet& R = GetRange(state, sym).Add##OP(state.getBasicVals(), F, V);\
+ isFeasible = !R.isEmpty();\
+ return isFeasible ? state.set<ConstraintRange>(sym, R).getState() : 0;\
+}
+
+AssumeX(EQ)
+AssumeX(NE)
+AssumeX(LT)
+AssumeX(GT)
+AssumeX(LE)
+AssumeX(GE)
+
+//===------------------------------------------------------------------------===
+// Pretty-printing.
+//===------------------------------------------------------------------------===/
+
void RangeConstraintManager::print(const GRState* St, std::ostream& Out,
const char* nl, const char *sep) {
- ConstRangeTy Ranges = St->get<ConstRange>();
+ ConstraintRangeTy Ranges = St->get<ConstraintRange>();
if (Ranges.isEmpty())
return;
Out << nl << sep << "ranges of symbol values:";
- for (ConstRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I) {
+ for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){
Out << nl << " $" << I.getKey() << " : ";
I.getData().Print(Out);
}
More information about the cfe-commits
mailing list