@@ -3,7 +3,6 @@ use std::io::Write;
3
3
use std:: path:: Path ;
4
4
5
5
use rustc_abi:: { Align , AlignFromBytesError , CanonAbi , Size } ;
6
- use rustc_apfloat:: Float ;
7
6
use rustc_ast:: expand:: allocator:: alloc_error_handler_name;
8
7
use rustc_hir:: attrs:: Linkage ;
9
8
use rustc_hir:: def:: DefKind ;
@@ -15,7 +14,6 @@ use rustc_middle::{mir, ty};
15
14
use rustc_span:: Symbol ;
16
15
use rustc_target:: callconv:: FnAbi ;
17
16
18
- use self :: helpers:: { ToHost , ToSoft } ;
19
17
use super :: alloc:: EvalContextExt as _;
20
18
use super :: backtrace:: EvalContextExt as _;
21
19
use crate :: helpers:: EvalContextExt as _;
@@ -818,225 +816,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
818
816
this. write_pointer ( ptr_dest, dest) ?;
819
817
}
820
818
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
-
1040
819
// LLVM intrinsics
1041
820
"llvm.prefetch" => {
1042
821
let [ p, rw, loc, ty] =
@@ -1118,8 +897,18 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
1118
897
}
1119
898
}
1120
899
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
1123
912
return match this. tcx . sess . target . os . as_ref ( ) {
1124
913
_ if this. target_os_is_unix ( ) =>
1125
914
shims:: unix:: foreign_items:: EvalContextExt :: emulate_foreign_item_inner (
@@ -1134,7 +923,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
1134
923
this, link_name, abi, args, dest,
1135
924
) ,
1136
925
_ => interp_ok ( EmulateItemResult :: NotSupported ) ,
1137
- } ,
926
+ } ;
927
+ }
1138
928
} ;
1139
929
// We only fall through to here if we did *not* hit the `_` arm above,
1140
930
// i.e., if we actually emulated the function with one of the shims.
0 commit comments