Skip to content

Error handling cleanup in solvers/flattening 5 #2938

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
7 changes: 3 additions & 4 deletions src/solvers/flattening/boolbv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,8 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
expr.id()==ID_bitxnor || expr.id()==ID_bitnor ||
expr.id()==ID_bitnand)
return convert_bitwise(expr);
else if(expr.id()==ID_unary_minus ||
expr.id()=="no-overflow-unary-minus")
return convert_unary_minus(to_unary_expr(expr));
else if(expr.id() == ID_unary_minus)
return convert_unary_minus(to_unary_minus_expr(expr));
else if(expr.id()==ID_unary_plus)
{
return convert_bitvector(to_unary_plus_expr(expr).op());
Expand Down Expand Up @@ -281,7 +280,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
else if(expr.id()==ID_array)
return convert_array(expr);
else if(expr.id()==ID_vector)
return convert_vector(expr);
return convert_vector(to_vector_expr(expr));
else if(expr.id()==ID_complex)
return convert_complex(to_complex_expr(expr));
else if(expr.id()==ID_complex_real)
Expand Down
4 changes: 2 additions & 2 deletions src/solvers/flattening/boolbv.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class boolbvt:public arrayst
virtual bvt convert_if(const if_exprt &expr);
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_vector(const vector_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);
Expand All @@ -164,7 +164,7 @@ class boolbvt:public arrayst
virtual bvt convert_cond(const exprt &expr);
virtual bvt convert_shift(const binary_exprt &expr);
virtual bvt convert_bitwise(const exprt &expr);
virtual bvt convert_unary_minus(const unary_exprt &expr);
virtual bvt convert_unary_minus(const unary_minus_exprt &expr);
virtual bvt convert_abs(const abs_exprt &expr);
virtual bvt convert_concatenation(const concatenation_exprt &expr);
virtual bvt convert_replication(const replication_exprt &expr);
Expand Down
76 changes: 27 additions & 49 deletions src/solvers/flattening/boolbv_unary_minus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ Author: Daniel Kroening, [email protected]

#include <solvers/floatbv/float_utils.h>

#include <algorithm>
#include <iterator>

#include "boolbv_type.h"

bvt boolbvt::convert_unary_minus(const unary_exprt &expr)
bvt boolbvt::convert_unary_minus(const unary_minus_exprt &expr)
{
const typet &type=ns.follow(expr.type());

Expand All @@ -23,23 +26,12 @@ bvt boolbvt::convert_unary_minus(const unary_exprt &expr)
if(width==0)
return conversion_failed(expr);

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

if(operands.size()!=1)
throw "unary minus takes one operand";
const exprt &op = expr.op();

const exprt &op0=expr.op0();

const bvt &op_bv=convert_bv(op0);
const bvt &op_bv = convert_bv(op, width);

bvtypet bvtype=get_bvtype(type);
bvtypet op_bvtype=get_bvtype(op0.type());
std::size_t op_width=op_bv.size();

bool no_overflow=(expr.id()=="no-overflow-unary-minus");

if(op_width==0 || op_width!=width)
return conversion_failed(expr);
bvtypet op_bvtype = get_bvtype(op.type());

if(bvtype==bvtypet::IS_UNKNOWN &&
(type.id()==ID_vector || type.id()==ID_complex))
Expand All @@ -48,68 +40,54 @@ bvt boolbvt::convert_unary_minus(const unary_exprt &expr)

std::size_t sub_width=boolbv_width(subtype);

if(sub_width==0 || width%sub_width!=0)
throw "unary-: unexpected vector operand width";
INVARIANT(
sub_width > 0,
"bitvector representation of type needs to have at least one bit");

INVARIANT(
width % sub_width == 0,
"total bitvector width needs to be a multiple of the component bitvector "
"widths");

std::size_t size=width/sub_width;
bvt bv;
bv.resize(width);

for(std::size_t i=0; i<size; i++)
for(std::size_t sub_idx = 0; sub_idx < width; sub_idx += sub_width)
{
bvt tmp_op;
tmp_op.resize(sub_width);

for(std::size_t j=0; j<tmp_op.size(); j++)
{
assert(i*sub_width+j<op_bv.size());
tmp_op[j]=op_bv[i*sub_width+j];
}

bvt tmp_result;
const auto sub_it = std::next(op_bv.begin(), sub_idx);
std::copy_n(sub_it, sub_width, std::back_inserter(tmp_op));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure this is a good idea, but seems unrelated to the goal of the commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this has become a separate commit now.


if(type.subtype().id()==ID_floatbv)
if(type.subtype().id() == ID_floatbv)
{
float_utilst float_utils(prop, to_floatbv_type(subtype));
tmp_result=float_utils.negate(tmp_op);
tmp_op = float_utils.negate(tmp_op);
}
else
tmp_result=bv_utils.negate(tmp_op);
tmp_op = bv_utils.negate(tmp_op);

assert(tmp_result.size()==sub_width);
INVARIANT(
tmp_op.size() == sub_width,
"bitvector after negation shall have same bit width");

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];
}
std::copy(tmp_op.begin(), tmp_op.end(), std::back_inserter(bv));
}

