Migrated transfer functions for binary operators for simple value tracking

from RValues to GRTransferFuncs/GRSimpleVals.

llvm-svn: 47131
This commit is contained in:
Ted Kremenek 2008-02-14 19:37:24 +00:00
parent 99a59b6ba0
commit cf7cf8e8b0
7 changed files with 227 additions and 91 deletions

View File

@ -333,6 +333,16 @@ public:
inline NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) {
return TF.EvalComplement(ValMgr, X);
}
inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) {
return TF.EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
LValue LHS, LValue RHS) {
return TF.EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
};
} // end anonymous namespace
@ -555,13 +565,12 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
do {
nonlval::ConcreteInt CaseVal(ValMgr.getValue(V1));
NonLValue Result =
CondV.EvalBinaryOp(ValMgr, BinaryOperator::EQ, CaseVal);
NonLValue Res = EvalBinaryOp(ValMgr, BinaryOperator::EQ, CondV, CaseVal);
// Now "assume" that the case matches.
bool isFeasible;
StateTy StNew = Assume(St, Result, true, isFeasible);
StateTy StNew = Assume(St, Res, true, isFeasible);
if (isFeasible) {
builder.generateCaseStmtNode(I, StNew);
@ -576,7 +585,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// Now "assume" that the case doesn't match. Add this state
// to the default state (if it is feasible).
StNew = Assume(DefaultSt, Result, false, isFeasible);
StNew = Assume(DefaultSt, Res, false, isFeasible);
if (isFeasible)
DefaultSt = StNew;
@ -805,8 +814,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
const LValue& L1 = GetLValue(St, U->getSubExpr());
NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add,
GetRValueConstant(1U, U));
NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add,
R1, GetRValueConstant(1U, U));
Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
break;
@ -816,8 +825,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
const LValue& L1 = GetLValue(St, U->getSubExpr());
NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub,
GetRValueConstant(1U, U));
NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub,
R1, GetRValueConstant(1U, U));
Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
break;
@ -827,8 +836,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
const LValue& L1 = GetLValue(St, U->getSubExpr());
NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add,
GetRValueConstant(1U, U));
NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add,
R1, GetRValueConstant(1U, U));
Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
break;
@ -838,8 +847,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
const LValue& L1 = GetLValue(St, U->getSubExpr());
NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub,
GetRValueConstant(1U, U));
NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub,
R1, GetRValueConstant(1U, U));
Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
break;
@ -869,15 +878,15 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
const LValue& L1 = cast<LValue>(V1);
lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
Nodify(Dst, U, N1,
SetValue(St, U, L1.EvalBinaryOp(ValMgr, BinaryOperator::EQ,
V2)));
SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
L1, V2)));
}
else {
const NonLValue& R1 = cast<NonLValue>(V1);
nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
Nodify(Dst, U, N1,
SetValue(St, U, R1.EvalBinaryOp(ValMgr, BinaryOperator::EQ,
V2)));
SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
R1, V2)));
}
break;
@ -1023,13 +1032,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
const LValue& L1 = cast<LValue>(V1);
const LValue& L2 = cast<LValue>(V2);
Nodify(Dst, B, N2, SetValue(St, B, L1.EvalBinaryOp(ValMgr, Op, L2)));
Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, L1, L2)));
}
else {
const NonLValue& R1 = cast<NonLValue>(V1);
const NonLValue& R2 = cast<NonLValue>(V2);
Nodify(Dst, B, N2, SetValue(St, B, R1.EvalBinaryOp(ValMgr, Op, R2)));
Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, R1, R2)));
}
continue;
@ -1058,12 +1067,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
if (isa<LValue>(V2)) {
// FIXME: Add support for Non-LValues on RHS.
const LValue& L2 = cast<LValue>(V2);
Result = L1.EvalBinaryOp(ValMgr, Op, L2);
Result = EvalBinaryOp(ValMgr, Op, L1, L2);
}
else {
const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
const NonLValue& R2 = cast<NonLValue>(V2);
Result = R1.EvalBinaryOp(ValMgr, Op, R2);
Result = EvalBinaryOp(ValMgr, Op, R1, R2);
}
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));

View File

