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

Ted Kremenek kremenek at apple.com
Wed Feb 6 14:50:26 PST 2008


Author: kremenek
Date: Wed Feb  6 16:50:25 2008
New Revision: 46831

URL: http://llvm.org/viewvc/llvm-project?rev=46831&view=rev
Log:
Major code refactoring/cleanup with transfer function logic.  Now the
code structure is more suitable for additional symbolic analysis.

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

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

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Wed Feb  6 16:50:25 2008
@@ -537,7 +537,7 @@
     NodeTy* N = *I1;
     StateTy St = N->getState();
     const RValue& V = GetValue(St, E);
-    Nodify(Dst, CastE, N, SetValue(St, CastE, V.Cast(ValMgr, CastE)));
+    Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
   }
 }
 
@@ -585,7 +585,10 @@
       case UnaryOperator::PostInc: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        NonLValue Result = R1.Add(ValMgr, GetRValueConstant(1U, U));
+        
+        NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add,
+                                           GetRValueConstant(1U, U));
+        
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
         break;
       }
@@ -593,7 +596,10 @@
       case UnaryOperator::PostDec: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        NonLValue Result = R1.Sub(ValMgr, GetRValueConstant(1U, U));
+        
+        NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub,
+                                           GetRValueConstant(1U, U));
+        
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
         break;
       }
@@ -601,7 +607,10 @@
       case UnaryOperator::PreInc: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        NonLValue Result = R1.Add(ValMgr, GetRValueConstant(1U, U));
+        
+        NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add,
+                                           GetRValueConstant(1U, U));
+        
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
         break;
       }
@@ -609,20 +618,23 @@
       case UnaryOperator::PreDec: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        NonLValue Result = R1.Sub(ValMgr, GetRValueConstant(1U, U));
+        
+        NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub,
+                                           GetRValueConstant(1U, U));
+
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
         break;
       }
         
       case UnaryOperator::Minus: {
         const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
-        Nodify(Dst, U, N1, SetValue(St, U, R1.UnaryMinus(ValMgr, U)));
+        Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U)));
         break;
       }
         
       case UnaryOperator::Not: {
         const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
-        Nodify(Dst, U, N1, SetValue(St, U, R1.BitwiseComplement(ValMgr)));
+        Nodify(Dst, U, N1, SetValue(St, U, R1.EvalComplement(ValMgr)));
         break;
       }
         
@@ -635,14 +647,18 @@
         RValue V1 = GetValue(St, U->getSubExpr());
         
         if (isa<LValue>(V1)) {
-          lval::ConcreteInt V2(ValMgr.getValue(0, U->getSubExpr()->getType()));
-          Nodify(Dst, U, N1, SetValue(St, U,
-                                      cast<LValue>(V1).EQ(ValMgr, V2)));
+          const LValue& L1 = cast<LValue>(V1);
+          lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
+          Nodify(Dst, U, N1,
+                 SetValue(St, U, L1.EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+                                                 V2)));
         }
         else {
+          const NonLValue& R1 = cast<NonLValue>(V1);
           nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
-          Nodify(Dst, U, N1, SetValue(St, U,
-                                      cast<NonLValue>(V1).EQ(ValMgr, V2)));
+          Nodify(Dst, U, N1,
+                 SetValue(St, U, R1.EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+                                                 V2)));
         }
         
         break;
@@ -687,122 +703,63 @@
     Visit(B->getRHS(), N1, S2);
   
     for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
+
       NodeTy* N2 = *I2;
       StateTy St = N2->getState();
       const RValue& V2 = GetValue(St, B->getRHS());
 
-      switch (B->getOpcode()) {
-        default: 
-          Dst.Add(N2);
-          break;
-          
-        // Arithmetic operators.
-          
-        case BinaryOperator::Add: {
-          const NonLValue& R1 = cast<NonLValue>(V1);
-          const NonLValue& R2 = cast<NonLValue>(V2);
-          
-          Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
-          break;
-        }
-
-        case BinaryOperator::Sub: {
-          const NonLValue& R1 = cast<NonLValue>(V1);
-          const NonLValue& R2 = cast<NonLValue>(V2);
-	        Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
-          break;
-        }
-          
-        case BinaryOperator::Mul: {
-          const NonLValue& R1 = cast<NonLValue>(V1);
-          const NonLValue& R2 = cast<NonLValue>(V2);
-	        Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
-          break;
-        }
+      BinaryOperator::Opcode Op = B->getOpcode();
+      
+      if (Op <= BinaryOperator::Or) {
+        
+        if (isa<LValue>(V1)) {
+          // FIXME: Add support for RHS being a non-lvalue.
+          const LValue& L1 = cast<LValue>(V1);
+          const LValue& L2 = cast<LValue>(V2);
           
-        case BinaryOperator::Div: {
-          const NonLValue& R1 = cast<NonLValue>(V1);
-          const NonLValue& R2 = cast<NonLValue>(V2);
-	        Nodify(Dst, B, N2, SetValue(St, B, R1.Div(ValMgr, R2)));
-          break;
+          Nodify(Dst, B, N2, SetValue(St, B, L1.EvalBinaryOp(ValMgr, Op, L2)));
         }
-          
-        case BinaryOperator::Rem: {
+        else {
           const NonLValue& R1 = cast<NonLValue>(V1);
           const NonLValue& R2 = cast<NonLValue>(V2);
-	        Nodify(Dst, B, N2, SetValue(St, B, R1.Rem(ValMgr, R2)));
-          break;
+            
+          Nodify(Dst, B, N2, SetValue(St, B, R1.EvalBinaryOp(ValMgr, Op, R2)));
         }
-          
-        // Assignment operators.
-          
+        
+        continue;
+      }
+      
+      switch (Op) {
         case BinaryOperator::Assign: {
           const LValue& L1 = cast<LValue>(V1);
           Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2));
           break;
         }
+
+        default: { // Compound assignment operators.
           
-        case BinaryOperator::AddAssign: {
-          const LValue& L1 = cast<LValue>(V1);
-          NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
-          NonLValue Result = R1.Add(ValMgr, cast<NonLValue>(V2));
-          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
-          break;
-        }
-          
-        case BinaryOperator::SubAssign: {
-          const LValue& L1 = cast<LValue>(V1);
-          NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
-          NonLValue Result = R1.Sub(ValMgr, cast<NonLValue>(V2));
-          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
-          break;
-        }
-          
-        case BinaryOperator::MulAssign: {
-          const LValue& L1 = cast<LValue>(V1);
-          NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
-          NonLValue Result = R1.Mul(ValMgr, cast<NonLValue>(V2));
-          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
-          break;
-        }
-          
-        case BinaryOperator::DivAssign: {
-          const LValue& L1 = cast<LValue>(V1);
-          NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
-          NonLValue Result = R1.Div(ValMgr, cast<NonLValue>(V2));
-          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
-          break;
-        }
-          
-        case BinaryOperator::RemAssign: {
+          assert (B->isCompoundAssignmentOp());
+                          
           const LValue& L1 = cast<LValue>(V1);
-          NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
-          NonLValue Result = R1.Rem(ValMgr, cast<NonLValue>(V2));
-          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
-          break;
-        }
+          RValue Result = cast<NonLValue>(InvalidValue());
           
-        // Equality operators.
-
-        case BinaryOperator::EQ:
-          // FIXME: should we allow XX.EQ() to return a set of values,
-          //  allowing state bifurcation?  In such cases, they will also
-          //  modify the state (meaning that a new state will be returned
-          //  as well).
-          assert (B->getType() == getContext().IntTy);
+          Op = (BinaryOperator::Opcode)
+                  (((unsigned) Op) - ((unsigned) BinaryOperator::MulAssign));
           
-          if (isa<LValue>(V1)) {
-            const LValue& L1 = cast<LValue>(V1);
+          if (isa<LValue>(V2)) {
+            // FIXME: Add support for Non-LValues on RHS.
             const LValue& L2 = cast<LValue>(V2);
-            Nodify(Dst, B, N2, SetValue(St, B, L1.EQ(ValMgr, L2)));
+            Result = L1.EvalBinaryOp(ValMgr, Op, L2);
           }
           else {
-            const NonLValue& R1 = cast<NonLValue>(V1);
+            const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
             const NonLValue& R2 = cast<NonLValue>(V2);
-            Nodify(Dst, B, N2, SetValue(St, B, R1.EQ(ValMgr, R2)));
+            Result = R1.EvalBinaryOp(ValMgr, Op, R2);
           }
           
+          Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
           break;
+        }
       }
     }
   }

Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=46831&r1=46830&r2=46831&view=diff

