forked from OSchip/llvm-project
Migrated transfer functions for binary operators for simple value tracking
from RValues to GRTransferFuncs/GRSimpleVals. llvm-svn: 47131
This commit is contained in:
parent
99a59b6ba0
commit
cf7cf8e8b0
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue