aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Solver/STPBuilder.cpp
diff options
context:
space:
mode:
authorDan Liew <daniel.liew@imperial.ac.uk>2013-11-07 15:21:43 +0000
committerDan Liew <daniel.liew@imperial.ac.uk>2014-02-14 18:29:35 +0000
commit7759c90744bae5c531f765b2faa2475e13f464fd (patch)
treeab1d0fbb1c4b767369e2c3774a49ca48de69101c /lib/Solver/STPBuilder.cpp
parenta480b43bf38d4b030d3ceda92549fb721800c026 (diff)
downloadklee-7759c90744bae5c531f765b2faa2475e13f464fd.tar.gz
Fixed overshift of arithmetic right shift by symbolic so that it overshifts
to zero. Test case is included.
Diffstat (limited to 'lib/Solver/STPBuilder.cpp')
-rw-r--r--lib/Solver/STPBuilder.cpp23
1 files changed, 12 insertions, 11 deletions
diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp
index a92b6f2b..84e88579 100644
--- a/lib/Solver/STPBuilder.cpp
+++ b/lib/Solver/STPBuilder.cpp
@@ -248,31 +248,33 @@ ExprHandle STPBuilder::bvVarRightShift(ExprHandle expr, ExprHandle shift) {
}
// arithmetic right shift by a variable amount on an expression of the specified width
-ExprHandle STPBuilder::bvVarArithRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
- int shiftBits = getShiftBits( width );
-
- //get the shift amount (looking only at the bits appropriate for the given width)
- ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
+ExprHandle STPBuilder::bvVarArithRightShift(ExprHandle expr, ExprHandle shift) {
+ unsigned width = vc_getBVLength(vc, expr);
//get the sign bit to fill with
ExprHandle signedBool = bvBoolExtract(expr, width-1);
//start with the result if shifting by width-1
- ExprHandle res = constructAShrByConstant(expr, width-1, signedBool, shiftBits);
+ ExprHandle res = constructAShrByConstant(expr, width-1, signedBool, width);
//construct a big if-then-elif-elif-... with one case per possible shift amount
// XXX more efficient to move the ite on the sign outside all exprs?
// XXX more efficient to sign extend, right shift, then extract lower bits?
for( int i=width-2; i>=0; i-- ) {
res = vc_iteExpr(vc,
- eqExpr(shift, bvConst32(shiftBits,i)),
+ eqExpr(shift, bvConst32(width,i)),
constructAShrByConstant(expr,
i,
signedBool,
- shiftBits),
+ width),
res);
}
+ // If overshifting, shift to zero
+ res = vc_iteExpr(vc,
+ vc_bvLtExpr(vc, shift, bvConst32(width, width)),
+ res,
+ bvZero(width));
return res;
}
@@ -839,12 +841,11 @@ ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
unsigned shift = (unsigned) CE->getLimitedValue();
ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
- return constructAShrByConstant(left, shift, signedBool,
- getShiftBits(*width_out));
+ return constructAShrByConstant(left, shift, signedBool, getShiftBits(*width_out));
} else {
int shiftWidth;
ExprHandle amount = construct(ase->right, &shiftWidth);
- return bvVarArithRightShift( left, amount, *width_out );
+ return bvVarArithRightShift( left, amount);
}
}