Skip to content

Commit 03126ae

Browse files
authored
Merge pull request #2938 from danpoe/refactor/error-handling-solvers-flattening-from-boolbv-unary-minus
Error handling cleanup in solvers/flattening 5
2 parents 6b6302e + 7d629c5 commit 03126ae

File tree

7 files changed

+137
-111
lines changed

7 files changed

+137
-111
lines changed

src/solvers/flattening/boolbv.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,8 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
251251
expr.id()==ID_bitxnor || expr.id()==ID_bitnor ||
252252
expr.id()==ID_bitnand)
253253
return convert_bitwise(expr);
254-
else if(expr.id()==ID_unary_minus ||
255-
expr.id()=="no-overflow-unary-minus")
256-
return convert_unary_minus(to_unary_expr(expr));
254+
else if(expr.id() == ID_unary_minus)
255+
return convert_unary_minus(to_unary_minus_expr(expr));
257256
else if(expr.id()==ID_unary_plus)
258257
{
259258
return convert_bitvector(to_unary_plus_expr(expr).op());
@@ -281,7 +280,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
281280
else if(expr.id()==ID_array)
282281
return convert_array(expr);
283282
else if(expr.id()==ID_vector)
284-
return convert_vector(expr);
283+
return convert_vector(to_vector_expr(expr));
285284
else if(expr.id()==ID_complex)
286285
return convert_complex(to_complex_expr(expr));
287286
else if(expr.id()==ID_complex_real)

src/solvers/flattening/boolbv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class boolbvt:public arrayst
142142
virtual bvt convert_if(const if_exprt &expr);
143143
virtual bvt convert_struct(const struct_exprt &expr);
144144
virtual bvt convert_array(const exprt &expr);
145-
virtual bvt convert_vector(const exprt &expr);
145+
virtual bvt convert_vector(const vector_exprt &expr);
146146
virtual bvt convert_complex(const complex_exprt &expr);
147147
virtual bvt convert_complex_real(const complex_real_exprt &expr);
148148
virtual bvt convert_complex_imag(const complex_imag_exprt &expr);
@@ -164,7 +164,7 @@ class boolbvt:public arrayst
164164
virtual bvt convert_cond(const exprt &expr);
165165
virtual bvt convert_shift(const binary_exprt &expr);
166166
virtual bvt convert_bitwise(const exprt &expr);
167-
virtual bvt convert_unary_minus(const unary_exprt &expr);
167+
virtual bvt convert_unary_minus(const unary_minus_exprt &expr);
168168
virtual bvt convert_abs(const abs_exprt &expr);
169169
virtual bvt convert_concatenation(const concatenation_exprt &expr);
170170
virtual bvt convert_replication(const replication_exprt &expr);

src/solvers/flattening/boolbv_unary_minus.cpp

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <solvers/floatbv/float_utils.h>
1414

15+
#include <algorithm>
16+
#include <iterator>
17+
1518
#include "boolbv_type.h"
1619

17-
bvt boolbvt::convert_unary_minus(const unary_exprt &expr)
20+
bvt boolbvt::convert_unary_minus(const unary_minus_exprt &expr)
1821
{
1922
const typet &type=ns.follow(expr.type());
2023

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

26-
const exprt::operandst &operands=expr.operands();
27-
28-
if(operands.size()!=1)
29-
throw "unary minus takes one operand";
29+
const exprt &op = expr.op();
3030

31-
const exprt &op0=expr.op0();
32-
33-
const bvt &op_bv=convert_bv(op0);
31+
const bvt &op_bv = convert_bv(op, width);
3432

3533
bvtypet bvtype=get_bvtype(type);
36-
bvtypet op_bvtype=get_bvtype(op0.type());
37-
std::size_t op_width=op_bv.size();
38-
39-
bool no_overflow=(expr.id()=="no-overflow-unary-minus");
40-
41-
if(op_width==0 || op_width!=width)
42-
return conversion_failed(expr);
34+
bvtypet op_bvtype = get_bvtype(op.type());
4335

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

4941
std::size_t sub_width=boolbv_width(subtype);
5042

51-
if(sub_width==0 || width%sub_width!=0)
52-
throw "unary-: unexpected vector operand width";
43+
INVARIANT(
44+
sub_width > 0,
45+
"bitvector representation of type needs to have at least one bit");
46+
47+
INVARIANT(
48+
width % sub_width == 0,
49+
"total bitvector width needs to be a multiple of the component bitvector "
50+
"widths");
5351

54-
std::size_t size=width/sub_width;
5552
bvt bv;
56-
bv.resize(width);
5753

58-
for(std::size_t i=0; i<size; i++)
54+
for(std::size_t sub_idx = 0; sub_idx < width; sub_idx += sub_width)
5955
{
6056
bvt tmp_op;
61-
tmp_op.resize(sub_width);
6257

63-
for(std::size_t j=0; j<tmp_op.size(); j++)
64-
{
65-
assert(i*sub_width+j<op_bv.size());
66-
tmp_op[j]=op_bv[i*sub_width+j];
67-
}
68-
69-
bvt tmp_result;
58+
const auto sub_it = std::next(op_bv.begin(), sub_idx);
59+
std::copy_n(sub_it, sub_width, std::back_inserter(tmp_op));
7060

71-
if(type.subtype().id()==ID_floatbv)
61+
if(type.subtype().id() == ID_floatbv)
7262
{
7363
float_utilst float_utils(prop, to_floatbv_type(subtype));
74-
tmp_result=float_utils.negate(tmp_op);
64+
tmp_op = float_utils.negate(tmp_op);
7565
}
7666
else
77-
tmp_result=bv_utils.negate(tmp_op);
67+
tmp_op = bv_utils.negate(tmp_op);
7868

79-
assert(tmp_result.size()==sub_width);
69+
INVARIANT(
70+
tmp_op.size() == sub_width,
71+
"bitvector after negation shall have same bit width");
8072

81-
for(std::size_t j=0; j<tmp_result.size(); j++)
82-
{
83-
assert(i*sub_width+j<bv.size());
84-
bv[i*sub_width+j]=tmp_result[j];
85-
}
73+
std::copy(tmp_op.begin(), tmp_op.end(), std::back_inserter(bv));
8674
}
8775

8876
return bv;
8977
}
9078
else if(bvtype==bvtypet::IS_FIXED && op_bvtype==bvtypet::IS_FIXED)
9179
{
92-
if(no_overflow)
93-
return bv_utils.negate_no_overflow(op_bv);
94-
else
95-
return bv_utils.negate(op_bv);
80+
return bv_utils.negate(op_bv);
9681
}
9782
else if(bvtype==bvtypet::IS_FLOAT && op_bvtype==bvtypet::IS_FLOAT)
9883
{
99-
assert(!no_overflow);
10084
float_utilst float_utils(prop, to_floatbv_type(expr.type()));
10185
return float_utils.negate(op_bv);
10286
}
10387
else if((op_bvtype==bvtypet::IS_SIGNED || op_bvtype==bvtypet::IS_UNSIGNED) &&
10488
(bvtype==bvtypet::IS_SIGNED || bvtype==bvtypet::IS_UNSIGNED))
10589
{
106-
if(no_overflow)
107-
prop.l_set_to(bv_utils.overflow_negate(op_bv), false);
108-
109-
if(no_overflow)
110-
return bv_utils.negate_no_overflow(op_bv);
111-
else
112-
return bv_utils.negate(op_bv);
90+
return bv_utils.negate(op_bv);
11391
}
11492

11593
return conversion_failed(expr);

src/solvers/flattening/boolbv_union.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ bvt boolbvt::convert_union(const union_exprt &expr)
2222

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

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

2830
bvt bv;
2931
bv.resize(width);
@@ -39,8 +41,9 @@ bvt boolbvt::convert_union(const union_exprt &expr)
3941
}
4042
else
4143
{
42-
assert(
43-
config.ansi_c.endianness==configt::ansi_ct::endiannesst::IS_BIG_ENDIAN);
44+
INVARIANT(
45+
config.ansi_c.endianness == configt::ansi_ct::endiannesst::IS_BIG_ENDIAN,
46+
"endianness should be set to either little endian or big endian");
4447

4548
bv_endianness_mapt map_u(expr.type(), false, ns, boolbv_width);
4649
bv_endianness_mapt map_op(expr.op0().type(), false, ns, boolbv_width);

src/solvers/flattening/boolbv_vector.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,30 @@ Author: Daniel Kroening, [email protected]
99

1010
#include "boolbv.h"
1111

12-
bvt boolbvt::convert_vector(const exprt &expr)
12+
bvt boolbvt::convert_vector(const vector_exprt &expr)
1313
{
1414
std::size_t width=boolbv_width(expr.type());
1515

1616
if(width==0)
1717
return conversion_failed(expr);
1818

19-
if(expr.type().id()==ID_vector)
20-
{
21-
const exprt::operandst &operands=expr.operands();
22-
23-
bvt bv;
24-
bv.reserve(width);
19+
const exprt::operandst &operands = expr.operands();
2520

26-
if(!operands.empty())
27-
{
28-
std::size_t op_width=width/operands.size();
21+
bvt bv;
22+
bv.reserve(width);
2923

30-
forall_expr(it, operands)
31-
{
32-
const bvt &tmp=convert_bv(*it);
24+
if(!operands.empty())
25+
{
26+
std::size_t op_width = width / operands.size();
3327

34-
if(tmp.size()!=op_width)
35-
throw "convert_vector: unexpected operand width";
28+
forall_expr(it, operands)
29+
{
30+
const bvt &tmp = convert_bv(*it, op_width);
3631

37-
forall_literals(it2, tmp)
38-
bv.push_back(*it2);
39-
}
32+
forall_literals(it2, tmp)
33+
bv.push_back(*it2);
4034
}
41-
42-
return bv;
4335
}
4436

45-
return conversion_failed(expr);
37+
return bv;
4638
}

src/solvers/flattening/boolbv_width.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#include <algorithm>
1212

1313
#include <util/arith_tools.h>
14+
#include <util/exception_utils.h>
1415
#include <util/invariant.h>
1516
#include <util/std_types.h>
1617

@@ -79,39 +80,35 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
7980
else if(type_id==ID_c_bool)
8081
{
8182
entry.total_width=to_c_bool_type(type).get_width();
82-
assert(entry.total_width!=0);
8383
}
8484
else if(type_id==ID_signedbv)
8585
{
8686
entry.total_width=to_signedbv_type(type).get_width();
87-
assert(entry.total_width!=0);
8887
}
8988
else if(type_id==ID_unsignedbv)
9089
{
9190
entry.total_width=to_unsignedbv_type(type).get_width();
92-
assert(entry.total_width!=0);
9391
}
9492
else if(type_id==ID_floatbv)
9593
{
9694
entry.total_width=to_floatbv_type(type).get_width();
97-
assert(entry.total_width!=0);
9895
}
9996
else if(type_id==ID_fixedbv)
10097
{
10198
entry.total_width=to_fixedbv_type(type).get_width();
102-
assert(entry.total_width!=0);
10399
}
104100
else if(type_id==ID_bv)
105101
{
106102
entry.total_width=to_bv_type(type).get_width();
107-
assert(entry.total_width!=0);
108103
}
109104
else if(type_id==ID_verilog_signedbv ||
110105
type_id==ID_verilog_unsignedbv)
111106
{
112107
// we encode with two bits
113-
entry.total_width = type.get_size_t(ID_width) * 2;
114-
assert(entry.total_width!=0);
108+
std::size_t size = type.get_size_t(ID_width);
109+
DATA_INVARIANT(
110+
size > 0, "verilog bitvector width shall be greater than zero");
111+
entry.total_width = size * 2;
115112
}
116113
else if(type_id==ID_range)
117114
{
@@ -123,7 +120,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
123120
if(size>=1)
124121
{
125122
entry.total_width = address_bits(size);
126-
assert(entry.total_width!=0);
123+
CHECK_RETURN(entry.total_width > 0);
127124
}
128125
}
129126
else if(type_id==ID_array)
@@ -142,7 +139,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
142139
{
143140
mp_integer total=array_size*sub_width;
144141
if(total>(1<<30)) // realistic limit
145-
throw "array too large for flattening";
142+
throw analysis_exceptiont("array too large for flattening");
146143

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

168165
entry.total_width=integer2unsigned(vector_size*sub_width);
169166
}
@@ -181,13 +178,13 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
181178
// get number of necessary bits
182179
std::size_t size=to_enumeration_type(type).elements().size();
183180
entry.total_width = address_bits(size);
184-
assert(entry.total_width!=0);
181+
CHECK_RETURN(entry.total_width > 0);
185182
}
186183
else if(type_id==ID_c_enum)
187184
{
188185
// these have a subtype
189186
entry.total_width = type.subtype().get_size_t(ID_width);
190-
assert(entry.total_width!=0);
187+
CHECK_RETURN(entry.total_width > 0);
191188
}
192189
else if(type_id==ID_incomplete_c_enum)
193190
{

0 commit comments

Comments
 (0)