Skip to content

Commit 771b368

Browse files
authored
Merge pull request #3041 from hannes-steffenhagen-diffblue/feature-invariant_cleanup-flattening-extractbits
Invariant cleanup in flattening/boolbv_extractbit.cpp and flattening/boolbv_extractbits.cpp
2 parents b231a4f + 9423a5c commit 771b368

File tree

2 files changed

+56
-71
lines changed

2 files changed

+56
-71
lines changed

src/solvers/flattening/boolbv_extractbit.cpp

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,81 +12,77 @@ Author: Daniel Kroening, [email protected]
1212
#include <algorithm>
1313

1414
#include <util/arith_tools.h>
15+
#include <util/exception_utils.h>
1516
#include <util/std_expr.h>
1617
#include <util/std_types.h>
1718

1819
literalt boolbvt::convert_extractbit(const extractbit_exprt &expr)
1920
{
20-
const exprt::operandst &operands=expr.operands();
21-
22-
if(operands.size()!=2)
23-
throw "extractbit takes two operands";
24-
25-
const bvt &bv0=convert_bv(operands[0]);
21+
const bvt &src_bv = convert_bv(expr.src());
2622

2723
// constant?
28-
if(operands[1].is_constant())
24+
if(expr.index().is_constant())
2925
{
30-
mp_integer o;
31-
32-
if(to_integer(operands[1], o))
33-
throw "extractbit failed to convert constant index";
26+
mp_integer index_as_integer = numeric_cast_v<mp_integer>(expr.index());
3427

35-
if(o<0 || o>=bv0.size())
28+
if(index_as_integer < 0 || index_as_integer >= src_bv.size())
3629
return prop.new_variable(); // out of range!
3730
else
38-
return bv0[integer2size_t(o)];
31+
return src_bv[integer2size_t(index_as_integer)];
3932
}
4033

41-
if(operands[0].type().id()==ID_verilog_signedbv ||
42-
operands[0].type().id()==ID_verilog_unsignedbv)
34+
if(
35+
expr.src().type().id() == ID_verilog_signedbv ||
36+
expr.src().type().id() == ID_verilog_unsignedbv)
4337
{
44-
// TODO
45-
assert(false);
38+
throw unsupported_operation_exceptiont(
39+
"extractbit expression not implemented for verilog integers in "
40+
"flattening solver");
4641
}
4742
else
4843
{
49-
std::size_t width_op0=boolbv_width(operands[0].type());
50-
std::size_t width_op1=boolbv_width(operands[1].type());
44+
std::size_t src_bv_width = boolbv_width(expr.src().type());
45+
std::size_t index_bv_width = boolbv_width(expr.index().type());
5146

52-
if(width_op0==0 || width_op1==0)
47+
if(src_bv_width == 0 || index_bv_width == 0)
5348
return SUB::convert_rest(expr);
5449

55-
std::size_t index_width = std::max(address_bits(width_op0), width_op1);
50+
std::size_t index_width =
51+
std::max(address_bits(src_bv_width), index_bv_width);
5652
unsignedbv_typet index_type(index_width);
5753

5854
equal_exprt equality;
59-
equality.lhs()=operands[1]; // index operand
55+
equality.lhs() = expr.index();
6056

6157
if(index_type!=equality.lhs().type())
6258
equality.lhs().make_typecast(index_type);
6359

6460
if(prop.has_set_to())
6561
{
6662
// free variable
67-
literalt l=prop.new_variable();
63+
literalt literal = prop.new_variable();
6864

6965
// add implications
70-
for(std::size_t i=0; i<bv0.size(); i++)
66+
for(std::size_t i = 0; i < src_bv.size(); i++)
7167
{
7268
equality.rhs()=from_integer(i, index_type);
73-
literalt equal=prop.lequal(l, bv0[i]);
69+
literalt equal = prop.lequal(literal, src_bv[i]);
7470
prop.l_set_to_true(prop.limplies(convert(equality), equal));
7571
}
7672

77-
return l;
73+
return literal;
7874
}
7975
else
8076
{
81-
literalt l=prop.new_variable();
77+
literalt literal = prop.new_variable();
8278

83-
for(std::size_t i=0; i<bv0.size(); i++)
79+
for(std::size_t i = 0; i < src_bv.size(); i++)
8480
{
8581
equality.rhs()=from_integer(i, index_type);
86-
l=prop.lselect(convert(equality), bv0[i], l);
82+
literal = prop.lselect(convert(equality), src_bv[i], literal);
8783
}
8884

89-
return l;
85+
return literal;
9086
}
9187
}
9288

src/solvers/flattening/boolbv_extractbits.cpp

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,62 +12,51 @@ Author: Daniel Kroening, [email protected]
1212

1313
bvt boolbvt::convert_extractbits(const extractbits_exprt &expr)
1414
{
15-
std::size_t width=boolbv_width(expr.type());
15+
const std::size_t bv_width = boolbv_width(expr.type());
1616

17-
if(width==0)
17+
if(bv_width == 0)
1818
return conversion_failed(expr);
1919

20-
if(expr.operands().size()!=3)
21-
{
22-
error().source_location=expr.find_source_location();
23-
error() << "extractbits takes three operands" << eom;
24-
throw 0;
25-
}
20+
auto const &src_bv = convert_bv(expr.src());
2621

27-
mp_integer o1, o2;
28-
const bvt &bv0=convert_bv(expr.op0());
22+
auto const maybe_upper_as_int = numeric_cast<mp_integer>(expr.upper());
23+
auto const maybe_lower_as_int = numeric_cast<mp_integer>(expr.lower());
2924

3025
// We only do constants for now.
3126
// Should implement a shift here.
32-
if(to_integer(expr.op1(), o1) ||
33-
to_integer(expr.op2(), o2))
27+
if(!maybe_upper_as_int.has_value() || !maybe_lower_as_int.has_value())
3428
return conversion_failed(expr);
3529

36-
if(o1<0 || o1>=bv0.size())
37-
{
38-
error().source_location=expr.find_source_location();
39-
error() << "extractbits: second operand out of range: "
40-
<< expr.pretty() << eom;
41-
}
30+
auto upper_as_int = maybe_upper_as_int.value();
31+
auto lower_as_int = maybe_lower_as_int.value();
4232

43-
if(o2<0 || o2>=bv0.size())
44-
{
45-
error().source_location=expr.find_source_location();
46-
error() << "extractbits: third operand out of range: "
47-
<< expr.pretty() << eom;
48-
throw 0;
49-
}
33+
DATA_INVARIANT_WITH_DIAGNOSTICS(
34+
upper_as_int >= 0 && upper_as_int < src_bv.size(),
35+
"upper end of extracted bits must be within the bitvector",
36+
expr.find_source_location(),
37+
irep_pretty_diagnosticst{expr});
5038

51-
if(o2>o1)
52-
std::swap(o1, o2);
39+
DATA_INVARIANT_WITH_DIAGNOSTICS(
40+
lower_as_int >= 0 && lower_as_int < src_bv.size(),
41+
"lower end of extracted bits must be within the bitvector",
42+
expr.find_source_location(),
43+
irep_pretty_diagnosticst{expr});
5344

54-
// now o2<=o1
45+
if(lower_as_int > upper_as_int)
46+
std::swap(upper_as_int, lower_as_int);
5547

56-
if((o1-o2+1)!=width)
57-
{
58-
error().source_location=expr.find_source_location();
59-
error() << "extractbits: wrong width (expected " << (o1-o2+1)
60-
<< " but got " << width << "): " << expr.pretty() << eom;
61-
throw 0;
62-
}
48+
// now lower_as_int <= upper_as_int
6349

64-
std::size_t offset=integer2unsigned(o2);
50+
DATA_INVARIANT_WITH_DIAGNOSTICS(
51+
(upper_as_int - lower_as_int + 1) == bv_width,
52+
"the difference between upper and lower end of the range must have the "
53+
"same width as the resulting bitvector type",
54+
expr.find_source_location(),
55+
irep_pretty_diagnosticst{expr});
6556

66-
bvt bv;
67-
bv.resize(width);
57+
const std::size_t offset = integer2unsigned(lower_as_int);
6858

69-
for(std::size_t i=0; i<width; i++)
70-
bv[i]=bv0[offset+i];
59+
bvt result_bv(src_bv.begin() + offset, src_bv.begin() + offset + bv_width);
7160

72-
return bv;
61+
return result_bv;
7362
}

0 commit comments

Comments
 (0)