Skip to content

Commit 5be304b

Browse files
committed
miri: simplify shift operator overflow checking
1 parent cdb50c6 commit 5be304b

File tree

1 file changed

+13
-12
lines changed

1 file changed

+13
-12
lines changed

src/librustc_mir/interpret/operator.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::TryFrom;
2+
13
use rustc::mir;
24
use rustc::mir::interpret::{InterpResult, Scalar};
35
use rustc::ty::{
@@ -130,28 +132,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
130132
// Shift ops can have an RHS with a different numeric type.
131133
if bin_op == Shl || bin_op == Shr {
132134
let signed = left_layout.abi.is_signed();
133-
let mut oflo = (r as u32 as u128) != r;
134-
let mut r = r as u32;
135-
let size = left_layout.size;
136-
oflo |= r >= size.bits() as u32;
137-
r %= size.bits() as u32;
135+
let size = u128::from(left_layout.size.bits());
136+
let overflow = r >= size;
137+
let r = r % size; // mask to type size
138+
let r = u32::try_from(r).unwrap(); // we masked so this will always fit
138139
let result = if signed {
139140
let l = self.sign_extend(l, left_layout) as i128;
140141
let result = match bin_op {
141-
Shl => l << r,
142-
Shr => l >> r,
142+
Shl => l.checked_shl(r).unwrap(),
143+
Shr => l.checked_shr(r).unwrap(),
143144
_ => bug!("it has already been checked that this is a shift op"),
144145
};
145146
result as u128
146147
} else {
147148
match bin_op {
148-
Shl => l << r,
149-
Shr => l >> r,
149+
Shl => l.checked_shl(r).unwrap(),
150+
Shr => l.checked_shr(r).unwrap(),
150151
_ => bug!("it has already been checked that this is a shift op"),
151152
}
152153
};
153154
let truncated = self.truncate(result, left_layout);
154-
return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty));
155+
return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty));
155156
}
156157

157158
// For the remaining ops, the types must be the same on both sides
@@ -193,7 +194,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
193194
_ => None,
194195
};
195196
if let Some(op) = op {
196-
let l128 = self.sign_extend(l, left_layout) as i128;
197197
let r = self.sign_extend(r, right_layout) as i128;
198198
// We need a special check for overflowing remainder:
199199
// "int_min % -1" overflows and returns 0, but after casting things to a larger int
@@ -206,8 +206,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
206206
}
207207
_ => {}
208208
}
209+
let l = self.sign_extend(l, left_layout) as i128;
209210

210-
let (result, oflo) = op(l128, r);
211+
let (result, oflo) = op(l, r);
211212
// This may be out-of-bounds for the result type, so we have to truncate ourselves.
212213
// If that truncation loses any information, we have an overflow.
213214
let result = result as u128;

0 commit comments

Comments
 (0)