@@ -48,7 +48,7 @@ macro_rules! from_bytes {
4848 ( $ty: tt, $value: expr) => {
4949 ( $ty:: from_le_bytes( match ( $value) . try_into( ) {
5050 Ok ( x) => x,
51- Err ( _) => return Err ( MirEvalError :: TypeError ( " mismatched size" ) ) ,
51+ Err ( _) => return Err ( MirEvalError :: TypeError ( stringify! ( mismatched size in constructing $ty ) ) ) ,
5252 } ) )
5353 } ;
5454}
@@ -797,70 +797,127 @@ impl Evaluator<'_> {
797797 lc = self . read_memory ( Address :: from_bytes ( lc) ?, size) ?;
798798 rc = self . read_memory ( Address :: from_bytes ( rc) ?, size) ?;
799799 }
800- let is_signed = matches ! ( ty. as_builtin( ) , Some ( BuiltinType :: Int ( _) ) ) ;
801- let l128 = i128:: from_le_bytes ( pad16 ( lc, is_signed) ) ;
802- let r128 = i128:: from_le_bytes ( pad16 ( rc, is_signed) ) ;
803- match op {
804- BinOp :: Ge | BinOp :: Gt | BinOp :: Le | BinOp :: Lt | BinOp :: Eq | BinOp :: Ne => {
805- let r = match op {
806- BinOp :: Ge => l128 >= r128,
807- BinOp :: Gt => l128 > r128,
808- BinOp :: Le => l128 <= r128,
809- BinOp :: Lt => l128 < r128,
810- BinOp :: Eq => l128 == r128,
811- BinOp :: Ne => l128 != r128,
812- _ => unreachable ! ( ) ,
813- } ;
814- let r = r as u8 ;
815- Owned ( vec ! [ r] )
800+ if let TyKind :: Scalar ( chalk_ir:: Scalar :: Float ( f) ) = ty. kind ( Interner ) {
801+ match f {
802+ chalk_ir:: FloatTy :: F32 => {
803+ let l = from_bytes ! ( f32 , lc) ;
804+ let r = from_bytes ! ( f32 , rc) ;
805+ match op {
806+ BinOp :: Ge
807+ | BinOp :: Gt
808+ | BinOp :: Le
809+ | BinOp :: Lt
810+ | BinOp :: Eq
811+ | BinOp :: Ne => {
812+ let r = op. run_compare ( l, r) as u8 ;
813+ Owned ( vec ! [ r] )
814+ }
815+ BinOp :: Add | BinOp :: Sub | BinOp :: Mul | BinOp :: Div => {
816+ let r = match op {
817+ BinOp :: Add => l + r,
818+ BinOp :: Sub => l - r,
819+ BinOp :: Mul => l * r,
820+ BinOp :: Div => l / r,
821+ _ => unreachable ! ( ) ,
822+ } ;
823+ Owned ( r. to_le_bytes ( ) . into ( ) )
824+ }
825+ x => not_supported ! (
826+ "invalid binop {x:?} on floating point operators"
827+ ) ,
828+ }
829+ }
830+ chalk_ir:: FloatTy :: F64 => {
831+ let l = from_bytes ! ( f64 , lc) ;
832+ let r = from_bytes ! ( f64 , rc) ;
833+ match op {
834+ BinOp :: Ge
835+ | BinOp :: Gt
836+ | BinOp :: Le
837+ | BinOp :: Lt
838+ | BinOp :: Eq
839+ | BinOp :: Ne => {
840+ let r = op. run_compare ( l, r) as u8 ;
841+ Owned ( vec ! [ r] )
842+ }
843+ BinOp :: Add | BinOp :: Sub | BinOp :: Mul | BinOp :: Div => {
844+ let r = match op {
845+ BinOp :: Add => l + r,
846+ BinOp :: Sub => l - r,
847+ BinOp :: Mul => l * r,
848+ BinOp :: Div => l / r,
849+ _ => unreachable ! ( ) ,
850+ } ;
851+ Owned ( r. to_le_bytes ( ) . into ( ) )
852+ }
853+ x => not_supported ! (
854+ "invalid binop {x:?} on floating point operators"
855+ ) ,
856+ }
857+ }
816858 }
817- BinOp :: BitAnd
818- | BinOp :: BitOr
819- | BinOp :: BitXor
820- | BinOp :: Add
821- | BinOp :: Mul
822- | BinOp :: Div
823- | BinOp :: Rem
824- | BinOp :: Sub => {
825- let r = match op {
826- BinOp :: Add => l128. overflowing_add ( r128) . 0 ,
827- BinOp :: Mul => l128. overflowing_mul ( r128) . 0 ,
828- BinOp :: Div => l128. checked_div ( r128) . ok_or_else ( || {
829- MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) )
830- } ) ?,
831- BinOp :: Rem => l128. checked_rem ( r128) . ok_or_else ( || {
832- MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) )
833- } ) ?,
834- BinOp :: Sub => l128. overflowing_sub ( r128) . 0 ,
835- BinOp :: BitAnd => l128 & r128,
836- BinOp :: BitOr => l128 | r128,
837- BinOp :: BitXor => l128 ^ r128,
838- _ => unreachable ! ( ) ,
839- } ;
859+ } else {
860+ let is_signed = matches ! ( ty. as_builtin( ) , Some ( BuiltinType :: Int ( _) ) ) ;
861+ let l128 = i128:: from_le_bytes ( pad16 ( lc, is_signed) ) ;
862+ let r128 = i128:: from_le_bytes ( pad16 ( rc, is_signed) ) ;
863+ let check_overflow = |r : i128 | {
864+ // FIXME: this is not very correct, and only catches the basic cases.
840865 let r = r. to_le_bytes ( ) ;
841866 for & k in & r[ lc. len ( ) ..] {
842867 if k != 0 && ( k != 255 || !is_signed) {
843868 return Err ( MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) ) ) ;
844869 }
845870 }
846- Owned ( r[ 0 ..lc. len ( ) ] . into ( ) )
847- }
848- BinOp :: Shl | BinOp :: Shr => {
849- let shift_amount = if r128 < 0 {
850- return Err ( MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) ) ) ;
851- } else if r128 > 128 {
852- return Err ( MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) ) ) ;
853- } else {
854- r128 as u8
855- } ;
856- let r = match op {
857- BinOp :: Shl => l128 << shift_amount,
858- BinOp :: Shr => l128 >> shift_amount,
859- _ => unreachable ! ( ) ,
860- } ;
861- Owned ( r. to_le_bytes ( ) [ 0 ..lc. len ( ) ] . into ( ) )
871+ Ok ( Owned ( r[ 0 ..lc. len ( ) ] . into ( ) ) )
872+ } ;
873+ match op {
874+ BinOp :: Ge | BinOp :: Gt | BinOp :: Le | BinOp :: Lt | BinOp :: Eq | BinOp :: Ne => {
875+ let r = op. run_compare ( l128, r128) as u8 ;
876+ Owned ( vec ! [ r] )
877+ }
878+ BinOp :: BitAnd
879+ | BinOp :: BitOr
880+ | BinOp :: BitXor
881+ | BinOp :: Add
882+ | BinOp :: Mul
883+ | BinOp :: Div
884+ | BinOp :: Rem
885+ | BinOp :: Sub => {
886+ let r = match op {
887+ BinOp :: Add => l128. overflowing_add ( r128) . 0 ,
888+ BinOp :: Mul => l128. overflowing_mul ( r128) . 0 ,
889+ BinOp :: Div => l128. checked_div ( r128) . ok_or_else ( || {
890+ MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) )
891+ } ) ?,
892+ BinOp :: Rem => l128. checked_rem ( r128) . ok_or_else ( || {
893+ MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) )
894+ } ) ?,
895+ BinOp :: Sub => l128. overflowing_sub ( r128) . 0 ,
896+ BinOp :: BitAnd => l128 & r128,
897+ BinOp :: BitOr => l128 | r128,
898+ BinOp :: BitXor => l128 ^ r128,
899+ _ => unreachable ! ( ) ,
900+ } ;
901+ check_overflow ( r) ?
902+ }
903+ BinOp :: Shl | BinOp :: Shr => {
904+ let r = ' b: {
905+ if let Ok ( shift_amount) = u32:: try_from ( r128) {
906+ let r = match op {
907+ BinOp :: Shl => l128. checked_shl ( shift_amount) ,
908+ BinOp :: Shr => l128. checked_shr ( shift_amount) ,
909+ _ => unreachable ! ( ) ,
910+ } ;
911+ if let Some ( r) = r {
912+ break ' b r;
913+ }
914+ } ;
915+ return Err ( MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) ) ) ;
916+ } ;
917+ check_overflow ( r) ?
918+ }
919+ BinOp :: Offset => not_supported ! ( "offset binop" ) ,
862920 }
863- BinOp :: Offset => not_supported ! ( "offset binop" ) ,
864921 }
865922 }
866923 Rvalue :: Discriminant ( p) => {
0 commit comments