[cfe-commits] r46789 - in /cfe/trunk/Analysis: GRConstants.cpp RValues.h ValueState.cpp ValueState.h

Ted Kremenek kremenek at apple.com
Tue Feb 5 16:54:14 PST 2008


Author: kremenek
Date: Tue Feb  5 18:54:14 2008
New Revision: 46789

URL: http://llvm.org/viewvc/llvm-project?rev=46789&view=rev
Log:
Added some skeleton code for performing "assume" on symbols: e.g. assume($0 != 0).
This action will add constraints to the possible values of a symbol.
Still needs to be debugged.

Modified:
    cfe/trunk/Analysis/GRConstants.cpp
    cfe/trunk/Analysis/RValues.h
    cfe/trunk/Analysis/ValueState.cpp
    cfe/trunk/Analysis/ValueState.h

Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46789&r1=46788&r2=46789&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Tue Feb  5 18:54:14 2008
@@ -228,6 +228,12 @@
   StateTy Assume(StateTy St, LValue Cond, bool Assumption, bool& isFeasible);
   StateTy Assume(StateTy St, NonLValue Cond, bool Assumption, bool& isFeasible);
   
+  StateTy AssumeSymNE(StateTy St, SymbolID sym, const llvm::APSInt& V,
+                      bool& isFeasible);
+
+  StateTy AssumeSymEQ(StateTy St, SymbolID sym, const llvm::APSInt& V,
+                      bool& isFeasible);
+  
   void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
   
   /// Nodify - This version of Nodify is used to batch process a set of states.
@@ -851,18 +857,27 @@
 // "Assume" logic.
 //===----------------------------------------------------------------------===//
 
-GRConstants::StateTy GRConstants::Assume(StateTy St, LValue Cond, bool Assumption, 
+GRConstants::StateTy GRConstants::Assume(StateTy St, LValue Cond,
+                                         bool Assumption, 
                                          bool& isFeasible) {    
   
   switch (Cond.getSubKind()) {
     default:
-      assert (false && "'Assume' not implemented for this NonLValue.");
+      assert (false && "'Assume' not implemented for this LValue.");
       return St;
       
+    case lval::SymbolValKind:
+      if (Assumption)
+        return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
+                           ValMgr.getZeroWithPtrWidth(), isFeasible);
+      else
+        return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
+                           ValMgr.getZeroWithPtrWidth(), isFeasible);
+      
     case lval::DeclValKind:
       isFeasible = Assumption;
       return St;
-      
+
     case lval::ConcreteIntKind: {
       bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
       isFeasible = b ? Assumption : !Assumption;      
@@ -871,7 +886,8 @@
   }
 }
 
-GRConstants::StateTy GRConstants::Assume(StateTy St, NonLValue Cond, bool Assumption, 
+GRConstants::StateTy GRConstants::Assume(StateTy St, NonLValue Cond,
+                                         bool Assumption, 
                                          bool& isFeasible) {
   
   switch (Cond.getSubKind()) {
@@ -887,6 +903,51 @@
   }
 }
 
+GRConstants::StateTy
+GRConstants::AssumeSymNE(StateTy St, SymbolID sym,
+                         const llvm::APSInt& V, bool& isFeasible) {
+
+  // First, determine if sym == X, where X != V.
+  if (const llvm::APSInt* X = St.getSymVal(sym)) {
+    isFeasible = *X != V;
+    return St;
+  }
+  
+  // Second, determine if sym != V.
+  if (St.isNotEqual(sym, V)) {
+    isFeasible = true;
+    return St;
+  }
+      
+  // If we reach here, sym is not a constant and we don't know if it is != V.
+  // Make that assumption.
+  
+  isFeasible = true;
+  return StateMgr.AddNE(St, sym, V);
+}
+
+GRConstants::StateTy
+GRConstants::AssumeSymEQ(StateTy St, SymbolID sym,
+                         const llvm::APSInt& V, bool& isFeasible) {
+  
+  // First, determine if sym == X, where X != V.
+  if (const llvm::APSInt* X = St.getSymVal(sym)) {
+    isFeasible = *X == V;
+    return St;
+  }
+  
+  // Second, determine if sym != V.
+  if (St.isNotEqual(sym, V)) {
+    isFeasible = false;
+    return St;
+  }
+  
+  // If we reach here, sym is not a constant and we don't know if it is == V.
+  // Make that assumption.
+  
+  isFeasible = true;
+  return StateMgr.AddEQ(St, sym, V);
+}
 
 //===----------------------------------------------------------------------===//
 // Driver.

Modified: cfe/trunk/Analysis/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.h?rev=46789&r1=46788&r2=46789&view=diff

==============================================================================
--- cfe/trunk/Analysis/RValues.h (original)
+++ cfe/trunk/Analysis/RValues.h Tue Feb  5 18:54:14 2008
@@ -149,6 +149,10 @@
   const llvm::APSInt& getValue(uint64_t X, QualType T,
                                SourceLocation Loc = SourceLocation());
   
+  inline const llvm::APSInt& getZeroWithPtrWidth() {
+    return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()), true);
+  }
+  
   const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
                                         const llvm::APSInt& V);
 };

Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=46789&r1=46788&r2=46789&view=diff

