Skip to content

Commit f3694af

Browse files
author
Daniel Kroening
committed
added support for rotation operators
1 parent 7f3ba30 commit f3694af

File tree

9 files changed

+51
-21
lines changed

9 files changed

+51
-21
lines changed

regression/smt2_solver/basic-bv1/basic-bv1.smt2

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
(define-fun b09 () Bool (= (bvlshr #xf0 #x03) #x1e)) ; unsigned (logical) shift right
1515
(define-fun b10 () Bool (= (bvashr #xf0 #x03) #xfe)) ; signed (arithmetical) shift right#x0a
1616

17+
; rotation
18+
(define-fun b11 () Bool (= ((_ rotate_left 2) #xf7) #xdf)) ; rotation left
19+
(define-fun b12 () Bool (= ((_ rotate_right 2) #x07) #xc1)) ; rotation right
20+
1721
; Bitwise Operations
1822

1923
(define-fun w1 () Bool (= (bvor #x6 #x3) #x7)) ; bitwise or
@@ -56,7 +60,7 @@
5660
; all must be true
5761

5862
(assert (not (and
59-
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
63+
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10 b11 b12
6064
d01
6165
power-test
6266
p1 p2 p3 p4 p5 p6 p7 p8)))

src/solvers/flattening/boolbv.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
216216
return convert_div(to_div_expr(expr));
217217
else if(expr.id()==ID_mod)
218218
return convert_mod(to_mod_expr(expr));
219-
else if(expr.id()==ID_shl || expr.id()==ID_ashr || expr.id()==ID_lshr)
219+
else if(expr.id()==ID_shl || expr.id()==ID_ashr || expr.id()==ID_lshr ||
220+
expr.id()==ID_rol || expr.id()==ID_ror)
220221
return convert_shift(to_shift_expr(expr));
221222
else if(expr.id()==ID_floatbv_plus || expr.id()==ID_floatbv_minus ||
222223
expr.id()==ID_floatbv_mult || expr.id()==ID_floatbv_div ||

src/solvers/flattening/boolbv_overflow.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ literalt boolbvt::convert_overflow(const exprt &expr)
112112

113113
bvt bv_ext=bv_utils.extension(bv0, new_size, rep);
114114

115-
bvt result=bv_utils.shift(bv_ext, bv_utilst::shiftt::LEFT, bv1);
115+
bvt result=bv_utils.shift(bv_ext, bv_utilst::shiftt::SHIFT_LEFT, bv1);
116116

117117
// a negative shift is undefined; yet this isn't an overflow
118118
literalt neg_shift =

src/solvers/flattening/boolbv_power.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ bvt boolbvt::convert_power(const binary_exprt &expr)
2929
bv_utils.equal(op0, bv_utils.build_constant(2, op0.size()));
3030

3131
bvt one=bv_utils.build_constant(1, width);
32-
bvt shift=bv_utils.shift(one, bv_utilst::shiftt::LEFT, op1);
32+
bvt shift=bv_utils.shift(one, bv_utilst::shiftt::SHIFT_LEFT, op1);
3333

3434
bvt nondet=prop.new_variables(width);
3535

src/solvers/flattening/boolbv_shift.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ bvt boolbvt::convert_shift(const binary_exprt &expr)
3030
if(width==0)
3131
return conversion_failed(expr);
3232

33-
if(expr.operands().size()!=2)
34-
throw "shifting takes two operands";
35-
3633
const bvt &op=convert_bv(expr.op0());
3734

3835
if(op.size()!=width)
@@ -41,11 +38,15 @@ bvt boolbvt::convert_shift(const binary_exprt &expr)
4138
bv_utilst::shiftt shift;
4239

4340
if(expr.id()==ID_shl)
44-
shift=bv_utilst::shiftt::LEFT;
41+
shift=bv_utilst::shiftt::SHIFT_LEFT;
4542
else if(expr.id()==ID_ashr)
46-
shift=bv_utilst::shiftt::ARIGHT;
43+
shift=bv_utilst::shiftt::SHIFT_ARIGHT;
4744
else if(expr.id()==ID_lshr)
48-
shift=bv_utilst::shiftt::LRIGHT;
45+
shift=bv_utilst::shiftt::SHIFT_LRIGHT;
46+
else if(expr.id()==ID_rol)
47+
shift=bv_utilst::shiftt::ROTATE_LEFT;
48+
else if(expr.id()==ID_ror)
49+
shift=bv_utilst::shiftt::ROTATE_RIGHT;
4950
else
5051
throw "unexpected shift operator";
5152

src/solvers/flattening/bv_utils.cpp

+25-6
Original file line numberDiff line numberDiff line change
@@ -482,26 +482,45 @@ bvt bv_utilst::shift(const bvt &src, const shiftt s, std::size_t dist)
482482
bvt result;
483483
result.resize(src.size());
484484

485+
// 'dist' is user-controlled, and thus arbitary.
486+
// We thus must guard against the case in which i+dist overflows.
487+
// We do so by considering the case dist>=src.size().
488+
485489
for(std::size_t i=0; i<src.size(); i++)
486490
{
487491
literalt l;
488492

489493
switch(s)
490494
{
491-
case shiftt::LEFT:
495+
case shiftt::SHIFT_LEFT:
496+
// no underflow on i-dist because of condition dist<=i
492497
l=(dist<=i?src[i-dist]:const_literal(false));
493498
break;
494499

495-
case shiftt::ARIGHT:
496-
l=(i+dist<src.size()?src[i+dist]:src[src.size()-1]); // sign bit
500+
case shiftt::SHIFT_ARIGHT:
501+
// src.size()-i won't underflow as i<src.size()
502+
// Then, if dist<src.size()-i, then i+dist<src.size()
503+
l=(dist<src.size()-i?src[i+dist]:src[src.size()-1]); // sign bit
504+
break;
505+
506+
case shiftt::SHIFT_LRIGHT:
507+
// src.size()-i won't underflow as i<src.size()
508+
// Then, if dist<src.size()-i, then i+dist<src.size()
509+
l=(dist<src.size()-i?src[i+dist]:const_literal(false));
497510
break;
498511

499-
case shiftt::LRIGHT:
500-
l=(i+dist<src.size()?src[i+dist]:const_literal(false));
512+
case shiftt::ROTATE_LEFT:
513+
// prevent overflows by using dist%src.size()
514+
l=src[(src.size()+i-(dist%src.size()))%src.size()];
515+
break;
516+
517+
case shiftt::ROTATE_RIGHT:
518+
// prevent overflows by using dist%src.size()
519+
l=src[(i+(dist%src.size()))%src.size()];
501520
break;
502521

503522
default:
504-
assert(false);
523+
UNREACHABLE;
505524
}
506525

507526
result[i]=l;

src/solvers/flattening/bv_utils.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ class bv_utilst
6868
literalt overflow_sub(const bvt &op0, const bvt &op1, representationt rep);
6969
literalt carry_out(const bvt &op0, const bvt &op1, literalt carry_in);
7070

71-
enum class shiftt { LEFT, LRIGHT, ARIGHT };
71+
enum class shiftt
72+
{
73+
SHIFT_LEFT, SHIFT_LRIGHT, SHIFT_ARIGHT, ROTATE_LEFT, ROTATE_RIGHT
74+
};
75+
7276
bvt shift(const bvt &op, const shiftt shift, std::size_t distance);
7377
bvt shift(const bvt &op, const shiftt shift, const bvt &distance);
7478

src/solvers/floatbv/float_approximation.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void float_approximationt::normalization_shift(bvt &fraction, bvt &exponent)
4242
if(over_approximate)
4343
shifted_fraction=overapproximating_left_shift(fraction, i);
4444
else
45-
shifted_fraction=bv_utils.shift(fraction, bv_utilst::shiftt::LEFT, i);
45+
shifted_fraction=bv_utils.shift(
46+
fraction, bv_utilst::shiftt::SHIFT_LEFT, i);
4647

4748
bv_utils.cond_implies_equal(shift, shifted_fraction, new_fraction);
4849

src/solvers/floatbv/float_utils.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ bvt float_utilst::to_integer(
106106
unpacked.exponent.size());
107107
bvt distance=bv_utils.sub(offset, unpacked.exponent);
108108
bvt shift_result=bv_utils.shift(
109-
fraction, bv_utilst::shiftt::LRIGHT, distance);
109+
fraction, bv_utilst::shiftt::SHIFT_LRIGHT, distance);
110110

111111
// if the exponent is negative, we have zero anyways
112112
bvt result=shift_result;
@@ -809,7 +809,7 @@ void float_utilst::normalization_shift(bvt &fraction, bvt &exponent)
809809
// If so, shift the zeros out left by 'distance'.
810810
// Otherwise, leave as is.
811811
const bvt shifted=
812-
bv_utils.shift(fraction, bv_utilst::shiftt::LEFT, distance);
812+
bv_utils.shift(fraction, bv_utilst::shiftt::SHIFT_LEFT, distance);
813813

814814
fraction=
815815
bv_utils.select(prefix_is_zero, shifted, fraction);
@@ -1281,7 +1281,7 @@ bvt float_utilst::sticky_right_shift(
12811281
{
12821282
if(dist[stage]!=const_literal(false))
12831283
{
1284-
bvt tmp=bv_utils.shift(result, bv_utilst::shiftt::LRIGHT, d);
1284+
bvt tmp=bv_utils.shift(result, bv_utilst::shiftt::SHIFT_LRIGHT, d);
12851285

12861286
bvt lost_bits;
12871287

0 commit comments

Comments
 (0)