ExprEngine: ExprData::getConstraintExpr
This commit is contained in:
parent
78b9fd9bb9
commit
dcf8a7213f
|
@ -218,6 +218,8 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
void addConstraint(ExprEngine::ValuePtr condValue, bool trueCond) {
|
void addConstraint(ExprEngine::ValuePtr condValue, bool trueCond) {
|
||||||
|
if (!condValue)
|
||||||
|
return;
|
||||||
if (trueCond)
|
if (trueCond)
|
||||||
constraints.push_back(condValue);
|
constraints.push_back(condValue);
|
||||||
else
|
else
|
||||||
|
@ -485,6 +487,7 @@ std::string ExprEngine::IntegerTruncation::getSymbolicExpression() const
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_Z3
|
#ifdef USE_Z3
|
||||||
|
|
||||||
struct ExprData {
|
struct ExprData {
|
||||||
typedef std::map<std::string, z3::expr> ValueExpr;
|
typedef std::map<std::string, z3::expr> ValueExpr;
|
||||||
typedef std::vector<z3::expr> AssertionList;
|
typedef std::vector<z3::expr> AssertionList;
|
||||||
|
@ -497,14 +500,10 @@ struct ExprData {
|
||||||
for (auto assertExpr : assertionList)
|
for (auto assertExpr : assertionList)
|
||||||
solver.add(assertExpr);
|
solver.add(assertExpr);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
static z3::expr getExpr(ExprEngine::ValuePtr v, ExprData &exprData);
|
z3::expr getExpr(const ExprEngine::BinOpResult *b) {
|
||||||
|
auto op1 = getExpr(b->op1);
|
||||||
static z3::expr getExpr(const ExprEngine::BinOpResult *b, ExprData &exprData)
|
auto op2 = getExpr(b->op2);
|
||||||
{
|
|
||||||
auto op1 = getExpr(b->op1, exprData);
|
|
||||||
auto op2 = getExpr(b->op2, exprData);
|
|
||||||
|
|
||||||
if (b->binop == "+")
|
if (b->binop == "+")
|
||||||
return op1 + op2;
|
return op1 + op2;
|
||||||
|
@ -533,43 +532,49 @@ static z3::expr getExpr(const ExprEngine::BinOpResult *b, ExprData &exprData)
|
||||||
if (b->binop == "||")
|
if (b->binop == "||")
|
||||||
return op1 || op2;
|
return op1 || op2;
|
||||||
throw std::runtime_error("Internal error: Unhandled operator");
|
throw std::runtime_error("Internal error: Unhandled operator");
|
||||||
}
|
}
|
||||||
|
|
||||||
static z3::expr getExpr(ExprEngine::ValuePtr v, ExprData &exprData)
|
z3::expr getExpr(ExprEngine::ValuePtr v) {
|
||||||
{
|
|
||||||
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(v)) {
|
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(v)) {
|
||||||
if (intRange->name[0] != '$')
|
if (intRange->name[0] != '$')
|
||||||
return exprData.context.int_val(int64_t(intRange->minValue));
|
return context.int_val(int64_t(intRange->minValue));
|
||||||
auto it = exprData.valueExpr.find(v->name);
|
auto it = valueExpr.find(v->name);
|
||||||
if (it != exprData.valueExpr.end())
|
if (it != valueExpr.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
auto e = exprData.context.int_const(v->name.c_str());
|
auto e = context.int_const(v->name.c_str());
|
||||||
exprData.valueExpr.emplace(v->name, e);
|
valueExpr.emplace(v->name, e);
|
||||||
if (intRange->maxValue <= INT_MAX)
|
if (intRange->maxValue <= INT_MAX)
|
||||||
exprData.assertionList.push_back(e <= int(intRange->maxValue));
|
assertionList.push_back(e <= int(intRange->maxValue));
|
||||||
if (intRange->minValue >= INT_MIN)
|
if (intRange->minValue >= INT_MIN)
|
||||||
exprData.assertionList.push_back(e >= int(intRange->minValue));
|
assertionList.push_back(e >= int(intRange->minValue));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto b = std::dynamic_pointer_cast<ExprEngine::BinOpResult>(v)) {
|
if (auto b = std::dynamic_pointer_cast<ExprEngine::BinOpResult>(v)) {
|
||||||
return getExpr(b.get(), exprData);
|
return getExpr(b.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto c = std::dynamic_pointer_cast<ExprEngine::ConditionalValue>(v)) {
|
if (auto c = std::dynamic_pointer_cast<ExprEngine::ConditionalValue>(v)) {
|
||||||
if (c->values.size() == 1)
|
if (c->values.size() == 1)
|
||||||
return ::getExpr(c->values[0].second, exprData);
|
return getExpr(c->values[0].second);
|
||||||
|
|
||||||
return z3::ite(::getExpr(c->values[1].first, exprData),
|
return z3::ite(getExpr(c->values[1].first),
|
||||||
::getExpr(c->values[1].second, exprData),
|
getExpr(c->values[1].second),
|
||||||
::getExpr(c->values[0].second, exprData));
|
getExpr(c->values[0].second));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->type == ExprEngine::ValueType::UninitValue)
|
if (v->type == ExprEngine::ValueType::UninitValue)
|
||||||
return exprData.context.int_val(0);
|
return context.int_val(0);
|
||||||
|
|
||||||
throw std::runtime_error("Internal error: Unhandled value type");
|
throw std::runtime_error("Internal error: Unhandled value type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
z3::expr getConstraintExpr(ExprEngine::ValuePtr v) {
|
||||||
|
if (v->type == ExprEngine::ValueType::IntRange)
|
||||||
|
return (getExpr(v) != 0);
|
||||||
|
return getExpr(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ExprEngine::IntRange::isIntValueInRange(DataBase *dataBase, int value) const
|
bool ExprEngine::IntRange::isIntValueInRange(DataBase *dataBase, int value) const
|
||||||
|
@ -587,7 +592,7 @@ bool ExprEngine::IntRange::isIntValueInRange(DataBase *dataBase, int value) cons
|
||||||
z3::expr e = exprData.context.int_const(name.c_str());
|
z3::expr e = exprData.context.int_const(name.c_str());
|
||||||
exprData.valueExpr.emplace(name, e);
|
exprData.valueExpr.emplace(name, e);
|
||||||
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
||||||
solver.add(::getExpr(constraint, exprData));
|
solver.add(exprData.getConstraintExpr(constraint));
|
||||||
solver.add(e == value);
|
solver.add(e == value);
|
||||||
return solver.check() == z3::sat;
|
return solver.check() == z3::sat;
|
||||||
#else
|
#else
|
||||||
|
@ -601,10 +606,10 @@ bool ExprEngine::BinOpResult::isIntValueInRange(ExprEngine::DataBase *dataBase,
|
||||||
#ifdef USE_Z3
|
#ifdef USE_Z3
|
||||||
ExprData exprData;
|
ExprData exprData;
|
||||||
z3::solver solver(exprData.context);
|
z3::solver solver(exprData.context);
|
||||||
z3::expr e = ::getExpr(this, exprData);
|
z3::expr e = exprData.getExpr(this);
|
||||||
exprData.addAssertions(solver);
|
exprData.addAssertions(solver);
|
||||||
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
||||||
solver.add(::getExpr(constraint, exprData));
|
solver.add(exprData.getConstraintExpr(constraint));
|
||||||
solver.add(e == value);
|
solver.add(e == value);
|
||||||
return solver.check() == z3::sat;
|
return solver.check() == z3::sat;
|
||||||
#else
|
#else
|
||||||
|
@ -619,10 +624,10 @@ std::string ExprEngine::BinOpResult::getExpr(ExprEngine::DataBase *dataBase) con
|
||||||
#ifdef USE_Z3
|
#ifdef USE_Z3
|
||||||
ExprData exprData;
|
ExprData exprData;
|
||||||
z3::solver solver(exprData.context);
|
z3::solver solver(exprData.context);
|
||||||
z3::expr e = ::getExpr(this, exprData);
|
z3::expr e = exprData.getExpr(this);
|
||||||
exprData.addAssertions(solver);
|
exprData.addAssertions(solver);
|
||||||
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
for (auto constraint : dynamic_cast<const Data *>(dataBase)->constraints)
|
||||||
solver.add(::getExpr(constraint, exprData));
|
solver.add(exprData.getConstraintExpr(constraint));
|
||||||
solver.add(e);
|
solver.add(e);
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << solver;
|
os << solver;
|
||||||
|
|
Loading…
Reference in New Issue