==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Wed Feb  6 16:50:25 2008
@@ -115,37 +115,157 @@
 // Transfer function for Casts.
 //===----------------------------------------------------------------------===//
 
-RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
+RValue RValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
   switch (getBaseKind()) {
     default: assert(false && "Invalid RValue."); break;
-    case LValueKind: return cast<LValue>(this)->Cast(ValMgr, CastExpr);
-    case NonLValueKind: return cast<NonLValue>(this)->Cast(ValMgr, CastExpr);      
+    case LValueKind: return cast<LValue>(this)->EvalCast(ValMgr, CastExpr);
+    case NonLValueKind: return cast<NonLValue>(this)->EvalCast(ValMgr, CastExpr);      
     case UninitializedKind: case InvalidKind: break;
   }
   
   return *this;
 }
  
-RValue LValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
-  if (CastExpr->getType()->isPointerType())
-    return *this;
+
+//===----------------------------------------------------------------------===//
+// Transfer function dispatch for Non-LValues.
+//===----------------------------------------------------------------------===//
   
-  assert (CastExpr->getType()->isIntegerType());
+  // Binary Operators (except assignments and comma).
 
-  if (!isa<lval::ConcreteInt>(*this))
-    return InvalidValue();
+NonLValue NonLValue::EvalBinaryOp(ValueManager& ValMgr,
+                                  BinaryOperator::Opcode Op,
+                                  const NonLValue& RHS) const {
   
-  APSInt V = cast<lval::ConcreteInt>(this)->getValue();
-  QualType T = CastExpr->getType();
-  V.setIsUnsigned(T->isUnsignedIntegerType());
-  V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
-  return nonlval::ConcreteInt(ValMgr.getValue(V));
+  if (isa<InvalidValue>(this) || isa<InvalidValue>(RHS))
+    return cast<NonLValue>(InvalidValue());
+  
+  if (isa<UninitializedValue>(this) || isa<UninitializedValue>(RHS))
+    return cast<NonLValue>(UninitializedValue());
+  
+  switch (getSubKind()) {
+    default:
+      assert (false && "Binary Operators not implemented for this NonLValue");
+      
+    case nonlval::ConcreteIntKind:
+      
+      if (isa<nonlval::ConcreteInt>(RHS)) {
+        nonlval::ConcreteInt& self = cast<nonlval::ConcreteInt>(*this);
+        return self.EvalBinaryOp(ValMgr, Op,
+                                       cast<nonlval::ConcreteInt>(RHS));
+      }
+      else if(isa<InvalidValue>(RHS))
+        return cast<NonLValue>(InvalidValue());
+      else
+        return RHS.EvalBinaryOp(ValMgr, Op, *this);
+      
+    case nonlval::SymbolValKind: {
+      const nonlval::SymbolVal& self = cast<nonlval::SymbolVal>(*this);
+      
+      switch (RHS.getSubKind()) {
+        default: assert ("Not Implemented." && false);
+        case nonlval::ConcreteIntKind: {
+          const SymIntConstraint& C =
+            ValMgr.getConstraint(self.getSymbol(), Op,
+                                 cast<nonlval::ConcreteInt>(RHS).getValue());
+          
+          return nonlval::SymIntConstraintVal(C);
+        }
+      }
+    }
+  }
+}
+
+static const
+llvm::APSInt& EvaluateAPSInt(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+                             const llvm::APSInt& V1, const llvm::APSInt& V2) {
+  
+  switch (Op) {
+    default:
+      assert (false && "Invalid Opcode.");
+      
+    case BinaryOperator::Mul:
+      return ValMgr.getValue( V1 * V2 );
+      
+    case BinaryOperator::Div:
+      return ValMgr.getValue( V1 / V2 );
+      
+    case BinaryOperator::Rem:
+      return ValMgr.getValue( V1 % V2 );
+      
+    case BinaryOperator::Add:
+      return ValMgr.getValue( V1 + V2 );
+
+    case BinaryOperator::Sub:
+      return ValMgr.getValue( V1 - V2 );
+
+#if 0
+    case BinaryOperator::Shl:
+      return ValMgr.getValue( V1 << V2 );
+      
+    case BinaryOperator::Shr:
+      return ValMgr.getValue( V1 >> V2 );
+#endif     
+    
+    case BinaryOperator::LT:
+      return ValMgr.getTruthValue( V1 < V2 );
+      
+    case BinaryOperator::GT:
+      return ValMgr.getTruthValue( V1 > V2 );
+      
+    case BinaryOperator::LE:
+      return ValMgr.getTruthValue( V1 <= V2 );
+      
+    case BinaryOperator::GE:
+      return ValMgr.getTruthValue( V1 >= V2 );
+      
+    case BinaryOperator::EQ:
+      return ValMgr.getTruthValue( V1 == V2 );
+      
+    case BinaryOperator::NE:
+      return ValMgr.getTruthValue( V1 != V2 );
+      
+    // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
+      
+    case BinaryOperator::And:
+      return ValMgr.getValue( V1 & V2 );
+      
+    case BinaryOperator::Or:
+      return ValMgr.getValue( V1 | V2 );
+  }
+}
+
+nonlval::ConcreteInt
+nonlval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
+                                   BinaryOperator::Opcode Op,
+                                   const nonlval::ConcreteInt& RHS) const {
+
+  return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
+}
+
+
+  // Bitwise-Complement.
+
+NonLValue NonLValue::EvalComplement(ValueManager& ValMgr) const {
+  switch (getSubKind()) {
+    case nonlval::ConcreteIntKind:
+      return cast<nonlval::ConcreteInt>(this)->EvalComplement(ValMgr);
+    default:
+      return cast<NonLValue>(InvalidValue());
+  }
 }
 
