[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