@@ -272,7 +272,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
272272 let b = this. read_immediate ( args[ 1 ] ) ?;
273273 // check x % y != 0
274274 if this. binary_op ( mir:: BinOp :: Rem , a, b) ?. 0 . to_bits ( dest. layout . size ) ? != 0 {
275- return err ! ( ValidationFailure ( format!( "exact_div: {:?} cannot be divided by {:?}" , a, b) ) ) ;
275+ // Check if `b` is -1, which is the "min_value / -1" case.
276+ let minus1 = Scalar :: from_int ( -1 , dest. layout . size ) ;
277+ return if b. to_scalar ( ) . unwrap ( ) == minus1 {
278+ err ! ( Intrinsic ( format!( "exact_div: result of dividing MIN by -1 cannot be represented" ) ) )
279+ } else {
280+ err ! ( Intrinsic ( format!( "exact_div: {:?} cannot be divided by {:?} without remainder" , * a, * b) ) )
281+ } ;
276282 }
277283 this. binop_ignore_overflow ( mir:: BinOp :: Div , a, b, dest) ?;
278284 } ,
@@ -459,6 +465,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
459465 ) ?;
460466 }
461467
468+ "unchecked_add" | "unchecked_sub" | "unchecked_mul" => {
469+ let l = this. read_immediate ( args[ 0 ] ) ?;
470+ let r = this. read_immediate ( args[ 1 ] ) ?;
471+ let op = match intrinsic_name. get ( ) {
472+ "unchecked_add" => mir:: BinOp :: Add ,
473+ "unchecked_sub" => mir:: BinOp :: Sub ,
474+ "unchecked_mul" => mir:: BinOp :: Mul ,
475+ _ => bug ! ( ) ,
476+ } ;
477+ let ( res, overflowed) = this. binary_op ( op, l, r) ?;
478+ if overflowed {
479+ return err ! ( Intrinsic ( format!( "Overflowing arithmetic in {}" , intrinsic_name. get( ) ) ) ) ;
480+ }
481+ this. write_scalar ( res, dest) ?;
482+ }
483+
462484 "uninit" => {
463485 // Check fast path: we don't want to force an allocation in case the destination is a simple value,
464486 // but we also do not want to create a new allocation with 0s and then copy that over.
0 commit comments