-RValue NonLValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
+nonlval::ConcreteInt
+nonlval::ConcreteInt::EvalComplement(ValueManager& ValMgr) const {
+  return ValMgr.getValue(~getValue()); 
+}
+
+  // Casts.
+
+RValue NonLValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
   if (!isa<nonlval::ConcreteInt>(this))
     return InvalidValue();
-    
+  
   APSInt V = cast<nonlval::ConcreteInt>(this)->getValue();
   QualType T = CastExpr->getType();
   V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
@@ -157,123 +277,100 @@
     return nonlval::ConcreteInt(ValMgr.getValue(V));
 }
 
-//===----------------------------------------------------------------------===//
-// Transfer function dispatch for Non-LValues.
-//===----------------------------------------------------------------------===//
+  // Unary Minus.
 
-NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
+NonLValue NonLValue::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
   switch (getSubKind()) {
     case nonlval::ConcreteIntKind:
-      return cast<nonlval::ConcreteInt>(this)->UnaryMinus(ValMgr, U);
+      return cast<nonlval::ConcreteInt>(this)->EvalMinus(ValMgr, U);
     default:
       return cast<NonLValue>(InvalidValue());
   }
 }
 
-NonLValue NonLValue::BitwiseComplement(ValueManager& ValMgr) const {
-  switch (getSubKind()) {
-    case nonlval::ConcreteIntKind:
-      return cast<nonlval::ConcreteInt>(this)->BitwiseComplement(ValMgr);
-    default:
-      return cast<NonLValue>(InvalidValue());
-  }
+nonlval::ConcreteInt
+nonlval::ConcreteInt::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
+  assert (U->getType() == U->getSubExpr()->getType());  
+  assert (U->getType()->isIntegerType());  
+  return ValMgr.getValue(-getValue()); 
 }
 
+//===----------------------------------------------------------------------===//
+// Transfer function dispatch for LValues.
+//===----------------------------------------------------------------------===//
 