@ -79,3 +79,161 @@ NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
return cast<NonLValue>(UnknownVal());
}
}
// Binary operators.
NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) {
if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
return cast<NonLValue>(UnknownVal());
if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
return cast<NonLValue>(UninitializedVal());
while(1) {
switch (LHS.getSubKind()) {
default:
return cast<NonLValue>(UnknownVal());
case nonlval::ConcreteIntKind:
if (isa<nonlval::ConcreteInt>(RHS)) {
const nonlval::ConcreteInt& LHS_CI = cast<nonlval::ConcreteInt>(LHS);
const nonlval::ConcreteInt& RHS_CI = cast<nonlval::ConcreteInt>(RHS);
return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI);
}
else if(isa<UnknownVal>(RHS))
return cast<NonLValue>(UnknownVal());
else {
NonLValue tmp = RHS;
RHS = LHS;
LHS = tmp;
continue;
}
case nonlval::SymbolValKind: {
if (isa<nonlval::ConcreteInt>(RHS)) {
const SymIntConstraint& C =
ValMgr.getConstraint(cast<nonlval::SymbolVal>(LHS).getSymbol(), Op,
cast<nonlval::ConcreteInt>(RHS).getValue());
return nonlval::SymIntConstraintVal(C);
}
else
return cast<NonLValue>(UnknownVal());
}
}
}
}
// Equality operators for LValues.
NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
switch (LHS.getSubKind()) {
default:
assert(false && "EQ not implemented for this LValue.");
return cast<NonLValue>(UnknownVal());
case lval::ConcreteIntKind:
if (isa<lval::ConcreteInt>(RHS)) {
bool b = cast<lval::ConcreteInt>(LHS).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>(LHS).getValue());
return nonlval::SymIntConstraintVal(C);
}
break;
case lval::SymbolValKind: {
if (isa<lval::ConcreteInt>(RHS)) {
const SymIntConstraint& C =
ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
BinaryOperator::EQ,
cast<lval::ConcreteInt>(RHS).getValue());
return nonlval::SymIntConstraintVal(C);
}
assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification.");
break;
}
case lval::DeclValKind:
if (isa<lval::DeclVal>(RHS)) {
bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
return NonLValue::GetIntTruthValue(ValMgr, b);
}
break;
}
return NonLValue::GetIntTruthValue(ValMgr, false);
}
NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
switch (LHS.getSubKind()) {
default:
assert(false && "NE not implemented for this LValue.");
return cast<NonLValue>(UnknownVal());
case lval::ConcreteIntKind:
if (isa<lval::ConcreteInt>(RHS)) {
bool b = cast<lval::ConcreteInt>(LHS).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::NE,
cast<lval::ConcreteInt>(LHS).getValue());
return nonlval::SymIntConstraintVal(C);
}
break;
case lval::SymbolValKind: {
if (isa<lval::ConcreteInt>(RHS)) {
const SymIntConstraint& C =
ValMgr.getConstraint(cast<lval::SymbolVal>(LHS).getSymbol(),
BinaryOperator::NE,
cast<lval::ConcreteInt>(RHS).getValue());
return nonlval::SymIntConstraintVal(C);
}
assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement sym !=.");
break;
}
case lval::DeclValKind:
if (isa<lval::DeclVal>(RHS)) {
bool b = cast<lval::DeclVal>(LHS) == cast<lval::DeclVal>(RHS);
return NonLValue::GetIntTruthValue(ValMgr, b);
}
break;
}
return NonLValue::GetIntTruthValue(ValMgr, true);
}

View File

@ -36,6 +36,16 @@ public:
NonLValue X);
virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X);
// Binary Operators.
virtual NonLValue EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS);
// Equality operators for LValues.
virtual NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS);
virtual NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS);
};

View File

@ -39,3 +39,21 @@ RValue GRTransferFuncs::EvalCast(ValueManager& ValMgr, RValue X,
return X;
}
// Binary Operators (except assignments and comma).
RValue GRTransferFuncs::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
LValue LHS, LValue RHS) {
switch (Op) {
default:
assert (false && "Not yet implemented.");
case BinaryOperator::EQ:
return EvalEQ(ValMgr, LHS, RHS);
case BinaryOperator::NE:
return EvalNE(ValMgr, LHS, RHS);
}
}

View File

@ -129,51 +129,6 @@ ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
//===----------------------------------------------------------------------===//
// Transfer function dispatch for Non-LValues.
//===----------------------------------------------------------------------===//
// Binary Operators (except assignments and comma).
NonLValue NonLValue::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
const NonLValue& RHS) const {
if (isa<UnknownVal>(this) || isa<UnknownVal>(RHS))
return cast<NonLValue>(UnknownVal());
if (isa<UninitializedVal>(this) || isa<UninitializedVal>(RHS))
return cast<NonLValue>(UninitializedVal());
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<UnknownVal>(RHS))
return cast<NonLValue>(UnknownVal());
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,
@ -262,25 +217,6 @@ nonlval::ConcreteInt::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const {
// Transfer function dispatch for LValues.
//===----------------------------------------------------------------------===//
// Binary Operators (except assignments and comma).
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);
}
}
lval::ConcreteInt
lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,

View File

@ -37,7 +37,19 @@ public:
virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) = 0;
// Binary Operators.
virtual NonLValue EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) = 0;
RValue EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
LValue LHS, LValue RHS);
// Equality operators for LValues.
virtual NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0;
virtual NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0;
};
} // end clang namespace

View File

@ -322,10 +322,6 @@ protected:
public:
void print(std::ostream& Out) const;
NonLValue EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
const NonLValue& RHS) const;
// Utility methods to create NonLValues.
static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
SourceLocation Loc = SourceLocation());
@ -351,9 +347,6 @@ protected:
public:
void print(std::ostream& Out) const;
RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
const LValue& RHS) const;
static LValue GetValue(AddrLabelExpr* E);