1
+ use std:: convert:: TryInto ;
2
+
3
+ use rustc_apfloat:: Float ;
1
4
use rustc:: ty:: layout:: { Align , LayoutOf , Size } ;
2
5
use rustc:: hir:: def_id:: DefId ;
3
6
use rustc:: mir;
@@ -577,7 +580,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
577
580
} ;
578
581
this. write_scalar ( Scalar :: from_u64 ( f. to_bits ( ) ) , dest) ?;
579
582
}
580
- // underscore case for windows
583
+ // underscore case for windows, here and below
584
+ // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
581
585
"_hypot" | "hypot" | "atan2" => {
582
586
// FIXME: Using host floats.
583
587
let f1 = f64:: from_bits ( this. read_scalar ( args[ 0 ] ) ?. to_u64 ( ) ?) ;
@@ -589,16 +593,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
589
593
} ;
590
594
this. write_scalar ( Scalar :: from_u64 ( n. to_bits ( ) ) , dest) ?;
591
595
}
592
- // underscore case for windows
593
- "_ldexp" | "ldexp" => {
594
- // FIXME: Using host floats.
595
- let x = f64:: from_bits ( this. read_scalar ( args[ 0 ] ) ?. to_u64 ( ) ?) ;
596
+ // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
597
+ "_ldexp" | "ldexp" | "scalbn" => {
598
+ let x = this. read_scalar ( args[ 0 ] ) ?. to_f64 ( ) ?;
596
599
let exp = this. read_scalar ( args[ 1 ] ) ?. to_i32 ( ) ?;
597
- extern {
598
- fn ldexp ( x : f64 , n : i32 ) -> f64 ;
599
- }
600
- let n = unsafe { ldexp ( x, exp) } ;
601
- this. write_scalar ( Scalar :: from_u64 ( n. to_bits ( ) ) , dest) ?;
600
+
601
+ // Saturating cast to i16. Even those are outside the valid exponent range to
602
+ // `scalbn` below will do its over/underflow handling.
603
+ let exp = if exp > i16:: max_value ( ) as i32 {
604
+ i16:: max_value ( )
605
+ } else if exp < i16:: min_value ( ) as i32 {
606
+ i16:: min_value ( )
607
+ } else {
608
+ exp. try_into ( ) . unwrap ( )
609
+ } ;
610
+
611
+ let res = x. scalbn ( exp) ;
612
+ this. write_scalar ( Scalar :: from_f64 ( res) , dest) ?;
602
613
}
603
614
604
615
// Some things needed for `sys::thread` initialization to go through.
0 commit comments