-#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\
-case (k1##Kind*nonlval::NumKind+k2##Kind):\
-return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
-
-#define NONLVALUE_DISPATCH(Op)\
-switch (getSubKind()*nonlval::NumKind+RHS.getSubKind()){\
-NONLVALUE_DISPATCH_CASE(nonlval::ConcreteInt,nonlval::ConcreteInt,Op)\
-default:\
-if (getBaseKind() == UninitializedKind ||\
-RHS.getBaseKind() == UninitializedKind)\
-return cast<NonLValue>(UninitializedValue());\
-assert (!isValid() || !RHS.isValid() && "Missing case.");\
-break;\
-}\
-return cast<NonLValue>(InvalidValue());
-
-NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(Add)
-}
-
-NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(Sub)
-}
-
-NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(Mul)
-}
+  // Binary Operators (except assignments and comma).
 
-NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(Div)
-}
-
-NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(Rem)
+RValue LValue::EvalBinaryOp(ValueManager& ValMgr, 
+                                  BinaryOperator::Opcode Op,
+                                  const LValue& RHS) const {
+  
+  switch (Op) {
+    default:
+      assert (false && "Not yet implemented.");
+      
+    case BinaryOperator::EQ:
+      return EQ(ValMgr, RHS);
+    
+    case BinaryOperator::NE:
+      return NE(ValMgr, RHS);
+  }
 }
 
-NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const {  
-  NONLVALUE_DISPATCH(EQ)
-}
 
-NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const {
-  NONLVALUE_DISPATCH(NE)
+lval::ConcreteInt
+lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
+                                BinaryOperator::Opcode Op,
+                                const lval::ConcreteInt& RHS) const {
+  
+  assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
+          (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
+  
+  return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
 }
 
-#undef NONLVALUE_DISPATCH_CASE
-#undef NONLVALUE_DISPATCH
-
-//===----------------------------------------------------------------------===//
-// Transfer function dispatch for LValues.
-//===----------------------------------------------------------------------===//
-
-
 NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
   switch (getSubKind()) {
     default:
       assert(false && "EQ not implemented for this LValue.");
       return cast<NonLValue>(InvalidValue());
-    
+      
     case lval::ConcreteIntKind:
       if (isa<lval::ConcreteInt>(RHS)) {
         bool b = cast<lval::ConcreteInt>(this)->getValue() ==
-                 cast<lval::ConcreteInt>(RHS).getValue();
-              
+        cast<lval::ConcreteInt>(RHS).getValue();
+        
         return NonLValue::GetIntTruthValue(ValMgr, b);
       }
       else if (isa<lval::SymbolVal>(RHS)) {
-
+        
         const SymIntConstraint& C =
-          ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
-                               BinaryOperator::EQ,
-                               cast<lval::ConcreteInt>(this)->getValue());
+        ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(),
+                             BinaryOperator::EQ,
+                             cast<lval::ConcreteInt>(this)->getValue());
         
         return nonlval::SymIntConstraintVal(C);        
       }
       
       break;
       
