@@ -15,11 +15,15 @@ use rustc::ty::layout::{Layout, LayoutTyper};
15
15
use rustc:: mir:: tcx:: LvalueTy ;
16
16
use rustc:: mir;
17
17
use rustc:: middle:: lang_items:: ExchangeMallocFnLangItem ;
18
+ use rustc_apfloat:: { ieee, Float , Status , Round } ;
19
+ use rustc_const_math:: MAX_F32_PLUS_HALF_ULP ;
20
+ use std:: { u128, i128} ;
18
21
19
22
use base;
20
23
use builder:: Builder ;
21
24
use callee;
22
- use common:: { self , val_ty, C_bool , C_i32 , C_null , C_usize , C_uint } ;
25
+ use common:: { self , val_ty, C_bool , C_i32 , C_u32 , C_u64 , C_null , C_usize , C_uint , C_big_integral } ;
26
+ use consts;
23
27
use adt;
24
28
use machine;
25
29
use monomorphize;
@@ -333,14 +337,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
333
337
bcx. ptrtoint ( llval, ll_t_out) ,
334
338
( CastTy :: Int ( _) , CastTy :: Ptr ( _) ) =>
335
339
bcx. inttoptr ( llval, ll_t_out) ,
336
- ( CastTy :: Int ( _) , CastTy :: Float ) if signed =>
337
- bcx. sitofp ( llval, ll_t_out) ,
338
340
( CastTy :: Int ( _) , CastTy :: Float ) =>
339
- bcx . uitofp ( llval, ll_t_out) ,
341
+ cast_int_to_float ( & bcx , signed , llval, ll_t_in , ll_t_out) ,
340
342
( CastTy :: Float , CastTy :: Int ( IntTy :: I ) ) =>
341
- bcx . fptosi ( llval, ll_t_out) ,
343
+ cast_float_to_int ( & bcx , true , llval, ll_t_in , ll_t_out) ,
342
344
( CastTy :: Float , CastTy :: Int ( _) ) =>
343
- bcx . fptoui ( llval, ll_t_out) ,
345
+ cast_float_to_int ( & bcx , false , llval, ll_t_in , ll_t_out) ,
344
346
_ => bug ! ( "unsupported cast: {:?} to {:?}" , operand. ty, cast_ty)
345
347
} ;
346
348
OperandValue :: Immediate ( newval)
@@ -815,3 +817,158 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
815
817
816
818
bcx. ccx . get_intrinsic ( & name)
817
819
}
820
+
821
+ fn cast_int_to_float ( bcx : & Builder ,
822
+ signed : bool ,
823
+ x : ValueRef ,
824
+ int_ty : Type ,
825
+ float_ty : Type ) -> ValueRef {
826
+ // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
827
+ // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
828
+ // LLVM's uitofp produces undef in those cases, so we manually check for that case.
829
+ let is_u128_to_f32 = !signed && int_ty. int_width ( ) == 128 && float_ty. float_width ( ) == 32 ;
830
+ if is_u128_to_f32 && bcx. sess ( ) . opts . debugging_opts . saturating_float_casts {
831
+ // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
832
+ // and for everything else LLVM's uitofp works just fine.
833
+ let max = C_big_integral ( int_ty, MAX_F32_PLUS_HALF_ULP ) ;
834
+ let overflow = bcx. icmp ( llvm:: IntUGE , x, max) ;
835
+ let infinity_bits = C_u32 ( bcx. ccx , ieee:: Single :: INFINITY . to_bits ( ) as u32 ) ;
836
+ let infinity = consts:: bitcast ( infinity_bits, float_ty) ;
837
+ bcx. select ( overflow, infinity, bcx. uitofp ( x, float_ty) )
838
+ } else {
839
+ if signed {
840
+ bcx. sitofp ( x, float_ty)
841
+ } else {
842
+ bcx. uitofp ( x, float_ty)
843
+ }
844
+ }
845
+ }
846
+
847
+ fn cast_float_to_int ( bcx : & Builder ,
848
+ signed : bool ,
849
+ x : ValueRef ,
850
+ float_ty : Type ,
851
+ int_ty : Type ) -> ValueRef {
852
+ let fptosui_result = if signed {
853
+ bcx. fptosi ( x, int_ty)
854
+ } else {
855
+ bcx. fptoui ( x, int_ty)
856
+ } ;
857
+
858
+ if !bcx. sess ( ) . opts . debugging_opts . saturating_float_casts {
859
+ return fptosui_result;
860
+ }
861
+ // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
862
+ // destination integer type after rounding towards zero. This `undef` value can cause UB in
863
+ // safe code (see issue #10184), so we implement a saturating conversion on top of it:
864
+ // Semantically, the mathematical value of the input is rounded towards zero to the next
865
+ // mathematical integer, and then the result is clamped into the range of the destination
866
+ // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
867
+ // the destination integer type. NaN is mapped to 0.
868
+ //
869
+ // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
870
+ // a value representable in int_ty.
871
+ // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
872
+ // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
873
+ // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
874
+ // representable. Note that this only works if float_ty's exponent range is sufficently large.
875
+ // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
876
+ // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
877
+ // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
878
+ // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
879
+ // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
880
+ fn compute_clamp_bounds < F : Float > ( signed : bool , int_ty : Type ) -> ( u128 , u128 ) {
881
+ let rounded_min = F :: from_i128_r ( int_min ( signed, int_ty) , Round :: TowardZero ) ;
882
+ assert_eq ! ( rounded_min. status, Status :: OK ) ;
883
+ let rounded_max = F :: from_u128_r ( int_max ( signed, int_ty) , Round :: TowardZero ) ;
884
+ assert ! ( rounded_max. value. is_finite( ) ) ;
885
+ ( rounded_min. value . to_bits ( ) , rounded_max. value . to_bits ( ) )
886
+ }
887
+ fn int_max ( signed : bool , int_ty : Type ) -> u128 {
888
+ let shift_amount = 128 - int_ty. int_width ( ) ;
889
+ if signed {
890
+ i128:: MAX as u128 >> shift_amount
891
+ } else {
892
+ u128:: MAX >> shift_amount
893
+ }
894
+ }
895
+ fn int_min ( signed : bool , int_ty : Type ) -> i128 {
896
+ if signed {
897
+ i128:: MIN >> ( 128 - int_ty. int_width ( ) )
898
+ } else {
899
+ 0
900
+ }
901
+ }
902
+ let float_bits_to_llval = |bits| {
903
+ let bits_llval = match float_ty. float_width ( ) {
904
+ 32 => C_u32 ( bcx. ccx , bits as u32 ) ,
905
+ 64 => C_u64 ( bcx. ccx , bits as u64 ) ,
906
+ n => bug ! ( "unsupported float width {}" , n) ,
907
+ } ;
908
+ consts:: bitcast ( bits_llval, float_ty)
909
+ } ;
910
+ let ( f_min, f_max) = match float_ty. float_width ( ) {
911
+ 32 => compute_clamp_bounds :: < ieee:: Single > ( signed, int_ty) ,
912
+ 64 => compute_clamp_bounds :: < ieee:: Double > ( signed, int_ty) ,
913
+ n => bug ! ( "unsupported float width {}" , n) ,
914
+ } ;
915
+ let f_min = float_bits_to_llval ( f_min) ;
916
+ let f_max = float_bits_to_llval ( f_max) ;
917
+ // To implement saturation, we perform the following steps:
918
+ //
919
+ // 1. Cast x to an integer with fpto[su]i. This may result in undef.
920
+ // 2. Compare x to f_min and f_max, and use the comparison results to select:
921
+ // a) int_ty::MIN if x < f_min or x is NaN
922
+ // b) int_ty::MAX if x > f_max
923
+ // c) the result of fpto[su]i otherwise
924
+ // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
925
+ //
926
+ // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
927
+ // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
928
+ // undef does not introduce any non-determinism either.
929
+ // More importantly, the above procedure correctly implements saturating conversion.
930
+ // Proof (sketch):
931
+ // If x is NaN, 0 is returned by definition.
932
+ // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
933
+ // This yields three cases to consider:
934
+ // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
935
+ // saturating conversion for inputs in that range.
936
+ // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
937
+ // (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
938
+ // than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
939
+ // is correct.
940
+ // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
941
+ // int_ty::MIN and therefore the return value of int_ty::MIN is correct.
942
+ // QED.
943
+
944
+ // Step 1 was already performed above.
945
+
946
+ // Step 2: We use two comparisons and two selects, with %s1 being the result:
947
+ // %less_or_nan = fcmp ult %x, %f_min
948
+ // %greater = fcmp olt %x, %f_max
949
+ // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
950
+ // %s1 = select %greater, int_ty::MAX, %s0
951
+ // Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the
952
+ // operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1
953
+ // becomes int_ty::MIN if x is NaN.
954
+ // Performance note: Unordered comparison can be lowered to a "flipped" comparison and a
955
+ // negation, and the negation can be merged into the select. Therefore, it not necessarily any
956
+ // more expensive than a ordered ("normal") comparison. Whether these optimizations will be
957
+ // performed is ultimately up to the backend, but at least x86 does perform them.
958
+ let less_or_nan = bcx. fcmp ( llvm:: RealULT , x, f_min) ;
959
+ let greater = bcx. fcmp ( llvm:: RealOGT , x, f_max) ;
960
+ let int_max = C_big_integral ( int_ty, int_max ( signed, int_ty) ) ;
961
+ let int_min = C_big_integral ( int_ty, int_min ( signed, int_ty) as u128 ) ;
962
+ let s0 = bcx. select ( less_or_nan, int_min, fptosui_result) ;
963
+ let s1 = bcx. select ( greater, int_max, s0) ;
964
+
965
+ // Step 3: NaN replacement.
966
+ // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
967
+ // Therefore we only need to execute this step for signed integer types.
968
+ if signed {
969
+ // LLVM has no isNaN predicate, so we use (x == x) instead
970
+ bcx. select ( bcx. fcmp ( llvm:: RealOEQ , x, x) , s1, C_uint ( int_ty, 0 ) )
971
+ } else {
972
+ s1
973
+ }
974
+ }
0 commit comments