Skip to content

Commit 6579378

Browse files
authored
Rollup merge of rust-lang#119574 - RalfJung:miri, r=oli-obk
Miri subtree update r? `@ghost`
2 parents ee882d6 + 5aa15b6 commit 6579378

34 files changed

+765
-308
lines changed

src/tools/miri/src/helpers.rs

+45-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::time::Duration;
66
use log::trace;
77

88
use rustc_apfloat::ieee::{Double, Single};
9+
use rustc_apfloat::Float;
910
use rustc_hir::def::{DefKind, Namespace};
1011
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
1112
use rustc_index::IndexVec;
@@ -117,6 +118,50 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
117118
}
118119
}
119120

121+
/// Convert a softfloat type to its corresponding hostfloat type.
122+
pub trait ToHost {
123+
type HostFloat;
124+
fn to_host(self) -> Self::HostFloat;
125+
}
126+
127+
/// Convert a hostfloat type to its corresponding softfloat type.
128+
pub trait ToSoft {
129+
type SoftFloat;
130+
fn to_soft(self) -> Self::SoftFloat;
131+
}
132+
133+
impl ToHost for rustc_apfloat::ieee::Double {
134+
type HostFloat = f64;
135+
136+
fn to_host(self) -> Self::HostFloat {
137+
f64::from_bits(self.to_bits().try_into().unwrap())
138+
}
139+
}
140+
141+
impl ToSoft for f64 {
142+
type SoftFloat = rustc_apfloat::ieee::Double;
143+
144+
fn to_soft(self) -> Self::SoftFloat {
145+
Float::from_bits(self.to_bits().into())
146+
}
147+
}
148+
149+
impl ToHost for rustc_apfloat::ieee::Single {
150+
type HostFloat = f32;
151+
152+
fn to_host(self) -> Self::HostFloat {
153+
f32::from_bits(self.to_bits().try_into().unwrap())
154+
}
155+
}
156+
157+
impl ToSoft for f32 {
158+
type SoftFloat = rustc_apfloat::ieee::Single;
159+
160+
fn to_soft(self) -> Self::SoftFloat {
161+
Float::from_bits(self.to_bits().into())
162+
}
163+
}
164+
120165
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
121166
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
122167
/// Checks if the given crate/module exists.
@@ -1188,11 +1233,3 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
11881233
_ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
11891234
})
11901235
}
1191-
1192-
// This looks like something that would be nice to have in the standard library...
1193-
pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 {
1194-
assert_ne!(divisor, 0);
1195-
// divisor is nonzero; multiplication cannot overflow since we just divided
1196-
#[allow(clippy::arithmetic_side_effects)]
1197-
return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor;
1198-
}

src/tools/miri/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![feature(round_ties_even)]
1212
#![feature(let_chains)]
1313
#![feature(lint_reasons)]
14+
#![feature(int_roundings)]
1415
// Configure clippy and other lints
1516
#![allow(
1617
clippy::collapsible_else_if,

src/tools/miri/src/operator.rs

+4
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
118118
nan
119119
}
120120
}
121+
122+
fn adjust_nan<F1: Float + FloatConvert<F2>, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 {
123+
if f.is_nan() { self.generate_nan(inputs) } else { f }
124+
}
121125
}

src/tools/miri/src/shims/foreign_items.rs