-    case lval::SymbolValKind: {
-      if (isa<lval::ConcreteInt>(RHS)) {
-
-        const SymIntConstraint& C =
+      case lval::SymbolValKind: {
+        if (isa<lval::ConcreteInt>(RHS)) {
+          
+          const SymIntConstraint& C =
           ValMgr.getConstraint(cast<lval::SymbolVal>(this)->getSymbol(),
                                BinaryOperator::EQ,
                                cast<lval::ConcreteInt>(RHS).getValue());
+          
+          return nonlval::SymIntConstraintVal(C);
+        }
+        
+        assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
         
-        return nonlval::SymIntConstraintVal(C);
+        break;
       }
-
-      assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
       
-      break;
-    }
-      
-    case lval::DeclValKind:
+      case lval::DeclValKind:
       if (isa<lval::DeclVal>(RHS)) {        
         bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(RHS);
         return NonLValue::GetIntTruthValue(ValMgr, b);
@@ -294,7 +391,7 @@
     case lval::ConcreteIntKind:
       if (isa<lval::ConcreteInt>(RHS)) {
         bool b = cast<lval::ConcreteInt>(this)->getValue() !=
-                 cast<lval::ConcreteInt>(RHS).getValue();
+        cast<lval::ConcreteInt>(RHS).getValue();
         
         return NonLValue::GetIntTruthValue(ValMgr, b);
       }
@@ -338,6 +435,23 @@
   return NonLValue::GetIntTruthValue(ValMgr, true);
 }
 
+  // Casts.
+
+RValue LValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
+  if (CastExpr->getType()->isPointerType())
+    return *this;
+  
+  assert (CastExpr->getType()->isIntegerType());
+  
+  if (!isa<lval::ConcreteInt>(*this))
+    return InvalidValue();
+  
+  APSInt V = cast<lval::ConcreteInt>(this)->getValue();
+  QualType T = CastExpr->getType();
+  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
+  V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
+  return nonlval::ConcreteInt(ValMgr.getValue(V));
+}
 
 //===----------------------------------------------------------------------===//
 // Utility methods for constructing Non-LValues.
@@ -354,6 +468,10 @@
                                    I->getType()->isUnsignedIntegerType())));
 }
 
+NonLValue NonLValue::GetIntTruthValue(ValueManager& ValMgr, bool b) {
+  return nonlval::ConcreteInt(ValMgr.getTruthValue(b));
+}
+
 RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
   QualType T = D->getType();
   
@@ -363,6 +481,8 @@
     return nonlval::SymbolVal(SymMgr.getSymbol(D));
 }
 
+
+
 //===----------------------------------------------------------------------===//
 // Pretty-Printing.
 //===----------------------------------------------------------------------===//
@@ -402,6 +522,10 @@
   switch (getSubKind()) {  
     case nonlval::ConcreteIntKind:
       Out << cast<nonlval::ConcreteInt>(this)->getValue().toString();
+
+      if (cast<nonlval::ConcreteInt>(this)->getValue().isUnsigned())
+        Out << 'U';
+      
       break;
       
     case nonlval::SymbolValKind:
@@ -415,6 +539,10 @@
       Out << '$' << C.getConstraint().getSymbol() << ' ';
       printOpcode(Out, C.getConstraint().getOpcode());
       Out << ' ' << C.getConstraint().getInt().toString();
+      
+      if (C.getConstraint().getInt().isUnsigned())
+        Out << 'U';
+      
       break;
     }  
       

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

==============================================================================
--- cfe/trunk/Analysis/RValues.h (original)
+++ cfe/trunk/Analysis/RValues.h Wed Feb  6 16:50:25 2008
@@ -150,13 +150,23 @@
   ~ValueManager();
   
   ASTContext& getContext() const { return Ctx; }  
+
   const llvm::APSInt& getValue(const llvm::APSInt& X);
   const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
   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);
+    return getValue( 0,
+                     Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
+                     true );
+  }
+  
+  inline const llvm::APSInt& getTruthValue(bool b) {
+    return getValue( b ? 1 : 0,
+                     Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
+                     false );
+    
   }
   
   const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
@@ -228,7 +238,7 @@
   typedef llvm::SmallVector<RValue,5> BufferTy;
 
   
-  RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
+  RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
   
   unsigned getRawKind() const { return Kind; }
   BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
@@ -245,6 +255,7 @@
   
   static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
   
+  
   inline bool isValid() const { return getRawKind() != InvalidKind; }
   inline bool isInvalid() const { return getRawKind() == InvalidKind; }
   
@@ -280,21 +291,13 @@
 public:
   void print(std::ostream& Out) const;
   
-  RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
-
-  // Arithmetic operators.
-  NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
-  NonLValue BitwiseComplement(ValueManager& ValMgr) const;
-  
-  // Equality operators.
-  NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
-  NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
-  
+  NonLValue EvalBinaryOp(ValueManager& ValMgr,
+                               BinaryOperator::Opcode Op,
+                               const NonLValue& RHS) const;
+
+  RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
+  NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
+  NonLValue EvalComplement(ValueManager& ValMgr) const;
   
   // Utility methods to create NonLValues.
   static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
