Skip to content

Commit 9669acc

Browse files
committed
Merge remote-tracking branch 'origin/master' into the_outer_limits
2 parents 5381981 + f4afb59 commit 9669acc

File tree

4 files changed

+114
-3
lines changed

4 files changed

+114
-3
lines changed

src/interpreter/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
173173
// TODO(solson): Try making const_to_primval instead.
174174
fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> {
175175
use rustc::middle::const_val::ConstVal::*;
176-
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
176+
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat};
177177
macro_rules! i2p {
178178
($i:ident, $n:expr) => {{
179179
let ptr = self.memory.allocate($n)?;
@@ -182,7 +182,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
182182
}}
183183
}
184184
match *const_val {
185-
Float(_f) => unimplemented!(),
185+
Float(ConstFloat::F32(f)) => {
186+
let ptr = self.memory.allocate(4);
187+
self.memory.write_f32(ptr, f)?;
188+
Ok(ptr)
189+
},
190+
Float(ConstFloat::F64(f)) => {
191+
let ptr = self.memory.allocate(8);
192+
self.memory.write_f64(ptr, f)?;
193+
Ok(ptr)
194+
},
195+
Float(ConstFloat::FInfer{..}) => unreachable!(),
186196
Integral(ConstInt::Infer(_)) => unreachable!(),
187197
Integral(ConstInt::InferSigned(_)) => unreachable!(),
188198
Integral(ConstInt::I8(i)) => i2p!(i, 1),
@@ -838,7 +848,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
838848
}
839849

840850
pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
841-
use syntax::ast::{IntTy, UintTy};
851+
use syntax::ast::{IntTy, UintTy, FloatTy};
842852
let val = match (self.memory.pointer_size(), &ty.sty) {
843853
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
844854
(_, &ty::TyChar) => {
@@ -863,6 +873,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
863873
(8, &ty::TyUint(UintTy::Us)) |
864874
(_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64),
865875

876+
(_, &ty::TyFloat(FloatTy::F32)) => PrimVal::F32(self.memory.read_f32(ptr)?),
877+
(_, &ty::TyFloat(FloatTy::F64)) => PrimVal::F64(self.memory.read_f64(ptr)?),
878+
866879
(_, &ty::TyFnDef(def_id, substs, fn_ty)) => {
867880
PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty))
868881
},

src/memory.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
426426
PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8),
427427
PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4),
428428
PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
429+
PrimVal::F32(f) => self.write_f32(ptr, f),
430+
PrimVal::F64(f) => self.write_f64(ptr, f),
429431
PrimVal::FnPtr(_p) |
430432
PrimVal::AbstractPtr(_p) => unimplemented!(),
431433
}
@@ -483,6 +485,28 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
483485
let size = self.pointer_size();
484486
self.write_uint(ptr, n, size)
485487
}
488+
489+
pub fn write_f32(&mut self, ptr: Pointer, f: f32) -> EvalResult<'tcx, ()> {
490+
let endianess = self.endianess();
491+
let b = self.get_bytes_mut(ptr, 4)?;
492+
write_target_f32(endianess, b, f).unwrap();
493+
Ok(())
494+
}
495+
496+
pub fn write_f64(&mut self, ptr: Pointer, f: f64) -> EvalResult<'tcx, ()> {
497+
let endianess = self.endianess();
498+
let b = self.get_bytes_mut(ptr, 8)?;
499+
write_target_f64(endianess, b, f).unwrap();
500+
Ok(())
501+
}
502+
503+
pub fn read_f32(&self, ptr: Pointer) -> EvalResult<'tcx, f32> {
504+
self.get_bytes(ptr, 4).map(|b| read_target_f32(self.endianess(), b).unwrap())
505+
}
506+
507+
pub fn read_f64(&self, ptr: Pointer) -> EvalResult<'tcx, f64> {
508+
self.get_bytes(ptr, 8).map(|b| read_target_f64(self.endianess(), b).unwrap())
509+
}
486510
}
487511

488512
/// Relocations
@@ -605,6 +629,36 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i64,
605629
}
606630
}
607631