+61-47
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc_target::{
2323

2424
use super::backtrace::EvalContextExt as _;
2525
use crate::*;
26+
use helpers::{ToHost, ToSoft};
2627

2728
/// Type of dynamic symbols (for `dlsym` et al)
2829
#[derive(Debug, Copy, Clone)]
@@ -886,23 +887,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
886887
| "tgammaf"
887888
=> {
888889
let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
890+
let f = this.read_scalar(f)?.to_f32()?;
889891
// FIXME: Using host floats.
890-
let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
892+
let f_host = f.to_host();
891893
let res = match link_name.as_str() {
892-
"cbrtf" => f.cbrt(),
893-
"coshf" => f.cosh(),
894-
"sinhf" => f.sinh(),
895-
"tanf" => f.tan(),
896-
"tanhf" => f.tanh(),
897-
"acosf" => f.acos(),
898-
"asinf" => f.asin(),
899-
"atanf" => f.atan(),
900-
"log1pf" => f.ln_1p(),
901-
"expm1f" => f.exp_m1(),
902-
"tgammaf" => f.gamma(),
894+
"cbrtf" => f_host.cbrt(),
895+
"coshf" => f_host.cosh(),
896+
"sinhf" => f_host.sinh(),
897+
"tanf" => f_host.tan(),
898+
"tanhf" => f_host.tanh(),
899+
"acosf" => f_host.acos(),
900+
"asinf" => f_host.asin(),
901+
"atanf" => f_host.atan(),
902+
"log1pf" => f_host.ln_1p(),
903+
"expm1f" => f_host.exp_m1(),
904+
"tgammaf" => f_host.gamma(),
903905
_ => bug!(),
904906
};
905-
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
907+
let res = res.to_soft();
908+
let res = this.adjust_nan(res, &[f]);
909+
this.write_scalar(res, dest)?;
906910
}
907911
#[rustfmt::skip]
908912
| "_hypotf"
@@ -911,19 +915,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
911915
| "fdimf"
912916
=> {
913917
let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
918+
let f1 = this.read_scalar(f1)?.to_f32()?;
919+
let f2 = this.read_scalar(f2)?.to_f32()?;
914920
// underscore case for windows, here and below
915921
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
916922
// FIXME: Using host floats.
917-
let f1 = f32::from_bits(this.read_scalar(f1)?.to_u32()?);
918-
let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?);
919923
let res = match link_name.as_str() {
920-
"_hypotf" | "hypotf" => f1.hypot(f2),
921-
"atan2f" => f1.atan2(f2),
924+
"_hypotf" | "hypotf" => f1.to_host().hypot(f2.to_host()).to_soft(),
925+
"atan2f" => f1.to_host().atan2(f2.to_host()).to_soft(),
922926
#[allow(deprecated)]
923-
"fdimf" => f1.abs_sub(f2),
927+
"fdimf" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
924928
_ => bug!(),
925929
};
926-
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
930+
let res = this.adjust_nan(res, &[f1, f2]);
931+
this.write_scalar(res, dest)?;
927932
}
928933
#[rustfmt::skip]
929934
| "cbrt"
@@ -939,23 +944,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
939944
| "tgamma"
940945
=> {
941946
let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
947+
let f = this.read_scalar(f)?.to_f64()?;
942948
// FIXME: Using host floats.
943-
let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
949+
let f_host = f.to_host();
944950
let res = match link_name.as_str() {
945-
"cbrt" => f.cbrt(),
946-
"cosh" => f.cosh(),
947-
"sinh" => f.sinh(),
948-
"tan" => f.tan(),
949-
"tanh" => f.tanh(),
950-
"acos" => f.acos(),
951-
"asin" => f.asin(),
952-
"atan" => f.atan(),
953-
"log1p" => f.ln_1p(),
954-
"expm1" => f.exp_m1(),
955-
"tgamma" => f.gamma(),
951+
"cbrt" => f_host.cbrt(),
952+
"cosh" => f_host.cosh(),
953+
"sinh" => f_host.sinh(),
954+
"tan" => f_host.tan(),
955+
"tanh" => f_host.tanh(),
956+
"acos" => f_host.acos(),
957+
"asin" => f_host.asin(),
958+
"atan" => f_host.atan(),
959+
"log1p" => f_host.ln_1p(),
960+
"expm1" => f_host.exp_m1(),
961+
"tgamma" => f_host.gamma(),
956962
_ => bug!(),
957963
};
958-
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
964+
let res = res.to_soft();
965+
let res = this.adjust_nan(res, &[f]);
966+
this.write_scalar(res, dest)?;
959967
}
960968
#[rustfmt::skip]
961969
| "_hypot"
@@ -964,17 +972,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
964972
| "fdim"
965973
=> {
966974
let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
975+
let f1 = this.read_scalar(f1)?.to_f64()?;
976+
let f2 = this.read_scalar(f2)?.to_f64()?;
977+
// underscore case for windows, here and below
978+
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
967979
// FIXME: Using host floats.
968-
let f1 = f64::from_bits(this.read_scalar(f1)?.to_u64()?);
969-
let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?);
970980
let res = match link_name.as_str() {
971-
"_hypot" | "hypot" => f1.hypot(f2),
972-
"atan2" => f1.atan2(f2),
981+
"_hypot" | "hypot" => f1.to_host().hypot(f2.to_host()).to_soft(),
982+
"atan2" => f1.to_host().atan2(f2.to_host()).to_soft(),
973983
#[allow(deprecated)]
974-
"fdim" => f1.abs_sub(f2),
984+
"fdim" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
975985
_ => bug!(),
976986
};
977-
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
987+
let res = this.adjust_nan(res, &[f1, f2]);
988+
this.write_scalar(res, dest)?;
978989
}
979990
#[rustfmt::skip]
980991
| "_ldexp"
@@ -987,27 +998,30 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
987998
let exp = this.read_scalar(exp)?.to_i32()?;
988999

9891000
let res = x.scalbn(exp);
990-
this.write_scalar(Scalar::from_f64(res), dest)?;
1001+
let res = this.adjust_nan(res, &[x]);
1002+
this.write_scalar(res, dest)?;
9911003
}
9921004
"lgammaf_r" => {
9931005
let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
994-
// FIXME: Using host floats.
995-
let x = f32::from_bits(this.read_scalar(x)?.to_u32()?);
1006+
let x = this.read_scalar(x)?.to_f32()?;
9961007
let signp = this.deref_pointer(signp)?;
9971008

998-
let (res, sign) = x.ln_gamma();
1009+
// FIXME: Using host floats.
1010+
let (res, sign) = x.to_host().ln_gamma();
9991011
this.write_int(sign, &signp)?;
1000-
this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
1012+
let res = this.adjust_nan(res.to_soft(), &[x]);
1013+
this.write_scalar(res, dest)?;
10011014
}
10021015
"lgamma_r" => {
10031016
let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
1004-
// FIXME: Using host floats.
1005-
let x = f64::from_bits(this.read_scalar(x)?.to_u64()?);
1017+
let x = this.read_scalar(x)?.to_f64()?;
10061018
let signp = this.deref_pointer(signp)?;
10071019

1008-
let (res, sign) = x.ln_gamma();
1020+
// FIXME: Using host floats.
1021+
let (res, sign) = x.to_host().ln_gamma();
10091022
this.write_int(sign, &signp)?;
1010-
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
1023+
let res = this.adjust_nan(res.to_soft(), &[x]);
1024+
this.write_scalar(res, dest)?;
10111025
}
10121026

10131027
// LLVM intrinsics

0 commit comments

Comments
 (0)