Skip to content

Commit 51ce4a2

Browse files
committed
use byteorder's write_f{32,64} instead of transmuting
1 parent 4b83156 commit 51ce4a2

File tree

3 files changed

+66
-17
lines changed

3 files changed

+66
-17
lines changed

src/interpreter/mod.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
170170
fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> {
171171
use rustc::middle::const_val::ConstVal::*;
172172
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat};
173-
use std::mem::transmute;
174173
macro_rules! i2p {
175174
($i:ident, $n:expr) => {{
176175
let ptr = self.memory.allocate($n);
@@ -180,12 +179,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
180179
}
181180
match *const_val {
182181
Float(ConstFloat::F32(f)) => {
183-
let i = unsafe { transmute::<_, u32>(f) };
184-
i2p!(i, 4)
182+
let ptr = self.memory.allocate(4);
183+
self.memory.write_f32(ptr, f)?;
184+
Ok(ptr)
185185
},
186186
Float(ConstFloat::F64(f)) => {
187-
let i = unsafe { transmute::<_, u64>(f) };
188-
i2p!(i, 8)
187+
let ptr = self.memory.allocate(8);
188+
self.memory.write_f64(ptr, f)?;
189+
Ok(ptr)
189190
},
190191
Float(ConstFloat::FInfer{..}) => unreachable!(),
191192
Integral(ConstInt::Infer(_)) => unreachable!(),
@@ -834,7 +835,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
834835

835836
pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
836837
use syntax::ast::{IntTy, UintTy, FloatTy};
837-
use std::mem::transmute;
838838
let val = match (self.memory.pointer_size(), &ty.sty) {
839839
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
840840
(_, &ty::TyChar) => {
@@ -858,14 +858,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
858858
(_, &ty::TyUint(UintTy::U32)) => PrimVal::U32(self.memory.read_uint(ptr, 4)? as u32),
859859
(8, &ty::TyUint(UintTy::Us)) |
860860
(_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64),
861-
(_, &ty::TyFloat(FloatTy::F32)) => {
862-
let i = self.memory.read_uint(ptr, 4)? as u32;
863-
PrimVal::F32(unsafe { transmute(i) })
864-
},
865-
(_, &ty::TyFloat(FloatTy::F64)) => {
866-
let i = self.memory.read_uint(ptr, 8)?;
867-
PrimVal::F64(unsafe { transmute(i) })
868-
},
861+
862+
(_, &ty::TyFloat(FloatTy::F32)) => PrimVal::F32(self.memory.read_f32(ptr)?),
863+
(_, &ty::TyFloat(FloatTy::F64)) => PrimVal::F64(self.memory.read_f64(ptr)?),
869864

870865
(_, &ty::TyFnDef(def_id, substs, fn_ty)) => {
871866
PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty))

src/memory.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,6 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
394394
}
395395

396396
pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> {
397-
use std::mem::transmute;
398397
let pointer_size = self.pointer_size();
399398
match val {
400399
PrimVal::Bool(b) => self.write_bool(ptr, b),
@@ -408,8 +407,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
408407
PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8),
409408
PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4),
410409
PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
411-
PrimVal::F32(f) => self.write_uint(ptr, unsafe { transmute::<_, u32>(f) } as u64, 4),
412-
PrimVal::F64(f) => self.write_uint(ptr, unsafe { transmute::<_, u64>(f) }, 8),
410+
PrimVal::F32(f) => self.write_f32(ptr, f),
411+
PrimVal::F64(f) => self.write_f64(ptr, f),
413412
PrimVal::FnPtr(_p) |
414413
PrimVal::AbstractPtr(_p) => unimplemented!(),
415414
}
@@ -467,6 +466,28 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
467466
let size = self.pointer_size();
468467
self.write_uint(ptr, n, size)
469468
}
469+
470+
pub fn write_f32(&mut self, ptr: Pointer, f: f32) -> EvalResult<'tcx, ()> {
471+
let endianess = self.endianess();
472+
let b = self.get_bytes_mut(ptr, 4)?;
473+
write_target_f32(endianess, b, f).unwrap();
474+
Ok(())
475+
}
476+
477+
pub fn write_f64(&mut self, ptr: Pointer, f: f64) -> EvalResult<'tcx, ()> {
478+
let endianess = self.endianess();
479+
let b = self.get_bytes_mut(ptr, 8)?;
480+
write_target_f64(endianess, b, f).unwrap();
481+
Ok(())
482+
}
483+
484+
pub fn read_f32(&self, ptr: Pointer) -> EvalResult<'tcx, f32> {
485+
self.get_bytes(ptr, 4).map(|b| read_target_f32(self.endianess(), b).unwrap())
486+
}
487+
488+
pub fn read_f64(&self, ptr: Pointer) -> EvalResult<'tcx, f64> {
489+
self.get_bytes(ptr, 8).map(|b| read_target_f64(self.endianess(), b).unwrap())
490+
}
470491
}
471492

472493
/// Relocations
@@ -589,6 +610,36 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i64,
589610
}
590611
}
591612

613+
////////////////////////////////////////////////////////////////////////////////
614+
// Methods to access floats in the target endianess
615+
////////////////////////////////////////////////////////////////////////////////
616+
617+
fn write_target_f32(endianess: layout::Endian, mut target: &mut [u8], data: f32) -> Result<(), byteorder::Error> {
618+
match endianess {
619+
layout::Endian::Little => target.write_f32::<LittleEndian>(data),
620+
layout::Endian::Big => target.write_f32::<BigEndian>(data),
621+
}
622+
}
623+
fn write_target_f64(endianess: layout::Endian, mut target: &mut [u8], data: f64) -> Result<(), byteorder::Error> {
624+
match endianess {
625+
layout::Endian::Little => target.write_f64::<LittleEndian>(data),
626+
layout::Endian::Big => target.write_f64::<BigEndian>(data),
627+
}
628+
}
629+
630+
fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result<f32, byteorder::Error> {
631+
match endianess {
632+
layout::Endian::Little => source.read_f32::<LittleEndian>(),
633+
layout::Endian::Big => source.read_f32::<BigEndian>(),
634+
}
635+
}
636+
fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result<f64, byteorder::Error> {
637+
match endianess {
638+
layout::Endian::Little => source.read_f64::<LittleEndian>(),
639+
layout::Endian::Big => source.read_f64::<BigEndian>(),
640+
}
641+
}
642+
592643
////////////////////////////////////////////////////////////////////////////////
593644
// Undefined byte tracking
594645
////////////////////////////////////////////////////////////////////////////////

tests/run-pass/floats.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@ fn main() {
55
assert_eq!(-{5.0_f32}, -5.0_f32);
66
assert!((5.0_f32/0.0).is_infinite());
77
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);
811
}

0 commit comments

Comments
 (0)