Skip to content

Commit 3836573

Browse files
committed
Scalar: only convert to/from soft-float types, not to/from hard-floats
1 parent 5c45343 commit 3836573

File tree

4 files changed

+41
-51
lines changed

4 files changed

+41
-51
lines changed

src/librustc/mir/interpret/value.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fmt;
22
use rustc_macros::HashStable;
3+
use rustc_apfloat::{Float, ieee::{Double, Single}};
34

45
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
56
use crate::ty::PlaceholderConst;
@@ -292,12 +293,12 @@ impl<'tcx, Tag> Scalar<Tag> {
292293
}
293294

294295
#[inline]
295-
pub fn from_f32(f: f32) -> Self {
296+
pub fn from_f32(f: Single) -> Self {
296297
Scalar::Raw { data: f.to_bits() as u128, size: 4 }
297298
}
298299

299300
#[inline]
300-
pub fn from_f64(f: f64) -> Self {
301+
pub fn from_f64(f: Double) -> Self {
301302
Scalar::Raw { data: f.to_bits() as u128, size: 8 }
302303
}
303304

@@ -427,13 +428,15 @@ impl<'tcx, Tag> Scalar<Tag> {
427428
}
428429

429430
#[inline]
430-
pub fn to_f32(self) -> InterpResult<'static, f32> {
431-
Ok(f32::from_bits(self.to_u32()?))
431+
pub fn to_f32(self) -> InterpResult<'static, Single> {
432+
// Going through `u32` to check size and truncation.
433+
Ok(Single::from_bits(self.to_u32()? as u128))
432434
}
433435

434436
#[inline]
435-
pub fn to_f64(self) -> InterpResult<'static, f64> {
436-
Ok(f64::from_bits(self.to_u64()?))
437+
pub fn to_f64(self) -> InterpResult<'static, Double> {
438+
// Going through `u64` to check size and truncation.
439+
Ok(Double::from_bits(self.to_u64()? as u128))
437440
}
438441
}
439442

@@ -517,12 +520,12 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
517520
}
518521

519522
#[inline(always)]
520-
pub fn to_f32(self) -> InterpResult<'tcx, f32> {
523+
pub fn to_f32(self) -> InterpResult<'tcx, Single> {
521524
self.not_undef()?.to_f32()
522525
}
523526

524527
#[inline(always)]
525-
pub fn to_f64(self) -> InterpResult<'tcx, f64> {
528+
pub fn to_f64(self) -> InterpResult<'tcx, Double> {
526529
self.not_undef()?.to_f64()
527530
}
528531