632+
////////////////////////////////////////////////////////////////////////////////
633+
// Methods to access floats in the target endianess
634+
////////////////////////////////////////////////////////////////////////////////
635+
636+
fn write_target_f32(endianess: layout::Endian, mut target: &mut [u8], data: f32) -> Result<(), byteorder::Error> {
637+
match endianess {
638+
layout::Endian::Little => target.write_f32::<LittleEndian>(data),
639+
layout::Endian::Big => target.write_f32::<BigEndian>(data),
640+
}
641+
}
642+
fn write_target_f64(endianess: layout::Endian, mut target: &mut [u8], data: f64) -> Result<(), byteorder::Error> {
643+
match endianess {
644+
layout::Endian::Little => target.write_f64::<LittleEndian>(data),
645+
layout::Endian::Big => target.write_f64::<BigEndian>(data),
646+
}
647+
}
648+
649+
fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result<f32, byteorder::Error> {
650+
match endianess {
651+
layout::Endian::Little => source.read_f32::<LittleEndian>(),
652+
layout::Endian::Big => source.read_f32::<BigEndian>(),
653+
}
654+
}
655+
fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result<f64, byteorder::Error> {
656+
match endianess {
657+
layout::Endian::Little => source.read_f64::<LittleEndian>(),
658+
layout::Endian::Big => source.read_f64::<BigEndian>(),
659+
}
660+
}
661+
608662
////////////////////////////////////////////////////////////////////////////////
609663
// Undefined byte tracking
610664
////////////////////////////////////////////////////////////////////////////////

src/primval.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub enum PrimVal {
1313
FnPtr(Pointer),
1414
IntegerPtr(u64),
1515
Char(char),
16+
17+
F32(f32), F64(f64),
1618
}
1719

1820
/// returns the result of the operation and whether the operation overflowed
@@ -57,6 +59,32 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
5759
})
5860
}
5961

62+
macro_rules! float_binops {
63+
($v:ident, $l:ident, $r:ident) => ({
64+
match bin_op {
65+
Add => $v($l + $r),
66+
Sub => $v($l - $r),
67+
Mul => $v($l * $r),
68+
Div => $v($l / $r),
69+
Rem => $v($l % $r),
70+
71+
// invalid float ops
72+
BitXor => unreachable!(),
73+
BitAnd => unreachable!(),
74+
BitOr => unreachable!(),
75+
Shl => unreachable!(),
76+
Shr => unreachable!(),
77+
78+
Eq => Bool($l == $r),
79+
Ne => Bool($l != $r),
80+
Lt => Bool($l < $r),
81+
Le => Bool($l <= $r),
82+
Gt => Bool($l > $r),
83+
Ge => Bool($l >= $r),
84+
}
85+
})
86+
}
87+
6088
fn unrelated_ptr_ops<'tcx>(bin_op: mir::BinOp) -> EvalResult<'tcx, PrimVal> {
6189
use rustc::mir::repr::BinOp::*;
6290
match bin_op {
@@ -128,6 +156,8 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
128156
(U16(l), U16(r)) => int_binops!(U16, l, r),
129157
(U32(l), U32(r)) => int_binops!(U32, l, r),
130158
(U64(l), U64(r)) => int_binops!(U64, l, r),
159+
(F32(l), F32(r)) => float_binops!(F32, l, r),
160+
(F64(l), F64(r)) => float_binops!(F64, l, r),
131161
(Char(l), Char(r)) => match bin_op {
132162
Eq => Bool(l == r),
133163
Ne => Bool(l != r),
@@ -211,6 +241,9 @@ pub fn unary_op<'tcx>(un_op: mir::UnOp, val: PrimVal) -> EvalResult<'tcx, PrimVa
211241
(Not, U16(n)) => Ok(U16(!n)),
212242
(Not, U32(n)) => Ok(U32(!n)),
213243
(Not, U64(n)) => Ok(U64(!n)),
244+
245+
(Neg, F64(n)) => Ok(F64(-n)),
246+
(Neg, F32(n)) => Ok(F32(-n)),
214247
_ => Err(EvalError::Unimplemented(format!("unimplemented unary op: {:?}, {:?}", un_op, val))),
215248
}
216249
}

tests/run-pass/floats.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
fn main() {
3+
assert_eq!(6.0_f32*6.0_f32, 36.0_f32);
4+
assert_eq!(6.0_f64*6.0_f64, 36.0_f64);
5+
assert_eq!(-{5.0_f32}, -5.0_f32);
6+
assert!((5.0_f32/0.0).is_infinite());
7+
assert!((-5.0_f32).sqrt().is_nan());
8+
let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
9+
let y: f64 = unsafe { std::mem::transmute(x) };
10+
assert_eq!(y, 42.0_f64);
11+
}

0 commit comments

Comments
 (0)