@@ -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