return bv;
}
else if(bvtype==bvtypet::IS_FIXED && op_bvtype==bvtypet::IS_FIXED)
{
if(no_overflow)
return bv_utils.negate_no_overflow(op_bv);
else
return bv_utils.negate(op_bv);
return bv_utils.negate(op_bv);
}
else if(bvtype==bvtypet::IS_FLOAT && op_bvtype==bvtypet::IS_FLOAT)
{
assert(!no_overflow);
float_utilst float_utils(prop, to_floatbv_type(expr.type()));
return float_utils.negate(op_bv);
}
else if((op_bvtype==bvtypet::IS_SIGNED || op_bvtype==bvtypet::IS_UNSIGNED) &&
(bvtype==bvtypet::IS_SIGNED || bvtype==bvtypet::IS_UNSIGNED))
{
if(no_overflow)
prop.l_set_to(bv_utils.overflow_negate(op_bv), false);

if(no_overflow)
return bv_utils.negate_no_overflow(op_bv);
else
return bv_utils.negate(op_bv);
return bv_utils.negate(op_bv);
}

return conversion_failed(expr);
Expand Down
11 changes: 7 additions & 4 deletions src/solvers/flattening/boolbv_union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ bvt boolbvt::convert_union(const union_exprt &expr)

const bvt &op_bv=convert_bv(expr.op());

if(width<op_bv.size())
throw "union: unexpected operand op width";
INVARIANT(
op_bv.size() <= width,
"operand bitvector width shall not be larger than the width indicated by "
"the union type");

bvt bv;
bv.resize(width);
Expand All @@ -39,8 +41,9 @@ bvt boolbvt::convert_union(const union_exprt &expr)
}
else
{
assert(
config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_BIG_ENDIAN);
INVARIANT(
config.ansi_c.endianness == configt::ansi_ct::endiannesst::IS_BIG_ENDIAN,
"endianness should be set to either little endian or big endian");

bv_endianness_mapt map_u(expr.type(), false, ns, boolbv_width);
bv_endianness_mapt map_op(expr.op0().type(), false, ns, boolbv_width);
Expand Down
34 changes: 13 additions & 21 deletions src/solvers/flattening/boolbv_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,30 @@ Author: Daniel Kroening, [email protected]

#include "boolbv.h"

bvt boolbvt::convert_vector(const exprt &expr)
bvt boolbvt::convert_vector(const vector_exprt &expr)
{
std::size_t width=boolbv_width(expr.type());

if(width==0)
return conversion_failed(expr);

if(expr.type().id()==ID_vector)
{
const exprt::operandst &operands=expr.operands();

bvt bv;
bv.reserve(width);
const exprt::operandst &operands = expr.operands();

if(!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(!operands.empty())
{
std::size_t op_width = width / operands.size();

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

forall_literals(it2, tmp)
bv.push_back(*it2);
}
forall_literals(it2, tmp)
bv.push_back(*it2);
}

return bv;
}

return conversion_failed(expr);
return bv;
}
23 changes: 10 additions & 13 deletions src/solvers/flattening/boolbv_width.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
#include <algorithm>

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

Expand Down Expand Up @@ -79,39 +80,35 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
else if(type_id==ID_c_bool)
{
entry.total_width=to_c_bool_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_signedbv)
{
entry.total_width=to_signedbv_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_unsignedbv)
{
entry.total_width=to_unsignedbv_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_floatbv)
{
entry.total_width=to_floatbv_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_fixedbv)
{
entry.total_width=to_fixedbv_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_bv)
{
entry.total_width=to_bv_type(type).get_width();
assert(entry.total_width!=0);
}
else if(type_id==ID_verilog_signedbv ||
type_id==ID_verilog_unsignedbv)
{
// we encode with two bits
entry.total_width = type.get_size_t(ID_width) * 2;
assert(entry.total_width!=0);
std::size_t size = type.get_size_t(ID_width);
DATA_INVARIANT(
size > 0, "verilog bitvector width shall be greater than zero");
entry.total_width = size * 2;
}
else if(type_id==ID_range)
{
Expand All @@ -123,7 +120,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
if(size>=1)
{
entry.total_width = address_bits(size);
assert(entry.total_width!=0);
CHECK_RETURN(entry.total_width > 0);
}
}
else if(type_id==ID_array)
Expand All @@ -142,7 +139,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
{
mp_integer total=array_size*sub_width;
if(total>(1<<30)) // realistic limit
throw "array too large for flattening";
throw analysis_exceptiont("array too large for flattening");

entry.total_width=integer2unsigned(total);
}
Expand All @@ -163,7 +160,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
{
mp_integer total=vector_size*sub_width;
if(total>(1<<30)) // realistic limit
throw "vector too large for flattening";
analysis_exceptiont("vector too large for flattening");

entry.total_width=integer2unsigned(vector_size*sub_width);
}
Expand All @@ -181,13 +178,13 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
// get number of necessary bits
std::size_t size=to_enumeration_type(type).elements().size();
entry.total_width = address_bits(size);
assert(entry.total_width!=0);
CHECK_RETURN(entry.total_width > 0);
}
else if(type_id==ID_c_enum)
{
// these have a subtype
entry.total_width = type.subtype().get_size_t(ID_width);
assert(entry.total_width!=0);
CHECK_RETURN(entry.total_width > 0);
}
else if(type_id==ID_incomplete_c_enum)
{
Expand Down
Loading