ExprEngine: ExprData::getConstraintExpr

This commit is contained in:
Daniel Marjamäki 2019-10-06 14:47:34 +02:00
parent 78b9fd9bb9
commit dcf8a7213f
1 changed files with 82 additions and 77 deletions

View File

@ -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;