==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Tue Feb  5 18:54:14 2008
@@ -15,6 +15,24 @@
 
 using namespace clang;
 
+bool ValueState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
+  // First, retrieve the NE-set associated with the given symbol.
+  ConstantNotEqTy::TreeTy* T = Data->ConstantNotEq.SlimFind(sym);
+  
+  if (!T)
+    return false;
+  
+  // Second, see if V is present in the NE-set.
+  return T->getValue().second.contains(&V);
+}
+
+const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
+  ConstantEqTy::TreeTy* T = Data->ConstantEq.SlimFind(sym);
+  return T ? T->getValue().second : NULL;  
+}
+
+
+
 RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
   switch (LV.getSubKind()) {
     case lval::DeclValKind: {
@@ -31,6 +49,36 @@
   return InvalidValue();
 }
 
+ValueStateManager::StateTy
+ValueStateManager::AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V) {
+  // First, retrieve the NE-set associated with the given symbol.
+  ValueState::ConstantNotEqTy::TreeTy* T =
+    St.getImpl()->ConstantNotEq.SlimFind(sym);    
+  
+  ValueState::IntSetTy S = T ? T->getValue().second : ISetFactory.GetEmptySet();
+  
+  // Now add V to the NE set.  
+  S = ISetFactory.Add(S, &V);
+  
+  // Create a new state with the old binding replaced.
+  ValueStateImpl NewStateImpl = *St.getImpl();
+  NewStateImpl.ConstantNotEq = CNEFactory.Add(NewStateImpl.ConstantNotEq,
+                                              sym, S);
+    
+  // Get the persistent copy.
+  return getPersistentState(NewStateImpl);
+}
+
+ValueStateManager::StateTy
+ValueStateManager::AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V) {
+  // Create a new state with the old binding replaced.
+  ValueStateImpl NewStateImpl = *St.getImpl();
+  NewStateImpl.ConstantEq = CEFactory.Add(NewStateImpl.ConstantEq, sym, &V);
+  
+  // Get the persistent copy.
+  return getPersistentState(NewStateImpl);
+}
+
 RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
   for (;;) {
     switch (S->getStmtClass()) {
@@ -163,7 +211,8 @@
 
   // Create a state with empty variable bindings.
   ValueStateImpl StateImpl(VBFactory.GetEmptyMap(),
-                           CNEFactory.GetEmptyMap());
+                           CNEFactory.GetEmptyMap(),
+                           CEFactory.GetEmptyMap());
   
   return getPersistentState(StateImpl);
 }

Modified: cfe/trunk/Analysis/ValueState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.h?rev=46789&r1=46788&r2=46789&view=diff

