diff options
Diffstat (limited to 'src/tools/miri/src/intrinsics/math.rs')
| -rw-r--r-- | src/tools/miri/src/intrinsics/math.rs | 52 |
1 files changed, 19 insertions, 33 deletions
diff --git a/src/tools/miri/src/intrinsics/math.rs b/src/tools/miri/src/intrinsics/math.rs index ca81454a98c..b9c99f28594 100644 --- a/src/tools/miri/src/intrinsics/math.rs +++ b/src/tools/miri/src/intrinsics/math.rs @@ -1,5 +1,5 @@ use rand::Rng; -use rustc_apfloat::{self, Float, Round}; +use rustc_apfloat::{self, Float, FloatConvert, Round}; use rustc_middle::mir; use rustc_middle::ty::{self, FloatTy}; @@ -7,6 +7,20 @@ use self::helpers::{ToHost, ToSoft}; use super::check_intrinsic_arg_count; use crate::*; +fn sqrt<'tcx, F: Float + FloatConvert<F> + Into<Scalar>>( + this: &mut MiriInterpCx<'tcx>, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, +) -> InterpResult<'tcx> { + let [f] = check_intrinsic_arg_count(args)?; + let f = this.read_scalar(f)?; + let f: F = f.to_float()?; + // Sqrt is specified to be fully precise. + let res = math::sqrt(f); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest) +} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_math_intrinsic( @@ -20,38 +34,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match intrinsic_name { // Operations we can do with soft-floats. - "sqrtf16" => { - let [f] = check_intrinsic_arg_count(args)?; - let f = this.read_scalar(f)?.to_f16()?; - // Sqrt is specified to be fully precise. - let res = math::sqrt(f); - let res = this.adjust_nan(res, &[f]); - this.write_scalar(res, dest)?; - } - "sqrtf32" => { - let [f] = check_intrinsic_arg_count(args)?; - let f = this.read_scalar(f)?.to_f32()?; - // Sqrt is specified to be fully precise. - let res = math::sqrt(f); - let res = this.adjust_nan(res, &[f]); - this.write_scalar(res, dest)?; - } - "sqrtf64" => { - let [f] = check_intrinsic_arg_count(args)?; - let f = this.read_scalar(f)?.to_f64()?; - // Sqrt is specified to be fully precise. - let res = math::sqrt(f); - let res = this.adjust_nan(res, &[f]); - this.write_scalar(res, dest)?; - } - "sqrtf128" => { - let [f] = check_intrinsic_arg_count(args)?; - let f = this.read_scalar(f)?.to_f128()?; - // Sqrt is specified to be fully precise. - let res = math::sqrt(f); - let res = this.adjust_nan(res, &[f]); - this.write_scalar(res, dest)?; - } + "sqrtf16" => sqrt::<rustc_apfloat::ieee::Half>(this, args, dest)?, + "sqrtf32" => sqrt::<rustc_apfloat::ieee::Single>(this, args, dest)?, + "sqrtf64" => sqrt::<rustc_apfloat::ieee::Double>(this, args, dest)?, + "sqrtf128" => sqrt::<rustc_apfloat::ieee::Quad>(this, args, dest)?, "fmaf32" => { let [a, b, c] = check_intrinsic_arg_count(args)?; |
