@@ -15,11 +15,15 @@ use rustc::ty::layout::{Layout, LayoutTyper};
1515use rustc:: mir:: tcx:: LvalueTy ;
1616use rustc:: mir;
1717use 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} ;
1821
1922use base;
2023use builder:: Builder ;
2124use 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;
2327use adt;
2428use machine;
2529use monomorphize;
@@ -333,14 +337,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
333337 bcx. ptrtoint ( llval, ll_t_out) ,
334338 ( CastTy :: Int ( _) , CastTy :: Ptr ( _) ) =>
335339 bcx. inttoptr ( llval, ll_t_out) ,
336- ( CastTy :: Int ( _) , CastTy :: Float ) if signed =>
337- bcx. sitofp ( llval, ll_t_out) ,
338340 ( 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) ,
340342 ( 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) ,
342344 ( 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) ,
344346 _ => bug ! ( "unsupported cast: {:?} to {:?}" , operand. ty, cast_ty)
345347 } ;
346348 OperandValue :: Immediate ( newval)
@@ -815,3 +817,158 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
815817
816818 bcx. ccx . get_intrinsic ( & name)
817819}
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