@@ -3,7 +3,6 @@ use std::io::Write;
33use std:: path:: Path ;
44
55use rustc_abi:: { Align , AlignFromBytesError , CanonAbi , Size } ;
6- use rustc_apfloat:: Float ;
76use rustc_ast:: expand:: allocator:: alloc_error_handler_name;
87use rustc_hir:: attrs:: Linkage ;
98use rustc_hir:: def:: DefKind ;
@@ -15,7 +14,6 @@ use rustc_middle::{mir, ty};
1514use rustc_span:: Symbol ;
1615use rustc_target:: callconv:: FnAbi ;
1716
18- use self :: helpers:: { ToHost , ToSoft } ;
1917use super :: alloc:: EvalContextExt as _;
2018use super :: backtrace:: EvalContextExt as _;
2119use crate :: helpers:: EvalContextExt as _;
@@ -818,225 +816,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
818816 this. write_pointer ( ptr_dest, dest) ?;
819817 }
820818
821- // math functions (note that there are also intrinsics for some other functions)
822- #[ rustfmt:: skip]
823- | "cbrtf"
824- | "coshf"
825- | "sinhf"
826- | "tanf"
827- | "tanhf"
828- | "acosf"
829- | "asinf"
830- | "atanf"
831- | "log1pf"
832- | "expm1f"
833- | "tgammaf"
834- | "erff"
835- | "erfcf"
836- => {
837- let [ f] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
838- let f = this. read_scalar ( f) ?. to_f32 ( ) ?;
839-
840- let res = math:: fixed_float_value ( this, link_name. as_str ( ) , & [ f] ) . unwrap_or_else ( || {
841- // Using host floats (but it's fine, these operations do not have
842- // guaranteed precision).
843- let f_host = f. to_host ( ) ;
844- let res = match link_name. as_str ( ) {
845- "cbrtf" => f_host. cbrt ( ) ,
846- "coshf" => f_host. cosh ( ) ,
847- "sinhf" => f_host. sinh ( ) ,
848- "tanf" => f_host. tan ( ) ,
849- "tanhf" => f_host. tanh ( ) ,
850- "acosf" => f_host. acos ( ) ,
851- "asinf" => f_host. asin ( ) ,
852- "atanf" => f_host. atan ( ) ,
853- "log1pf" => f_host. ln_1p ( ) ,
854- "expm1f" => f_host. exp_m1 ( ) ,
855- "tgammaf" => f_host. gamma ( ) ,
856- "erff" => f_host. erf ( ) ,
857- "erfcf" => f_host. erfc ( ) ,
858- _ => bug ! ( ) ,
859- } ;
860- let res = res. to_soft ( ) ;
861- // Apply a relative error of 4ULP to introduce some non-determinism
862- // simulating imprecise implementations and optimizations.
863- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
864-
865- // Clamp the result to the guaranteed range of this function according to the C standard,
866- // if any.
867- math:: clamp_float_value ( link_name. as_str ( ) , res)
868- } ) ;
869- let res = this. adjust_nan ( res, & [ f] ) ;
870- this. write_scalar ( res, dest) ?;
871- }
872- #[ rustfmt:: skip]
873- | "_hypotf"
874- | "hypotf"
875- | "atan2f"
876- | "fdimf"
877- => {
878- let [ f1, f2] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
879- let f1 = this. read_scalar ( f1) ?. to_f32 ( ) ?;
880- let f2 = this. read_scalar ( f2) ?. to_f32 ( ) ?;
881-
882- let res = math:: fixed_float_value ( this, link_name. as_str ( ) , & [ f1, f2] )
883- . unwrap_or_else ( || {
884- let res = match link_name. as_str ( ) {
885- // underscore case for windows, here and below
886- // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
887- // Using host floats (but it's fine, these operations do not have guaranteed precision).
888- "_hypotf" | "hypotf" => f1. to_host ( ) . hypot ( f2. to_host ( ) ) . to_soft ( ) ,
889- "atan2f" => f1. to_host ( ) . atan2 ( f2. to_host ( ) ) . to_soft ( ) ,
890- #[ allow( deprecated) ]
891- "fdimf" => f1. to_host ( ) . abs_sub ( f2. to_host ( ) ) . to_soft ( ) ,
892- _ => bug ! ( ) ,
893- } ;
894- // Apply a relative error of 4ULP to introduce some non-determinism
895- // simulating imprecise implementations and optimizations.
896- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
897-
898- // Clamp the result to the guaranteed range of this function according to the C standard,
899- // if any.
900- math:: clamp_float_value ( link_name. as_str ( ) , res)
901- } ) ;
902- let res = this. adjust_nan ( res, & [ f1, f2] ) ;
903- this. write_scalar ( res, dest) ?;
904- }
905- #[ rustfmt:: skip]
906- | "cbrt"
907- | "cosh"
908- | "sinh"
909- | "tan"
910- | "tanh"
911- | "acos"
912- | "asin"
913- | "atan"
914- | "log1p"
915- | "expm1"
916- | "tgamma"
917- | "erf"
918- | "erfc"
919- => {
920- let [ f] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
921- let f = this. read_scalar ( f) ?. to_f64 ( ) ?;
922-
923- let res = math:: fixed_float_value ( this, link_name. as_str ( ) , & [ f] ) . unwrap_or_else ( || {
924- // Using host floats (but it's fine, these operations do not have
925- // guaranteed precision).
926- let f_host = f. to_host ( ) ;
927- let res = match link_name. as_str ( ) {
928- "cbrt" => f_host. cbrt ( ) ,
929- "cosh" => f_host. cosh ( ) ,
930- "sinh" => f_host. sinh ( ) ,
931- "tan" => f_host. tan ( ) ,
932- "tanh" => f_host. tanh ( ) ,
933- "acos" => f_host. acos ( ) ,
934- "asin" => f_host. asin ( ) ,
935- "atan" => f_host. atan ( ) ,
936- "log1p" => f_host. ln_1p ( ) ,
937- "expm1" => f_host. exp_m1 ( ) ,
938- "tgamma" => f_host. gamma ( ) ,
939- "erf" => f_host. erf ( ) ,
940- "erfc" => f_host. erfc ( ) ,
941- _ => bug ! ( ) ,
942- } ;
943- let res = res. to_soft ( ) ;
944- // Apply a relative error of 4ULP to introduce some non-determinism
945- // simulating imprecise implementations and optimizations.
946- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
947-
948- // Clamp the result to the guaranteed range of this function according to the C standard,
949- // if any.
950- math:: clamp_float_value ( link_name. as_str ( ) , res)
951- } ) ;
952- let res = this. adjust_nan ( res, & [ f] ) ;
953- this. write_scalar ( res, dest) ?;
954- }
955- #[ rustfmt:: skip]
956- | "_hypot"
957- | "hypot"
958- | "atan2"
959- | "fdim"
960- => {
961- let [ f1, f2] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
962- let f1 = this. read_scalar ( f1) ?. to_f64 ( ) ?;
963- let f2 = this. read_scalar ( f2) ?. to_f64 ( ) ?;
964-
965- let res = math:: fixed_float_value ( this, link_name. as_str ( ) , & [ f1, f2] ) . unwrap_or_else ( || {
966- let res = match link_name. as_str ( ) {
967- // underscore case for windows, here and below
968- // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
969- // Using host floats (but it's fine, these operations do not have guaranteed precision).
970- "_hypot" | "hypot" => f1. to_host ( ) . hypot ( f2. to_host ( ) ) . to_soft ( ) ,
971- "atan2" => f1. to_host ( ) . atan2 ( f2. to_host ( ) ) . to_soft ( ) ,
972- #[ allow( deprecated) ]
973- "fdim" => f1. to_host ( ) . abs_sub ( f2. to_host ( ) ) . to_soft ( ) ,
974- _ => bug ! ( ) ,
975- } ;
976- // Apply a relative error of 4ULP to introduce some non-determinism
977- // simulating imprecise implementations and optimizations.
978- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
979-
980- // Clamp the result to the guaranteed range of this function according to the C standard,
981- // if any.
982- math:: clamp_float_value ( link_name. as_str ( ) , res)
983- } ) ;
984- let res = this. adjust_nan ( res, & [ f1, f2] ) ;
985- this. write_scalar ( res, dest) ?;
986- }
987- #[ rustfmt:: skip]
988- | "_ldexp"
989- | "ldexp"
990- | "scalbn"
991- => {
992- let [ x, exp] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
993- // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
994- let x = this. read_scalar ( x) ?. to_f64 ( ) ?;
995- let exp = this. read_scalar ( exp) ?. to_i32 ( ) ?;
996-
997- let res = x. scalbn ( exp) ;
998- let res = this. adjust_nan ( res, & [ x] ) ;
999- this. write_scalar ( res, dest) ?;
1000- }
1001- "lgammaf_r" => {
1002- let [ x, signp] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
1003- let x = this. read_scalar ( x) ?. to_f32 ( ) ?;
1004- let signp = this. deref_pointer_as ( signp, this. machine . layouts . i32 ) ?;
1005-
1006- // Using host floats (but it's fine, these operations do not have guaranteed precision).
1007- let ( res, sign) = x. to_host ( ) . ln_gamma ( ) ;
1008- this. write_int ( sign, & signp) ?;
1009-
1010- let res = res. to_soft ( ) ;
1011- // Apply a relative error of 4ULP to introduce some non-determinism
1012- // simulating imprecise implementations and optimizations.
1013- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
1014- // Clamp the result to the guaranteed range of this function according to the C standard,
1015- // if any.
1016- let res = math:: clamp_float_value ( link_name. as_str ( ) , res) ;
1017- let res = this. adjust_nan ( res, & [ x] ) ;
1018- this. write_scalar ( res, dest) ?;
1019- }
1020- "lgamma_r" => {
1021- let [ x, signp] = this. check_shim_sig_lenient ( abi, CanonAbi :: C , link_name, args) ?;
1022- let x = this. read_scalar ( x) ?. to_f64 ( ) ?;
1023- let signp = this. deref_pointer_as ( signp, this. machine . layouts . i32 ) ?;
1024-
1025- // Using host floats (but it's fine, these operations do not have guaranteed precision).
1026- let ( res, sign) = x. to_host ( ) . ln_gamma ( ) ;
1027- this. write_int ( sign, & signp) ?;
1028-
1029- let res = res. to_soft ( ) ;
1030- // Apply a relative error of 4ULP to introduce some non-determinism
1031- // simulating imprecise implementations and optimizations.
1032- let res = math:: apply_random_float_error_ulp ( this, res, 4 ) ;
1033- // Clamp the result to the guaranteed range of this function according to the C standard,
1034- // if any.
1035- let res = math:: clamp_float_value ( link_name. as_str ( ) , res) ;
1036- let res = this. adjust_nan ( res, & [ x] ) ;
1037- this. write_scalar ( res, dest) ?;
1038- }
1039-
1040819 // LLVM intrinsics
1041820 "llvm.prefetch" => {
1042821 let [ p, rw, loc, ty] =
@@ -1118,8 +897,18 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
1118897 }
1119898 }
1120899
1121- // Platform-specific shims
1122- _ =>
900+ // Fallback to shims in submodules.
901+ _ => {
902+ // Math shims
903+ #[ expect( irrefutable_let_patterns) ]
904+ if let res = shims:: math:: EvalContextExt :: emulate_foreign_item_inner (
905+ this, link_name, abi, args, dest,
906+ ) ? && !matches ! ( res, EmulateItemResult :: NotSupported )
907+ {
908+ return interp_ok ( res) ;
909+ }
910+
911+ // Platform-specific shims
1123912 return match this. tcx . sess . target . os . as_ref ( ) {
1124913 _ if this. target_os_is_unix ( ) =>
1125914 shims:: unix:: foreign_items:: EvalContextExt :: emulate_foreign_item_inner (
@@ -1134,7 +923,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
1134923 this, link_name, abi, args, dest,
1135924 ) ,
1136925 _ => interp_ok ( EmulateItemResult :: NotSupported ) ,
1137- } ,
926+ } ;
927+ }
1138928 } ;
1139929 // We only fall through to here if we did *not* hit the `_` arm above,
1140930 // i.e., if we actually emulated the function with one of the shims.
0 commit comments