@@ -5,17 +5,18 @@ use std::time::Duration;
55
66use  log:: trace; 
77
8+ use  rustc_apfloat:: ieee:: { Double ,  Single } ; 
89use  rustc_hir:: def:: { DefKind ,  Namespace } ; 
910use  rustc_hir:: def_id:: { DefId ,  CRATE_DEF_INDEX } ; 
1011use  rustc_index:: IndexVec ; 
1112use  rustc_middle:: mir; 
1213use  rustc_middle:: ty:: { 
1314    self , 
14-     layout:: { IntegerExt   as  _ ,   LayoutOf ,  TyAndLayout } , 
15-     IntTy ,  Ty ,  TyCtxt ,  UintTy , 
15+     layout:: { LayoutOf ,  TyAndLayout } , 
16+     FloatTy ,   IntTy ,  Ty ,  TyCtxt ,  UintTy , 
1617} ; 
1718use  rustc_span:: { def_id:: CrateNum ,  sym,  Span ,  Symbol } ; 
18- use  rustc_target:: abi:: { Align ,  FieldIdx ,  FieldsShape ,  Integer ,   Size ,  Variants } ; 
19+ use  rustc_target:: abi:: { Align ,  FieldIdx ,  FieldsShape ,  Size ,  Variants } ; 
1920use  rustc_target:: spec:: abi:: Abi ; 
2021
2122use  rand:: RngCore ; 
@@ -565,10 +566,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
565566/// is part of the UNIX family. It panics showing a message with the `name` of the foreign function 
566567/// if this is not the case. 
567568fn  assert_target_os_is_unix ( & self ,  name :  & str )  { 
568-         assert ! ( 
569-             target_os_is_unix( self . eval_context_ref( ) . tcx. sess. target. os. as_ref( ) ) , 
570-             "`{name}` is only available for supported UNIX family targets" , 
571-         ) ; 
569+         assert ! ( self . target_os_is_unix( ) ,  "`{name}` is only available for unix targets" , ) ; 
570+     } 
571+ 
572+     fn  target_os_is_unix ( & self )  -> bool  { 
573+         self . eval_context_ref ( ) . tcx . sess . target . families . iter ( ) . any ( |f| f == "unix" ) 
572574    } 
573575
574576    /// Get last error variable as a place, lazily allocating thread-local storage for it if 
@@ -985,65 +987,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
985987        } 
986988    } 
987989
988-     /// Converts `f` to integer type `dest_ty` after rounding with mode `round`. 
990+     /// Converts `src` from floating point to integer type `dest_ty` 
991+ /// after rounding with mode `round`. 
989992/// Returns `None` if `f` is NaN or out of range. 
990- fn  float_to_int_checked < F > ( 
993+ fn  float_to_int_checked ( 
991994        & self , 
992-         f :   F , 
995+         src :   & ImmTy < ' tcx ,   Provenance > , 
993996        cast_to :  TyAndLayout < ' tcx > , 
994997        round :  rustc_apfloat:: Round , 
995-     )  -> Option < ImmTy < ' tcx ,  Provenance > > 
996-     where 
997-         F :  rustc_apfloat:: Float  + Into < Scalar < Provenance > > , 
998-     { 
998+     )  -> InterpResult < ' tcx ,  Option < ImmTy < ' tcx ,  Provenance > > >  { 
999999        let  this = self . eval_context_ref ( ) ; 
10001000
1001-         let  val = match  cast_to. ty . kind ( )  { 
1002-             // Unsigned 
1003-             ty:: Uint ( t)  => { 
1004-                 let  size = Integer :: from_uint_ty ( this,  * t) . size ( ) ; 
1005-                 let  res = f. to_u128_r ( size. bits_usize ( ) ,  round,  & mut  false ) ; 
1006-                 if  res. status . intersects ( 
1007-                     rustc_apfloat:: Status :: INVALID_OP 
1008-                         | rustc_apfloat:: Status :: OVERFLOW 
1009-                         | rustc_apfloat:: Status :: UNDERFLOW , 
1010-                 )  { 
1011-                     // Floating point value is NaN (flagged with INVALID_OP) or outside the range 
1012-                     // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). 
1013-                     return  None ; 
1014-                 }  else  { 
1015-                     // Floating point value can be represented by the integer type after rounding. 
1016-                     // The INEXACT flag is ignored on purpose to allow rounding. 
1017-                     Scalar :: from_uint ( res. value ,  size) 
1001+         fn  float_to_int_inner < ' tcx ,  F :  rustc_apfloat:: Float > ( 
1002+             this :  & MiriInterpCx < ' _ ,  ' tcx > , 
1003+             src :  F , 
1004+             cast_to :  TyAndLayout < ' tcx > , 
1005+             round :  rustc_apfloat:: Round , 
1006+         )  -> ( Scalar < Provenance > ,  rustc_apfloat:: Status )  { 
1007+             let  int_size = cast_to. layout . size ; 
1008+             match  cast_to. ty . kind ( )  { 
1009+                 // Unsigned 
1010+                 ty:: Uint ( _)  => { 
1011+                     let  res = src. to_u128_r ( int_size. bits_usize ( ) ,  round,  & mut  false ) ; 
1012+                     ( Scalar :: from_uint ( res. value ,  int_size) ,  res. status ) 
10181013                } 
1019-             } 
1020-             // Signed 
1021-             ty:: Int ( t)  => { 
1022-                 let  size = Integer :: from_int_ty ( this,  * t) . size ( ) ; 
1023-                 let  res = f. to_i128_r ( size. bits_usize ( ) ,  round,  & mut  false ) ; 
1024-                 if  res. status . intersects ( 
1025-                     rustc_apfloat:: Status :: INVALID_OP 
1026-                         | rustc_apfloat:: Status :: OVERFLOW 
1027-                         | rustc_apfloat:: Status :: UNDERFLOW , 
1028-                 )  { 
1029-                     // Floating point value is NaN (flagged with INVALID_OP) or outside the range 
1030-                     // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). 
1031-                     return  None ; 
1032-                 }  else  { 
1033-                     // Floating point value can be represented by the integer type after rounding. 
1034-                     // The INEXACT flag is ignored on purpose to allow rounding. 
1035-                     Scalar :: from_int ( res. value ,  size) 
1014+                 // Signed 
1015+                 ty:: Int ( _)  => { 
1016+                     let  res = src. to_i128_r ( int_size. bits_usize ( ) ,  round,  & mut  false ) ; 
1017+                     ( Scalar :: from_int ( res. value ,  int_size) ,  res. status ) 
10361018                } 
1019+                 // Nothing else 
1020+                 _ =>
1021+                     span_bug ! ( 
1022+                         this. cur_span( ) , 
1023+                         "attempted float-to-int conversion with non-int output type {}" , 
1024+                         cast_to. ty, 
1025+                     ) , 
10371026            } 
1027+         } 
1028+ 
1029+         let  ( val,  status)  = match  src. layout . ty . kind ( )  { 
1030+             // f32 
1031+             ty:: Float ( FloatTy :: F32 )  =>
1032+                 float_to_int_inner :: < Single > ( this,  src. to_scalar ( ) . to_f32 ( ) ?,  cast_to,  round) , 
1033+             // f64 
1034+             ty:: Float ( FloatTy :: F64 )  =>
1035+                 float_to_int_inner :: < Double > ( this,  src. to_scalar ( ) . to_f64 ( ) ?,  cast_to,  round) , 
10381036            // Nothing else 
10391037            _ =>
10401038                span_bug ! ( 
10411039                    this. cur_span( ) , 
1042-                     "attempted float-to-int conversion with non-int output  type {}" , 
1043-                     cast_to . ty, 
1040+                     "attempted float-to-int conversion with non-float input  type {}" , 
1041+                     src . layout . ty, 
10441042                ) , 
10451043        } ; 
1046-         Some ( ImmTy :: from_scalar ( val,  cast_to) ) 
1044+ 
1045+         if  status. intersects ( 
1046+             rustc_apfloat:: Status :: INVALID_OP 
1047+                 | rustc_apfloat:: Status :: OVERFLOW 
1048+                 | rustc_apfloat:: Status :: UNDERFLOW , 
1049+         )  { 
1050+             // Floating point value is NaN (flagged with INVALID_OP) or outside the range 
1051+             // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). 
1052+             Ok ( None ) 
1053+         }  else  { 
1054+             // Floating point value can be represented by the integer type after rounding. 
1055+             // The INEXACT flag is ignored on purpose to allow rounding. 
1056+             Ok ( Some ( ImmTy :: from_scalar ( val,  cast_to) ) ) 
1057+         } 
10471058    } 
10481059
10491060    /// Returns an integer type that is twice wide as `ty` 
@@ -1063,6 +1074,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10631074            _ => span_bug ! ( this. cur_span( ) ,  "unexpected type: {ty:?}" ) , 
10641075        } 
10651076    } 
1077+ 
1078+     /// Checks that target feature `target_feature` is enabled. 
1079+ /// 
1080+ /// If not enabled, emits an UB error that states that the feature is 
1081+ /// required by `intrinsic`. 
1082+ fn  expect_target_feature_for_intrinsic ( 
1083+         & self , 
1084+         intrinsic :  Symbol , 
1085+         target_feature :  & str , 
1086+     )  -> InterpResult < ' tcx ,  ( ) >  { 
1087+         let  this = self . eval_context_ref ( ) ; 
1088+         if  !this. tcx . sess . unstable_target_features . contains ( & Symbol :: intern ( target_feature) )  { 
1089+             throw_ub_format ! ( 
1090+                 "attempted to call intrinsic `{intrinsic}` that requires missing target feature {target_feature}" 
1091+             ) ; 
1092+         } 
1093+         Ok ( ( ) ) 
1094+     } 
10661095} 
10671096
10681097impl < ' mir ,  ' tcx >  MiriMachine < ' mir ,  ' tcx >  { 
@@ -1143,12 +1172,6 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
11431172    local_crates
11441173} 
11451174
1146- /// Helper function used inside the shims of foreign functions to check that 
1147- /// `target_os` is a supported UNIX OS. 
1148- pub  fn  target_os_is_unix ( target_os :  & str )  -> bool  { 
1149-     matches ! ( target_os,  "linux"  | "macos"  | "freebsd"  | "android" ) 
1150- } 
1151- 
11521175pub ( crate )  fn  bool_to_simd_element ( b :  bool ,  size :  Size )  -> Scalar < Provenance >  { 
11531176    // SIMD uses all-1 as pattern for "true". In two's complement, 
11541177    // -1 has all its bits set to one and `from_int` will truncate or 
0 commit comments