@@ -134,9 +134,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
134
134
let mut r = r as u32 ;
135
135
let size = left_layout. size ;
136
136
oflo |= r >= size. bits ( ) as u32 ;
137
- if oflo {
138
- r %= size. bits ( ) as u32 ;
139
- }
137
+ r %= size. bits ( ) as u32 ;
140
138
let result = if signed {
141
139
let l = self . sign_extend ( l, left_layout) as i128 ;
142
140
let result = match bin_op {
@@ -168,6 +166,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
168
166
)
169
167
}
170
168
169
+ let size = left_layout. size ;
170
+
171
171
// Operations that need special treatment for signed integers
172
172
if left_layout. abi . is_signed ( ) {
173
173
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> {
195
195
if let Some ( op) = op {
196
196
let l128 = self . sign_extend ( l, left_layout) as i128 ;
197
197
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.
216
202
let result = result as u128 ;
217
203
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
+ ) ) ;
219
209
}
220
210
}
221
211
222
- let size = left_layout. size ;
223
-
224
212
let ( val, ty) = match bin_op {
225
213
Eq => ( Scalar :: from_bool ( l == r) , self . tcx . types . bool ) ,
226
214
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> {
247
235
_ => bug ! ( ) ,
248
236
} ;
249
237
let ( result, oflo) = op ( l, r) ;
238
+ // Truncate to target type.
239
+ // If that truncation loses any information, we have an overflow.
250
240
let truncated = self . truncate ( result, left_layout) ;
251
241
return Ok ( (
252
242
Scalar :: from_uint ( truncated, size) ,
0 commit comments