Scalar: only convert to/from soft-float types, not to/from hard-floats
This commit is contained in:
parent
5c45343f11
commit
3836573ae4
4 changed files with 41 additions and 51 deletions
|
|
@ -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<Tag> {
|
|||
}
|
||||
|
||||
#[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<Tag> {
|
|||
}
|
||||
|
||||
#[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<Tag> {
|
|||
}
|
||||
|
||||
#[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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,8 +69,7 @@ fn parse_float<'tcx>(
|
|||
) -> Result<ConstValue<'tcx>, ()> {
|
||||
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::<f32>().map_err(|_| ())?;
|
||||
let mut f = num.parse::<Single>().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::<f64>().map_err(|_| ())?;
|
||||
let mut f = num.parse::<Double>().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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue