Skip to content

Error handling cleanup in solvers/flattening 3 #2933

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 1 commit
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
24 changes: 16 additions & 8 deletions src/solvers/flattening/boolbv_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ boolbv_mapt::map_entryt &boolbv_mapt::get_map_entry(
map_entry.literal_map.resize(map_entry.width);
}

assert(map_entry.literal_map.size()==map_entry.width);
INVARIANT(
map_entry.literal_map.size() == map_entry.width,
"number of literals in the literal map shall equal the bitvector width");

return map_entry;
}
Expand All @@ -89,15 +91,18 @@ void boolbv_mapt::get_literals(
{
map_entryt &map_entry=get_map_entry(identifier, type);

assert(literals.size()==width);
assert(map_entry.literal_map.size()==width);
PRECONDITION(literals.size() == width);
INVARIANT(
map_entry.literal_map.size() == width,
"number of literals in the literal map shall equal the bitvector width");

Forall_literals(it, literals)
{
literalt &l=*it;
const std::size_t bit=it-literals.begin();

assert(bit<map_entry.literal_map.size());
INVARIANT(
bit < map_entry.literal_map.size(), "bit index shall be within bounds");
map_bitt &mb=map_entry.literal_map[bit];

if(mb.is_set)
Expand Down Expand Up @@ -128,12 +133,15 @@ void boolbv_mapt::set_literals(
forall_literals(it, literals)
{
const literalt &literal=*it;
const std::size_t bit=it-literals.begin();

assert(literal.is_constant() ||
literal.var_no()<prop.no_variables());
INVARIANT(
literal.is_constant() || literal.var_no() < prop.no_variables(),
"variable number of non-constant literals shall be within bounds");

const std::size_t bit = it - literals.begin();

assert(bit<map_entry.literal_map.size());
INVARIANT(
bit < map_entry.literal_map.size(), "bit index shall be within bounds");
map_bitt &mb=map_entry.literal_map[bit];

if(mb.is_set)
Expand Down
43 changes: 19 additions & 24 deletions src/solvers/flattening/boolbv_member.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ bvt boolbvt::convert_member(const member_exprt &expr)
from_integer(0, index_type()),
expr.type()));
}
else if(struct_op_type.id()==ID_struct)
else
{
INVARIANT(
struct_op_type.id() == ID_struct,
"member_exprt should denote access to a union or struct");

const irep_idt &component_name=expr.get_component_name();
const struct_typet::componentst &components=
to_struct_type(struct_op_type).components();
Expand All @@ -43,22 +47,18 @@ bvt boolbvt::convert_member(const member_exprt &expr)

if(c.get_name() == component_name)
{
if(!base_type_eq(subtype, expr.type(), ns))
{
#if 0
std::cout << "DEBUG " << expr.pretty() << "\n";
#endif

error().source_location=expr.find_source_location();
error() << "member: component type does not match: "
<< subtype.pretty() << " vs. "
<< expr.type().pretty() << eom;
throw 0;
}
DATA_INVARIANT_WITH_DIAGNOSTICS(
base_type_eq(subtype, expr.type(), ns),
"struct component type shall match the member expression type",
subtype.pretty(),
expr.type().pretty());

bvt bv;
bv.resize(sub_width);
assert(offset+sub_width<=struct_bv.size());
INVARIANT(
offset + sub_width <= struct_bv.size(),
"bitvector part corresponding to struct element shall be contained "
"within the full struct bitvector");

for(std::size_t i=0; i<sub_width; i++)
bv[i]=struct_bv[offset+i];
Expand All @@ -69,15 +69,10 @@ bvt boolbvt::convert_member(const member_exprt &expr)
offset+=sub_width;
}

error().source_location=expr.find_source_location();
error() << "component " << component_name
<< " not found in structure" << eom;
throw 0;
}
else
{
error().source_location=expr.find_source_location();
error() << "member takes struct or union operand" << eom;
throw 0;
INVARIANT_WITH_DIAGNOSTICS(
false,
"struct type shall contain component accessed by member expression",
expr.find_source_location(),
id2string(component_name));
}
}
20 changes: 11 additions & 9 deletions src/solvers/flattening/boolbv_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,22 @@ bvt boolbvt::convert_mod(const mod_exprt &expr)
if(width==0)
return conversion_failed(expr);

if(expr.op0().type().id()!=expr.type().id() ||
expr.op1().type().id()!=expr.type().id())
throw "mod got mixed-type operands";
DATA_INVARIANT(
expr.op0().type().id() == expr.type().id(),
"type of the first operand of a modulo operation shall equal the "
"expression type");

DATA_INVARIANT(
expr.op1().type().id() == expr.type().id(),
"type of the second operand of a modulo operation shall equal the "
"expression type");

bv_utilst::representationt rep=
expr.type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
bv_utilst::representationt::UNSIGNED;

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

if(op0.size()!=width ||
op1.size()!=width)
throw "convert_mod: unexpected operand width";
const bvt &op0 = convert_bv(expr.op0(), width);
const bvt &op1 = convert_bv(expr.op1(), width);

bvt res, rem;

Expand Down
45 changes: 17 additions & 28 deletions src/solvers/flattening/boolbv_mult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Author: Daniel Kroening, [email protected]

bvt boolbvt::convert_mult(const exprt &expr)
{
PRECONDITION(expr.id() == ID_mult || expr.id() == "no-overflow-mult");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is "no-overflow-mult" still used? It does not seem to be assigned anywhere. If not, we can remove it and make convert_mult take a mult_exprt instead.


std::size_t width=boolbv_width(expr.type());

if(width==0)
Expand All @@ -21,39 +23,34 @@ bvt boolbvt::convert_mult(const exprt &expr)
bv.resize(width);

const exprt::operandst &operands=expr.operands();
if(operands.empty())
throw "mult without operands";
DATA_INVARIANT(!operands.empty(), "multiplication must have operands");

const exprt &op0=expr.op0();

bool no_overflow=expr.id()=="no-overflow-mult";
Copy link
Member

Choose a reason for hiding this comment

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

This can be removed then too.


DATA_INVARIANT(
op0.type() == expr.type(),
"multiplication operands should have same type as expression");

if(expr.type().id()==ID_fixedbv)
{
if(op0.type()!=expr.type())
throw "multiplication with mixed types";

bv=convert_bv(op0);

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

std::size_t fraction_bits=
to_fixedbv_type(expr.type()).get_fraction_bits();

for(exprt::operandst::const_iterator it=operands.begin()+1;
it!=operands.end(); it++)
{
if(it->type()!=expr.type())
throw "multiplication with mixed types";
DATA_INVARIANT(
it->type() == expr.type(),
"multiplication operands should have same type as expression");

// do a sign extension by fraction_bits bits
bv=bv_utils.sign_extension(bv, bv.size()+fraction_bits);

bvt op=convert_bv(*it);

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

op=bv_utils.sign_extension(op, bv.size());

Expand All @@ -68,28 +65,20 @@ bvt boolbvt::convert_mult(const exprt &expr)
else if(expr.type().id()==ID_unsignedbv ||
expr.type().id()==ID_signedbv)
{
if(op0.type()!=expr.type())
throw "multiplication with mixed types";

bv_utilst::representationt rep=
expr.type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
bv_utilst::representationt::UNSIGNED;

bv=convert_bv(op0);

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

for(exprt::operandst::const_iterator it=operands.begin()+1;
it!=operands.end(); it++)
{
if(it->type()!=expr.type())
throw "multiplication with mixed types";

const bvt &op=convert_bv(*it);
DATA_INVARIANT(
it->type() == expr.type(),
"multiplication operands should have same type as expression");

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

if(no_overflow)
bv=bv_utils.multiplier_no_overflow(bv, op, rep);
Expand Down
4 changes: 1 addition & 3 deletions src/solvers/flattening/boolbv_not.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ Author: Daniel Kroening, [email protected]
bvt boolbvt::convert_not(const not_exprt &expr)
{
const bvt &op_bv=convert_bv(expr.op());

if(op_bv.empty())
throw "not operator takes one non-empty operand";
CHECK_RETURN(!op_bv.empty());

const typet &op_type=expr.op().type();

Expand Down
12 changes: 9 additions & 3 deletions src/solvers/flattening/boolbv_onehot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Author: Daniel Kroening, [email protected]

literalt boolbvt::convert_onehot(const unary_exprt &expr)
{
PRECONDITION(expr.id() == ID_onehot || expr.id() == ID_onehot0);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are those expressions used anywhere? The IDs are not assigned anywhere.

Copy link
Member

Choose a reason for hiding this comment

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

They are used in ebmc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Raised an issue for those as well: #3040


bvt op=convert_bv(expr.op());

literalt one_seen=const_literal(false);
Expand All @@ -25,8 +27,12 @@ literalt boolbvt::convert_onehot(const unary_exprt &expr)

if(expr.id()==ID_onehot)
return prop.land(one_seen, !more_than_one_seen);
else if(expr.id()==ID_onehot0)
return !more_than_one_seen;
else
throw "unexpected onehot expression";
{
INVARIANT(
expr.id() == ID_onehot0,
"should be a onehot0 expression as other onehot expression kind has been "
"handled in other branch");
return !more_than_one_seen;
}
}
39 changes: 20 additions & 19 deletions src/solvers/flattening/boolbv_overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ literalt boolbvt::convert_overflow(const exprt &expr)
if(expr.id()==ID_overflow_plus ||
expr.id()==ID_overflow_minus)
{
if(operands.size()!=2)
throw "operator "+expr.id_string()+" takes two operands";
DATA_INVARIANT(
operands.size() == 2,
"expression " + expr.id_string() + " should have two operands");

const bvt &bv0=convert_bv(operands[0]);
const bvt &bv1=convert_bv(operands[1]);
Expand All @@ -38,27 +39,25 @@ literalt boolbvt::convert_overflow(const exprt &expr)
}
else if(expr.id()==ID_overflow_mult)
{
if(operands.size()!=2)
throw "operator "+expr.id_string()+" takes two operands";
DATA_INVARIANT(
operands.size() == 2,
"overflow_mult expression should have two operands");

if(operands[0].type().id()!=ID_unsignedbv &&
operands[0].type().id()!=ID_signedbv)
return SUB::convert_rest(expr);

bvt bv0=convert_bv(operands[0]);
bvt bv1=convert_bv(operands[1]);

if(bv0.size()!=bv1.size())
throw "operand size mismatch on overflow-*";
bvt bv1 = convert_bv(operands[1], bv0.size());

bv_utilst::representationt rep=
operands[0].type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
bv_utilst::representationt::UNSIGNED;

if(operands[0].type()!=operands[1].type())
throw "operand type mismatch on overflow-*";
DATA_INVARIANT(
operands[0].type() == operands[1].type(),
"operands of overflow_mult expression shall have same type");

DATA_INVARIANT(bv0.size()==bv1.size(), "operands size mismatch");
std::size_t old_size=bv0.size();
std::size_t new_size=old_size*2;

Expand Down Expand Up @@ -97,8 +96,8 @@ literalt boolbvt::convert_overflow(const exprt &expr)
}
else if(expr.id() == ID_overflow_shl)
{
if(operands.size() != 2)
throw "operator " + expr.id_string() + " takes two operands";
DATA_INVARIANT(
operands.size() == 2, "overflow_shl expression should have two operands");

const bvt &bv0=convert_bv(operands[0]);
const bvt &bv1=convert_bv(operands[1]);
Expand Down Expand Up @@ -163,8 +162,9 @@ literalt boolbvt::convert_overflow(const exprt &expr)
}
else if(expr.id()==ID_overflow_unary_minus)
{
if(operands.size()!=1)
throw "operator "+expr.id_string()+" takes one operand";
DATA_INVARIANT(
operands.size() == 1,
"overflow_unary_minus expression should have one operand");

const bvt &bv=convert_bv(operands[0]);

Expand All @@ -173,18 +173,19 @@ literalt boolbvt::convert_overflow(const exprt &expr)
else if(has_prefix(expr.id_string(), "overflow-typecast-"))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is "overflow-typecast-" still used? It's not assigned anywhere.

{
std::size_t bits=unsafe_string2unsigned(id2string(expr.id()).substr(18));
INVARIANT(bits != 0, "");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing message


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

if(operands.size()!=1)
throw "operator "+expr.id_string()+" takes one operand";
DATA_INVARIANT(
operands.size() == 1,
"expression " + expr.id_string() + " should have one operand");

const exprt &op=operands[0];

const bvt &bv=convert_bv(op);

if(bits>=bv.size() || bits==0)
throw "overflow-typecast got wrong number of bits";
INVARIANT(bits < bv.size(), "");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing message


// signed or unsigned?
if(op.type().id()==ID_signedbv)
Expand Down