Skip to content

Commit 202d401

Browse files
committed
miri: simplify singed operator overflow detection
1 parent 07a34df commit 202d401

File tree

1 file changed

+14
-24
lines changed

1 file changed

+14
-24
lines changed

src/librustc_mir/interpret/operator.rs

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
134134
let mut r = r as u32;
135135
let size = left_layout.size;
136136
oflo |= r >= size.bits() as u32;
137-
if oflo {
138-
r %= size.bits() as u32;
139-
}
137+
r %= size.bits() as u32;
140138
let result = if signed {
141139
let l = self.sign_extend(l, left_layout) as i128;
142140
let result = match bin_op {
@@ -168,6 +166,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
168166
)
169167
}
170168

169+
let size = left_layout.size;
170+
171171
// Operations that need special treatment for signed integers
172172
if left_layout.abi.is_signed() {
173173
let op: Option<fn(&i128, &i128) -> bool> = match bin_op {
@@ -195,32 +195,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
195195
if let Some(op) = op {
196196
let l128 = self.sign_extend(l, left_layout) as i128;
197197
let r = self.sign_extend(r, right_layout) as i128;
198-
let size = left_layout.size;
199-
match bin_op {
200-
Rem | Div => {
201-
// int_min / -1
202-
if r == -1 && l == (1 << (size.bits() - 1)) {
203-
return Ok((Scalar::from_uint(l, size), true, left_layout.ty));
204-
}
205-
}
206-
_ => {}
207-
}
208-
trace!("{}, {}, {}", l, l128, r);
209-
let (result, mut oflo) = op(l128, r);
210-
trace!("{}, {}", result, oflo);
211-
if !oflo && size.bits() != 128 {
212-
let max = 1 << (size.bits() - 1);
213-
oflo = result >= max || result < -max;
214-
}
215-
// this may be out-of-bounds for the result type, so we have to truncate ourselves
198+
199+
let (result, oflo) = op(l128, r);
200+
// This may be out-of-bounds for the result type, so we have to truncate ourselves.
201+
// If that truncation loses any information, we have an overflow.
216202
let result = result as u128;
217203
let truncated = self.truncate(result, left_layout);
218-
return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty));
204+
return Ok((
205+
Scalar::from_uint(truncated, size),
206+
oflo || self.sign_extend(truncated, left_layout) != result,
207+
left_layout.ty,
208+
));
219209
}
220210
}
221211

222-
let size = left_layout.size;
223-
224212
let (val, ty) = match bin_op {
225213
Eq => (Scalar::from_bool(l == r), self.tcx.types.bool),
226214
Ne => (Scalar::from_bool(l != r), self.tcx.types.bool),
@@ -247,6 +235,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
247235
_ => bug!(),
248236
};
249237
let (result, oflo) = op(l, r);
238+
// Truncate to target type.
239+
// If that truncation loses any information, we have an overflow.
250240
let truncated = self.truncate(result, left_layout);
251241
return Ok((
252242
Scalar::from_uint(truncated, size),

0 commit comments

Comments
 (0)