src/librustc_mir/hair/constant.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ fn parse_float<'tcx>(
6969
) -> Result<ConstValue<'tcx>, ()> {
7070
let num = num.as_str();
7171
use rustc_apfloat::ieee::{Single, Double};
72-
use rustc_apfloat::Float;
73-
let (data, size) = match fty {
72+
let scalar = match fty {
7473
ast::FloatTy::F32 => {
7574
num.parse::<f32>().map_err(|_| ())?;
7675
let mut f = num.parse::<Single>().unwrap_or_else(|e| {
@@ -79,19 +78,19 @@ fn parse_float<'tcx>(
7978
if neg {
8079
f = -f;
8180
}
82-
(f.to_bits(), 4)
81+
Scalar::from_f32(f)
8382
}
8483
ast::FloatTy::F64 => {
8584
num.parse::<f64>().map_err(|_| ())?;
8685
let mut f = num.parse::<Double>().unwrap_or_else(|e| {
87-
panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
86+
panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
8887
});
8988
if neg {
9089
f = -f;
9190
}
92-
(f.to_bits(), 8)
91+
Scalar::from_f64(f)
9392
}
9493
};
9594

96-
Ok(ConstValue::Scalar(Scalar::from_uint(data, Size::from_bytes(size))))
95+
Ok(ConstValue::Scalar(scalar))
9796
}

src/librustc_mir/interpret/cast.rs

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
166166
Ok(Scalar::from_uint(v, dest_layout.size))
167167
}
168168

169-
Float(FloatTy::F32) if signed => Ok(Scalar::from_uint(
170-
Single::from_i128(v as i128).value.to_bits(),
171-
Size::from_bits(32)
169+
Float(FloatTy::F32) if signed => Ok(Scalar::from_f32(
170+
Single::from_i128(v as i128).value
172171
)),
173-
Float(FloatTy::F64) if signed => Ok(Scalar::from_uint(
174-
Double::from_i128(v as i128).value.to_bits(),
175-
Size::from_bits(64)
172+
Float(FloatTy::F64) if signed => Ok(Scalar::from_f64(
173+
Double::from_i128(v as i128).value
176174
)),
177-
Float(FloatTy::F32) => Ok(Scalar::from_uint(
178-
Single::from_u128(v).value.to_bits(),
179-
Size::from_bits(32)
175+
Float(FloatTy::F32) => Ok(Scalar::from_f32(
176+
Single::from_u128(v).value
180177
)),
181-
Float(FloatTy::F64) => Ok(Scalar::from_uint(
182-
Double::from_u128(v).value.to_bits(),
183-
Size::from_bits(64)
178+
Float(FloatTy::F64) => Ok(Scalar::from_f64(
179+
Double::from_u128(v).value
184180
)),
185181

186182
Char => {
@@ -223,22 +219,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
223219
Ok(Scalar::from_int(v, Size::from_bits(width as u64)))
224220
},
225221
// f64 -> f32
226-
Float(FloatTy::F32) if fty == FloatTy::F64 => {
227-
Ok(Scalar::from_uint(
228-
Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
229-
Size::from_bits(32),
230-
))
231-
},
222+
Float(FloatTy::F32) if fty == FloatTy::F64 =>
223+
Ok(Scalar::from_f32(Double::from_bits(bits).convert(&mut false).value)),
232224
// f32 -> f64
233-
Float(FloatTy::F64) if fty == FloatTy::F32 => {
234-
Ok(Scalar::from_uint(
235-
Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
236-
Size::from_bits(64),
237-
))
238-
},
225+
Float(FloatTy::F64) if fty == FloatTy::F32 =>
226+
Ok(Scalar::from_f64(Single::from_bits(bits).convert(&mut false).value)),
239227
// identity cast
240-
Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))),
241-
Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))),
228+
Float(FloatTy::F64) if fty == FloatTy::F64 =>
229+
Ok(Scalar::from_uint(bits, Size::from_bits(64))),
230+
Float(FloatTy::F32) if fty == FloatTy::F32 =>
231+
Ok(Scalar::from_uint(bits, Size::from_bits(32))),
242232
_ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
243233
}
244234
}

src/librustc_mir/interpret/operator.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc::mir;
2-
use rustc::ty::{self, layout::{Size, TyLayout}};
2+
use rustc::ty::{self, layout::TyLayout};
33
use syntax::ast::FloatTy;
44
use rustc_apfloat::ieee::{Double, Single};
55
use rustc_apfloat::Float;
@@ -92,31 +92,29 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
9292
use rustc::mir::BinOp::*;
9393

9494
macro_rules! float_math {
95-
($ty:path, $size:expr) => {{
95+
($ty:path, $from_float:ident) => {{
9696
let l = <$ty>::from_bits(l);
9797
let r = <$ty>::from_bits(r);
98-
let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>|
99-
Scalar::from_uint(res.value.to_bits(), Size::from_bytes($size));
10098
let val = match bin_op {
10199
Eq => Scalar::from_bool(l == r),
102100
Ne => Scalar::from_bool(l != r),
103101
Lt => Scalar::from_bool(l < r),
104102
Le => Scalar::from_bool(l <= r),
105103
Gt => Scalar::from_bool(l > r),
106104
Ge => Scalar::from_bool(l >= r),
107-
Add => bitify(l + r),
108-
Sub => bitify(l - r),
109-
Mul => bitify(l * r),
110-
Div => bitify(l / r),
111-
Rem => bitify(l % r),
105+
Add => Scalar::$from_float((l + r).value),
106+
Sub => Scalar::$from_float((l - r).value),
107+
Mul => Scalar::$from_float((l * r).value),
108+
Div => Scalar::$from_float((l / r).value),
109+
Rem => Scalar::$from_float((l % r).value),
112110
_ => bug!("invalid float op: `{:?}`", bin_op),
113111
};
114112
return Ok((val, false));
115113
}};
116114
}
117115
match fty {
118-
FloatTy::F32 => float_math!(Single, 4),
119-
FloatTy::F64 => float_math!(Double, 8),
116+
FloatTy::F32 => float_math!(Single, from_f32),
117+
FloatTy::F64 => float_math!(Double, from_f64),
120118
}
121119
}
122120

0 commit comments

Comments
 (0)