==============================================================================
--- cfe/trunk/Analysis/ValueState.h (original)
+++ cfe/trunk/Analysis/ValueState.h Tue Feb  5 18:54:14 2008
@@ -116,8 +116,9 @@
 namespace vstate {
   typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
   
-  typedef llvm::ImmutableMap<VarBindKey,RValue> VariableBindingsTy;  
-  typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstantNotEqTy;
+  typedef llvm::ImmutableMap<VarBindKey,RValue>            VariableBindingsTy;  
+  typedef llvm::ImmutableMap<SymbolID,IntSetTy>            ConstantNotEqTy;
+  typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstantEqTy;
 }
 
 /// ValueStateImpl - This class encapsulates the actual data values for
@@ -127,22 +128,28 @@
 struct ValueStateImpl : public llvm::FoldingSetNode {
   vstate::VariableBindingsTy VariableBindings;
   vstate::ConstantNotEqTy    ConstantNotEq;
+  vstate::ConstantEqTy       ConstantEq;
   
   /// This ctor is used when creating the first ValueStateImpl object.
-  ValueStateImpl(vstate::VariableBindingsTy VB, vstate::ConstantNotEqTy CNE)
-    : VariableBindings(VB), ConstantNotEq(CNE) {}
+  ValueStateImpl(vstate::VariableBindingsTy VB,
+                 vstate::ConstantNotEqTy CNE,
+                 vstate::ConstantEqTy CE)
+    : VariableBindings(VB), ConstantNotEq(CNE), ConstantEq(CE) {}
   
   /// Copy ctor - We must explicitly define this or else the "Next" ptr
   ///  in FoldingSetNode will also get copied.
   ValueStateImpl(const ValueStateImpl& RHS)
     : llvm::FoldingSetNode(),
       VariableBindings(RHS.VariableBindings),
-      ConstantNotEq(RHS.ConstantNotEq) {} 
+      ConstantNotEq(RHS.ConstantNotEq),
+      ConstantEq(RHS.ConstantEq) {} 
   
   /// Profile - Profile the contents of a ValueStateImpl object for use
   ///  in a FoldingSet.
   static void Profile(llvm::FoldingSetNodeID& ID, const ValueStateImpl& V) {
     V.VariableBindings.Profile(ID);
+    V.ConstantNotEq.Profile(ID);
+    V.ConstantEq.Profile(ID);
   }
 
   /// Profile - Used to profile the contents of this object for inclusion
@@ -171,10 +178,18 @@
   ValueStateImpl* getImpl() const { return Data; }
 
   // Typedefs.
+  typedef vstate::IntSetTy                 IntSetTy;
   typedef vstate::VariableBindingsTy       VariableBindingsTy;
   typedef vstate::ConstantNotEqTy          ConstantNotEqTy;
+  typedef vstate::ConstantEqTy             ConstantEqTy;
+
   typedef llvm::SmallVector<ValueState,5>  BufferTy;
 
+  // Queries.
+  
+  bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
+  const llvm::APSInt* getSymVal(SymbolID sym) const;
+  
   // Iterators.
 
   typedef VariableBindingsTy::iterator vb_iterator;  
@@ -211,8 +226,10 @@
   typedef ValueState StateTy;
 
 private:
+  ValueState::IntSetTy::Factory           ISetFactory;
   ValueState::VariableBindingsTy::Factory VBFactory;
   ValueState::ConstantNotEqTy::Factory    CNEFactory;
+  ValueState::ConstantEqTy::Factory       CEFactory;
   
   /// StateSet - FoldingSet containing all the states created for analyzing
   ///  a particular function.  This is used to unique states.
@@ -249,6 +266,9 @@
   StateTy Add(StateTy St, VarBindKey K, const RValue& V);
   StateTy Remove(StateTy St, VarBindKey K);
   StateTy getPersistentState(const ValueStateImpl& Impl);
+  
+  StateTy AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V);
+  StateTy AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V);
 };
   
 } // end clang namespace





More information about the cfe-commits mailing list