diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 454a4e2111a9..1909f3cb998b 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -1,5 +1,6 @@ use std::fmt; use rustc_macros::HashStable; +use rustc_apfloat::{Float, ieee::{Double, Single}}; use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef}; use crate::ty::PlaceholderConst; @@ -292,12 +293,12 @@ impl<'tcx, Tag> Scalar { } #[inline] - pub fn from_f32(f: f32) -> Self { + pub fn from_f32(f: Single) -> Self { Scalar::Raw { data: f.to_bits() as u128, size: 4 } } #[inline] - pub fn from_f64(f: f64) -> Self { + pub fn from_f64(f: Double) -> Self { Scalar::Raw { data: f.to_bits() as u128, size: 8 } } @@ -427,13 +428,15 @@ impl<'tcx, Tag> Scalar { } #[inline] - pub fn to_f32(self) -> InterpResult<'static, f32> { - Ok(f32::from_bits(self.to_u32()?)) + pub fn to_f32(self) -> InterpResult<'static, Single> { + // Going through `u32` to check size and truncation. + Ok(Single::from_bits(self.to_u32()? as u128)) } #[inline] - pub fn to_f64(self) -> InterpResult<'static, f64> { - Ok(f64::from_bits(self.to_u64()?)) + pub fn to_f64(self) -> InterpResult<'static, Double> { + // Going through `u64` to check size and truncation. + Ok(Double::from_bits(self.to_u64()? as u128)) } } @@ -517,12 +520,12 @@ impl<'tcx, Tag> ScalarMaybeUndef { } #[inline(always)] - pub fn to_f32(self) -> InterpResult<'tcx, f32> { + pub fn to_f32(self) -> InterpResult<'tcx, Single> { self.not_undef()?.to_f32() } #[inline(always)] - pub fn to_f64(self) -> InterpResult<'tcx, f64> { + pub fn to_f64(self) -> InterpResult<'tcx, Double> { self.not_undef()?.to_f64() } diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index b5604f4cb0f8..37a2e79dae91 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -69,8 +69,7 @@ fn parse_float<'tcx>( ) -> Result, ()> { let num = num.as_str(); use rustc_apfloat::ieee::{Single, Double}; - use rustc_apfloat::Float; - let (data, size) = match fty { + let scalar = match fty { ast::FloatTy::F32 => { num.parse::().map_err(|_| ())?; let mut f = num.parse::().unwrap_or_else(|e| { @@ -79,19 +78,19 @@ fn parse_float<'tcx>( if neg { f = -f; } - (f.to_bits(), 4) + Scalar::from_f32(f) } ast::FloatTy::F64 => { num.parse::().map_err(|_| ())?; let mut f = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) }); if neg { f = -f; } - (f.to_bits(), 8) + Scalar::from_f64(f) } }; - Ok(ConstValue::Scalar(Scalar::from_uint(data, Size::from_bytes(size)))) + Ok(ConstValue::Scalar(scalar)) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 5bc8b931ae86..4395f0c947b1 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -166,21 +166,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> Ok(Scalar::from_uint(v, dest_layout.size)) } - Float(FloatTy::F32) if signed => Ok(Scalar::from_uint( - Single::from_i128(v as i128).value.to_bits(), - Size::from_bits(32) + Float(FloatTy::F32) if signed => Ok(Scalar::from_f32( + Single::from_i128(v as i128).value )), - Float(FloatTy::F64) if signed => Ok(Scalar::from_uint( - Double::from_i128(v as i128).value.to_bits(), - Size::from_bits(64) + Float(FloatTy::F64) if signed => Ok(Scalar::from_f64( + Double::from_i128(v as i128).value )), - Float(FloatTy::F32) => Ok(Scalar::from_uint( - Single::from_u128(v).value.to_bits(), - Size::from_bits(32) + Float(FloatTy::F32) => Ok(Scalar::from_f32( + Single::from_u128(v).value )), - Float(FloatTy::F64) => Ok(Scalar::from_uint( - Double::from_u128(v).value.to_bits(), - Size::from_bits(64) + Float(FloatTy::F64) => Ok(Scalar::from_f64( + Double::from_u128(v).value )), Char => { @@ -223,22 +219,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> Ok(Scalar::from_int(v, Size::from_bits(width as u64))) }, // f64 -> f32 - Float(FloatTy::F32) if fty == FloatTy::F64 => { - Ok(Scalar::from_uint( - Single::to_bits(Double::from_bits(bits).convert(&mut false).value), - Size::from_bits(32), - )) - }, + Float(FloatTy::F32) if fty == FloatTy::F64 => + Ok(Scalar::from_f32(Double::from_bits(bits).convert(&mut false).value)), // f32 -> f64 - Float(FloatTy::F64) if fty == FloatTy::F32 => { - Ok(Scalar::from_uint( - Double::to_bits(Single::from_bits(bits).convert(&mut false).value), - Size::from_bits(64), - )) - }, + Float(FloatTy::F64) if fty == FloatTy::F32 => + Ok(Scalar::from_f64(Single::from_bits(bits).convert(&mut false).value)), // identity cast - Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))), - Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))), + Float(FloatTy::F64) if fty == FloatTy::F64 => + Ok(Scalar::from_uint(bits, Size::from_bits(64))), + Float(FloatTy::F32) if fty == FloatTy::F32 => + Ok(Scalar::from_uint(bits, Size::from_bits(32))), _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))), } } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 4f13eeb6fa45..fa4597c825ac 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,5 +1,5 @@ use rustc::mir; -use rustc::ty::{self, layout::{Size, TyLayout}}; +use rustc::ty::{self, layout::TyLayout}; use syntax::ast::FloatTy; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; @@ -92,11 +92,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> use rustc::mir::BinOp::*; macro_rules! float_math { - ($ty:path, $size:expr) => {{ + ($ty:path, $from_float:ident) => {{ let l = <$ty>::from_bits(l); let r = <$ty>::from_bits(r); - let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| - Scalar::from_uint(res.value.to_bits(), Size::from_bytes($size)); let val = match bin_op { Eq => Scalar::from_bool(l == r), Ne => Scalar::from_bool(l != r), @@ -104,19 +102,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> Le => Scalar::from_bool(l <= r), Gt => Scalar::from_bool(l > r), Ge => Scalar::from_bool(l >= r), - Add => bitify(l + r), - Sub => bitify(l - r), - Mul => bitify(l * r), - Div => bitify(l / r), - Rem => bitify(l % r), + Add => Scalar::$from_float((l + r).value), + Sub => Scalar::$from_float((l - r).value), + Mul => Scalar::$from_float((l * r).value), + Div => Scalar::$from_float((l / r).value), + Rem => Scalar::$from_float((l % r).value), _ => bug!("invalid float op: `{:?}`", bin_op), }; return Ok((val, false)); }}; } match fty { - FloatTy::F32 => float_math!(Single, 4), - FloatTy::F64 => float_math!(Double, 8), + FloatTy::F32 => float_math!(Single, from_f32), + FloatTy::F64 => float_math!(Double, from_f64), } }