@@ -302,10 +305,8 @@
   
   static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
   
-  static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
-    return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
-  }
-  
+  static NonLValue GetIntTruthValue(ValueManager& ValMgr, bool b);
+    
   // Implement isa<T> support.
   static inline bool classof(const RValue* V) {
     return V->getBaseKind() >= NonLValueKind;
@@ -316,16 +317,19 @@
 protected:
   LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D), 
                                                    true, SubKind) {}
-  
-public:
-  void print(std::ostream& Out) const;
-  
-  RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const;
 
   // Equality operators.
   NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
   NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
   
+public:
+  void print(std::ostream& Out) const;
+
+  RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+                            const LValue& RHS) const;
+  
+  RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
+  
   // Implement isa<T> support.
   static inline bool classof(const RValue* V) {
     return V->getBaseKind() == LValueKind;
@@ -380,67 +384,22 @@
       return *static_cast<llvm::APSInt*>(getRawPtr());
     }
     
-    // Arithmetic operators.
-    
-    ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() + V.getValue());
-    }
+    // Transfer functions for binary/unary operations on ConcreteInts.
+    ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
+                             BinaryOperator::Opcode Op,
+                             const ConcreteInt& RHS) const;
     
-    ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() - V.getValue());
-    }
-    
-    ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() * V.getValue());
-    }
-    
-    ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() / V.getValue());
-    }
-    
-    ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() % V.getValue());
-    }
-    
-    ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
-      assert (U->getType() == U->getSubExpr()->getType());  
-      assert (U->getType()->isIntegerType());  
-      return ValMgr.getValue(-getValue()); 
-    }
-    
-    ConcreteInt BitwiseComplement(ValueManager& ValMgr) const {
-      return ValMgr.getValue(~getValue()); 
-    }
-    
-    // Casting.
-    
-    ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
-      assert (CastExpr->getType()->isIntegerType());
-      
-      llvm::APSInt X(getValue());  
-      X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(),
-                                                   CastExpr->getLocStart()));
-      return ValMgr.getValue(X);
-    }
-    
-    // Equality operators.
-    
-    ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
-      const llvm::APSInt& Val = getValue();    
-      return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
-                             Val.getBitWidth(), Val.isUnsigned());
-    }
-    
-    ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
-      const llvm::APSInt& Val = getValue();    
-      return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
-                             Val.getBitWidth(), Val.isUnsigned());
-    }
+    ConcreteInt EvalComplement(ValueManager& ValMgr) const;
+    ConcreteInt EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const;
     
     // Implement isa<T> support.
     static inline bool classof(const RValue* V) {
       return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind;
     }
+    
+    static inline bool classof(const NonLValue* V) {
+      return V->getSubKind() == ConcreteIntKind;
+    }
   };
   
 } // end namespace clang::nonlval
@@ -500,34 +459,21 @@
       return *static_cast<llvm::APSInt*>(getRawPtr());
     }
     
-    // Arithmetic operators.
-    
-    ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() + V.getValue());
-    }
-    
-    ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
-      return ValMgr.getValue(getValue() - V.getValue());
-    }
-    
-    // Equality operators.
-    
-    ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
-      const llvm::APSInt& Val = getValue();    
-      return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
-                             Val.getBitWidth(), Val.isUnsigned());
-    }
-    
-    ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
-      const llvm::APSInt& Val = getValue();    
-      return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
-                             Val.getBitWidth(), Val.isUnsigned());
-    }
-    
+
+    // Transfer functions for binary/unary operations on ConcreteInts.
+    ConcreteInt EvalBinaryOp(ValueManager& ValMgr,
+                             BinaryOperator::Opcode Op,
+                             const ConcreteInt& RHS) const;
+        
     // Implement isa<T> support.
     static inline bool classof(const RValue* V) {
+      return isa<LValue>(V) && V->getSubKind() == ConcreteIntKind;
+    }
+    
+    static inline bool classof(const LValue* V) {
       return V->getSubKind() == ConcreteIntKind;
     }
+    
   };  
 } // end clang::lval namespace
   





More information about the cfe-commits mailing list