Skip to content

Error handling cleanup in solvers/flattening #2897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions src/solvers/flattening/boolbv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ bool boolbvt::literal(
throw "found no literal for expression";
}

const bvt &boolbvt::convert_bv(const exprt &expr)
const bvt &
boolbvt::convert_bv(const exprt &expr, optionalt<std::size_t> expected_width)
{
// check cache first
std::pair<bv_cachet::iterator, bool> cache_result=
Expand All @@ -123,18 +124,27 @@ const bvt &boolbvt::convert_bv(const exprt &expr)
// Iterators into hash_maps supposedly stay stable
// even though we are inserting more elements recursively.

cache_result.first->second=convert_bitvector(expr);
const bvt &bv = convert_bitvector(expr);

INVARIANT_WITH_DIAGNOSTICS(
!expected_width || bv.size() == *expected_width,
"bitvector width shall match the indicated expected width",
expr.find_source_location(),
irep_pretty_diagnosticst(expr));

cache_result.first->second = bv;

// check
forall_literals(it, cache_result.first->second)
{
if(freeze_all && !it->is_constant())
prop.set_frozen(*it);
if(it->var_no()==literalt::unused_var_no())
{
error() << "unused_var_no: " << expr.pretty() << eom;
assert(false);
}

INVARIANT_WITH_DIAGNOSTICS(
it->var_no() != literalt::unused_var_no(),
"variable number must be different from the unused variable number",
expr.find_source_location(),
irep_pretty_diagnosticst(expr));
}

return cache_result.first->second;
Expand Down Expand Up @@ -231,7 +241,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
else if(expr.id()==ID_floatbv_typecast)
return convert_floatbv_typecast(to_floatbv_typecast_expr(expr));
else if(expr.id()==ID_concatenation)
return convert_concatenation(expr);
return convert_concatenation(to_concatenation_expr(expr));
else if(expr.id()==ID_replication)
return convert_replication(to_replication_expr(expr));
else if(expr.id()==ID_extractbits)
Expand Down Expand Up @@ -273,7 +283,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
else if(expr.id()==ID_vector)
return convert_vector(expr);
else if(expr.id()==ID_complex)
return convert_complex(expr);
return convert_complex(to_complex_expr(expr));
else if(expr.id()==ID_complex_real)
return convert_complex_real(to_complex_real_expr(expr));
else if(expr.id()==ID_complex_imag)
Expand Down
14 changes: 9 additions & 5 deletions src/solvers/flattening/boolbv.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ Author: Daniel Kroening, [email protected]
// convert expression to boolean formula
//

#include <util/mp_arith.h>
#include <util/expr.h>
#include <util/byte_operators.h>
#include <util/expr.h>
#include <util/mp_arith.h>
#include <util/optional.h>

#include "bv_utils.h"
#include "boolbv_width.h"
Expand All @@ -43,7 +44,10 @@ class boolbvt:public arrayst
{
}

virtual const bvt &convert_bv(const exprt &expr); // check cache
virtual const bvt &convert_bv( // check cache
const exprt &expr,
const optionalt<std::size_t> expected_width = nullopt);

virtual bvt convert_bitvector(const exprt &expr); // no cache

// overloading
Expand Down Expand Up @@ -139,7 +143,7 @@ class boolbvt:public arrayst
virtual bvt convert_struct(const struct_exprt &expr);
virtual bvt convert_array(const exprt &expr);
virtual bvt convert_vector(const exprt &expr);
virtual bvt convert_complex(const exprt &expr);
virtual bvt convert_complex(const complex_exprt &expr);
virtual bvt convert_complex_real(const complex_real_exprt &expr);
virtual bvt convert_complex_imag(const complex_imag_exprt &expr);
virtual bvt convert_lambda(const exprt &expr);
Expand All @@ -162,7 +166,7 @@ class boolbvt:public arrayst
virtual bvt convert_bitwise(const exprt &expr);
virtual bvt convert_unary_minus(const unary_exprt &expr);
virtual bvt convert_abs(const abs_exprt &expr);
virtual bvt convert_concatenation(const exprt &expr);
virtual bvt convert_concatenation(const concatenation_exprt &expr);
virtual bvt convert_replication(const replication_exprt &expr);
virtual bvt convert_bv_literals(const exprt &expr);
virtual bvt convert_constant(const constant_exprt &expr);
Expand Down
50 changes: 27 additions & 23 deletions src/solvers/flattening/boolbv_add_sub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Author: Daniel Kroening, [email protected]

bvt boolbvt::convert_add_sub(const exprt &expr)
{
PRECONDITION(
expr.id() == ID_plus || expr.id() == ID_minus ||
expr.id() == "no-overflow-plus" || expr.id() == "no-overflow-minus");

const typet &type=ns.follow(expr.type());

if(type.id()!=ID_unsignedbv &&
Expand All @@ -33,17 +37,15 @@ bvt boolbvt::convert_add_sub(const exprt &expr)

const exprt::operandst &operands=expr.operands();

if(operands.empty())
throw "operator "+expr.id_string()+" takes at least one operand";
DATA_INVARIANT(
!operands.empty(),
"operator " + expr.id_string() + " takes at least one operand");

const exprt &op0=expr.op0();
DATA_INVARIANT(
op0.type() == type, "add/sub with mixed types:\n" + expr.pretty());

bvt bv=convert_bv(op0);

if(bv.size()!=width)
throw "convert_add_sub: unexpected operand 0 width";
bvt bv = convert_bv(op0, width);

bool subtract=(expr.id()==ID_minus ||
expr.id()=="no-overflow-minus");
Expand All @@ -67,19 +69,16 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
DATA_INVARIANT(
it->type() == type, "add/sub with mixed types:\n" + expr.pretty());

const bvt &op=convert_bv(*it);

if(op.size()!=width)
throw "convert_add_sub: unexpected operand width";
const bvt &op = convert_bv(*it, width);

if(type.id()==ID_vector || type.id()==ID_complex)
{
const typet &subtype=ns.follow(type.subtype());

std::size_t sub_width=boolbv_width(subtype);
std::size_t sub_width = boolbv_width(type.subtype());

if(sub_width==0 || width%sub_width!=0)
throw "convert_add_sub: unexpected vector operand width";
INVARIANT(sub_width != 0, "vector elements shall have nonzero bit width");
INVARIANT(
width % sub_width == 0,
"total vector bit width shall be a multiple of the element bit width");

std::size_t size=width/sub_width;
bv.resize(width);
Expand All @@ -91,34 +90,39 @@ bvt boolbvt::convert_add_sub(const exprt &expr)

for(std::size_t j=0; j<tmp_op.size(); j++)
{
assert(i*sub_width+j<op.size());
tmp_op[j]=op[i*sub_width+j];
const std::size_t index = i * sub_width + j;
INVARIANT(index < op.size(), "bit index shall be within bounds");
tmp_op[j] = op[index];
}

bvt tmp_result;
tmp_result.resize(sub_width);

for(std::size_t j=0; j<tmp_result.size(); j++)
{
assert(i*sub_width+j<bv.size());
tmp_result[j]=bv[i*sub_width+j];
const std::size_t index = i * sub_width + j;
INVARIANT(index < bv.size(), "bit index shall be within bounds");
tmp_result[j] = bv[index];
}

if(type.subtype().id()==ID_floatbv)
{
// needs to change due to rounding mode
float_utilst float_utils(prop, to_floatbv_type(subtype));
float_utilst float_utils(prop, to_floatbv_type(type.subtype()));
tmp_result=float_utils.add_sub(tmp_result, tmp_op, subtract);
}
else
tmp_result=bv_utils.add_sub(tmp_result, tmp_op, subtract);

assert(tmp_result.size()==sub_width);
INVARIANT(
tmp_result.size() == sub_width,
"applying the add/sub operation shall not change the bitwidth");

for(std::size_t j=0; j<tmp_result.size(); j++)
{
assert(i*sub_width+j<bv.size());
bv[i*sub_width+j]=tmp_result[j];
const std::size_t index = i * sub_width + j;
INVARIANT(index < bv.size(), "bit index shall be within bounds");
bv[index] = tmp_result[j];
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/solvers/flattening/boolbv_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ Author: Daniel Kroening, [email protected]

\*******************************************************************/


#include "boolbv.h"

#include <util/invariant.h>

bvt boolbvt::convert_array(const exprt &expr)
{
std::size_t width=boolbv_width(expr.type());
Expand All @@ -18,20 +19,19 @@ bvt boolbvt::convert_array(const exprt &expr)

if(expr.type().id()==ID_array)
{
assert(expr.has_operands());
DATA_INVARIANT(
expr.has_operands(),
"the bit width being nonzero implies that the array has a nonzero size "
"in which case the array shall have operands");
const exprt::operandst &operands=expr.operands();
assert(!operands.empty());
std::size_t op_width=width/operands.size();

bvt bv;
bv.reserve(width);

forall_expr(it, operands)
{
const bvt &tmp=convert_bv(*it);

if(tmp.size()!=op_width)
throw "convert_array: unexpected operand width";
const bvt &tmp = convert_bv(*it, op_width);

forall_literals(it2, tmp)
bv.push_back(*it2);
Expand Down
27 changes: 16 additions & 11 deletions src/solvers/flattening/boolbv_array_of.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Author: Daniel Kroening, [email protected]
#include "boolbv.h"

#include <util/arith_tools.h>
#include <util/invariant.h>
#include <util/std_types.h>

bvt boolbvt::convert_array_of(const array_of_exprt &expr)
{
if(expr.type().id()!=ID_array)
throw "array_of must be array-typed";
DATA_INVARIANT(
expr.type().id() == ID_array, "array_of expression shall have array type");

const array_typet &array_type=to_array_type(expr.type());

Expand Down Expand Up @@ -42,21 +43,25 @@ bvt boolbvt::convert_array_of(const array_of_exprt &expr)

const bvt &tmp=convert_bv(expr.op0());

INVARIANT(
size * tmp.size() == width,
"total array bit width shall equal the number of elements times the "
"element bit with");

bvt bv;
bv.resize(width);

if(size*tmp.size()!=width)
throw "convert_array_of: unexpected operand width";

std::size_t offset=0;
auto b_it = tmp.begin();

for(mp_integer i=0; i<size; i=i+1)
for(auto &b : bv)
{
for(std::size_t j=0; j<tmp.size(); j++, offset++)
bv[offset]=tmp[j];
}
b = *b_it;

assert(offset==bv.size());
b_it++;

if(b_it == tmp.end())
b_it = tmp.begin();
}

return bv;
}
6 changes: 2 additions & 4 deletions src/solvers/flattening/boolbv_bitwise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ bvt boolbvt::convert_bitwise(const exprt &expr)
{
DATA_INVARIANT(expr.operands().size() == 1, "bitnot takes one operand");
const exprt &op0=expr.op0();
const bvt &op_bv=convert_bv(op0);
CHECK_RETURN(op_bv.size() == width);
const bvt &op_bv = convert_bv(op0, width);
return bv_utils.inverted(op_bv);
}
else if(expr.id()==ID_bitand || expr.id()==ID_bitor ||
Expand All @@ -33,8 +32,7 @@ bvt boolbvt::convert_bitwise(const exprt &expr)

forall_operands(it, expr)
{
const bvt &op=convert_bv(*it);
CHECK_RETURN(op.size() == width);
const bvt &op = convert_bv(*it, width);

if(it==expr.operands().begin())
bv=op;
Expand Down
3 changes: 1 addition & 2 deletions src/solvers/flattening/boolbv_bswap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ bvt boolbvt::convert_bswap(const bswap_exprt &expr)
if(width % byte_bits != 0)
return conversion_failed(expr);

bvt result = convert_bv(expr.op());
CHECK_RETURN(result.size() == width);
bvt result = convert_bv(expr.op(), width);

std::size_t dest_base = width;

Expand Down
14 changes: 7 additions & 7 deletions src/solvers/flattening/boolbv_byte_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ Author: Daniel Kroening, [email protected]
#include "boolbv.h"

#include <iostream>
#include <cassert>

#include <util/arith_tools.h>
#include <util/byte_operators.h>
#include <util/invariant.h>

#include "bv_endianness_map.h"

bvt boolbvt::convert_byte_update(const byte_update_exprt &expr)
{
if(expr.operands().size()!=3)
throw "byte_update takes three operands";

const exprt &op=expr.op0();
const exprt &op = expr.op();
const exprt &offset_expr=expr.offset();
const exprt &value=expr.value();

Expand Down Expand Up @@ -70,8 +67,11 @@ bvt boolbvt::convert_byte_update(const byte_update_exprt &expr)
size_t index_op=map_op.map_bit(offset_i+i);
size_t index_value=map_value.map_bit(i);

assert(index_op<bv.size());
assert(index_value<value_bv.size());
INVARIANT(
index_op < bv.size(), "bit vector index shall be within bounds");
INVARIANT(
index_value < value_bv.size(),
"bit vector index shall be within bounds");

bv[index_op]=value_bv[index_value];
}
Expand Down
Loading