Skip to content
Permalink
Browse files

Scalar: only convert to/from soft-float types, not to/from hard-floats

  • Loading branch information...
RalfJung committed Jun 8, 2019
1 parent 5c45343 commit 3836573ae4610f75d41d467e35d855efd6b000b5
@@ -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,31 +92,29 @@ 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),
Lt => Scalar::from_bool(l < r),
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),
}
}

0 comments on commit 3836573

Please sign in to comment.
You can’t perform that action at this time.