@@ -48,7 +48,7 @@ macro_rules! from_bytes {
48
48
( $ty: tt, $value: expr) => {
49
49
( $ty:: from_le_bytes( match ( $value) . try_into( ) {
50
50
Ok ( x) => x,
51
- Err ( _) => return Err ( MirEvalError :: TypeError ( " mismatched size" ) ) ,
51
+ Err ( _) => return Err ( MirEvalError :: TypeError ( stringify! ( mismatched size in constructing $ty ) ) ) ,
52
52
} ) )
53
53
} ;
54
54
}
@@ -797,70 +797,127 @@ impl Evaluator<'_> {
797
797
lc = self . read_memory ( Address :: from_bytes ( lc) ?, size) ?;
798
798
rc = self . read_memory ( Address :: from_bytes ( rc) ?, size) ?;
799
799
}
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
+ }
816
858
}
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.
840
865
let r = r. to_le_bytes ( ) ;
841
866
for & k in & r[ lc. len ( ) ..] {
842
867
if k != 0 && ( k != 255 || !is_signed) {
843
868
return Err ( MirEvalError :: Panic ( format ! ( "Overflow in {op:?}" ) ) ) ;
844
869
}
845
870
}
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" ) ,
862
920
}
863
- BinOp :: Offset => not_supported ! ( "offset binop" ) ,
864
921
}
865
922
}
866
923
Rvalue :: Discriminant ( p) => {
0 commit comments