mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-10 00:47:45 +00:00
implement floats by running the ops on the host architecture
This commit is contained in:
parent
a7cc77a010
commit
4b831569f6
@ -169,7 +169,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||||||
// TODO(solson): Try making const_to_primval instead.
|
// TODO(solson): Try making const_to_primval instead.
|
||||||
fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> {
|
fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> {
|
||||||
use rustc::middle::const_val::ConstVal::*;
|
use rustc::middle::const_val::ConstVal::*;
|
||||||
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
|
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat};
|
||||||
|
use std::mem::transmute;
|
||||||
macro_rules! i2p {
|
macro_rules! i2p {
|
||||||
($i:ident, $n:expr) => {{
|
($i:ident, $n:expr) => {{
|
||||||
let ptr = self.memory.allocate($n);
|
let ptr = self.memory.allocate($n);
|
||||||
@ -178,7 +179,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
match *const_val {
|
match *const_val {
|
||||||
Float(_f) => unimplemented!(),
|
Float(ConstFloat::F32(f)) => {
|
||||||
|
let i = unsafe { transmute::<_, u32>(f) };
|
||||||
|
i2p!(i, 4)
|
||||||
|
},
|
||||||
|
Float(ConstFloat::F64(f)) => {
|
||||||
|
let i = unsafe { transmute::<_, u64>(f) };
|
||||||
|
i2p!(i, 8)
|
||||||
|
},
|
||||||
|
Float(ConstFloat::FInfer{..}) => unreachable!(),
|
||||||
Integral(ConstInt::Infer(_)) => unreachable!(),
|
Integral(ConstInt::Infer(_)) => unreachable!(),
|
||||||
Integral(ConstInt::InferSigned(_)) => unreachable!(),
|
Integral(ConstInt::InferSigned(_)) => unreachable!(),
|
||||||
Integral(ConstInt::I8(i)) => i2p!(i, 1),
|
Integral(ConstInt::I8(i)) => i2p!(i, 1),
|
||||||
@ -824,7 +833,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
|
pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
|
||||||
use syntax::ast::{IntTy, UintTy};
|
use syntax::ast::{IntTy, UintTy, FloatTy};
|
||||||
|
use std::mem::transmute;
|
||||||
let val = match (self.memory.pointer_size(), &ty.sty) {
|
let val = match (self.memory.pointer_size(), &ty.sty) {
|
||||||
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
|
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
|
||||||
(_, &ty::TyChar) => {
|
(_, &ty::TyChar) => {
|
||||||
@ -848,6 +858,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||||||
(_, &ty::TyUint(UintTy::U32)) => PrimVal::U32(self.memory.read_uint(ptr, 4)? as u32),
|
(_, &ty::TyUint(UintTy::U32)) => PrimVal::U32(self.memory.read_uint(ptr, 4)? as u32),
|
||||||
(8, &ty::TyUint(UintTy::Us)) |
|
(8, &ty::TyUint(UintTy::Us)) |
|
||||||
(_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64),
|
(_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64),
|
||||||
|
(_, &ty::TyFloat(FloatTy::F32)) => {
|
||||||
|
let i = self.memory.read_uint(ptr, 4)? as u32;
|
||||||
|
PrimVal::F32(unsafe { transmute(i) })
|
||||||
|
},
|
||||||
|
(_, &ty::TyFloat(FloatTy::F64)) => {
|
||||||
|
let i = self.memory.read_uint(ptr, 8)?;
|
||||||
|
PrimVal::F64(unsafe { transmute(i) })
|
||||||
|
},
|
||||||
|
|
||||||
(_, &ty::TyFnDef(def_id, substs, fn_ty)) => {
|
(_, &ty::TyFnDef(def_id, substs, fn_ty)) => {
|
||||||
PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty))
|
PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty))
|
||||||
|
@ -394,6 +394,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> {
|
pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> {
|
||||||
|
use std::mem::transmute;
|
||||||
let pointer_size = self.pointer_size();
|
let pointer_size = self.pointer_size();
|
||||||
match val {
|
match val {
|
||||||
PrimVal::Bool(b) => self.write_bool(ptr, b),
|
PrimVal::Bool(b) => self.write_bool(ptr, b),
|
||||||
@ -407,6 +408,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
|||||||
PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8),
|
PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8),
|
||||||
PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4),
|
PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4),
|
||||||
PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
|
PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size),
|
||||||
|
PrimVal::F32(f) => self.write_uint(ptr, unsafe { transmute::<_, u32>(f) } as u64, 4),
|
||||||
|
PrimVal::F64(f) => self.write_uint(ptr, unsafe { transmute::<_, u64>(f) }, 8),
|
||||||
PrimVal::FnPtr(_p) |
|
PrimVal::FnPtr(_p) |
|
||||||
PrimVal::AbstractPtr(_p) => unimplemented!(),
|
PrimVal::AbstractPtr(_p) => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ pub enum PrimVal {
|
|||||||
FnPtr(Pointer),
|
FnPtr(Pointer),
|
||||||
IntegerPtr(u64),
|
IntegerPtr(u64),
|
||||||
Char(char),
|
Char(char),
|
||||||
|
|
||||||
|
F32(f32), F64(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the result of the operation and whether the operation overflowed
|
/// returns the result of the operation and whether the operation overflowed
|
||||||
@ -57,6 +59,34 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! float_binops {
|
||||||
|
($v:ident, $l:ident, $r:ident) => ({
|
||||||
|
match bin_op {
|
||||||
|
Add => $v($l + $r),
|
||||||
|
Sub => $v($l - $r),
|
||||||
|
Mul => $v($l * $r),
|
||||||
|
Div => $v($l / $r),
|
||||||
|
Rem => $v($l % $r),
|
||||||
|
|
||||||
|
// invalid float ops
|
||||||
|
BitXor => unreachable!(),
|
||||||
|
BitAnd => unreachable!(),
|
||||||
|
BitOr => unreachable!(),
|
||||||
|
Shl => unreachable!(),
|
||||||
|
Shr => unreachable!(),
|
||||||
|
|
||||||
|
// directly comparing floats is questionable
|
||||||
|
// miri could forbid it, or at least miri as rust const eval should forbid it
|
||||||
|
Eq => Bool($l == $r),
|
||||||
|
Ne => Bool($l != $r),
|
||||||
|
Lt => Bool($l < $r),
|
||||||
|
Le => Bool($l <= $r),
|
||||||
|
Gt => Bool($l > $r),
|
||||||
|
Ge => Bool($l >= $r),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn unrelated_ptr_ops<'tcx>(bin_op: mir::BinOp) -> EvalResult<'tcx, PrimVal> {
|
fn unrelated_ptr_ops<'tcx>(bin_op: mir::BinOp) -> EvalResult<'tcx, PrimVal> {
|
||||||
use rustc::mir::repr::BinOp::*;
|
use rustc::mir::repr::BinOp::*;
|
||||||
match bin_op {
|
match bin_op {
|
||||||
@ -128,6 +158,8 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
|
|||||||
(U16(l), U16(r)) => int_binops!(U16, l, r),
|
(U16(l), U16(r)) => int_binops!(U16, l, r),
|
||||||
(U32(l), U32(r)) => int_binops!(U32, l, r),
|
(U32(l), U32(r)) => int_binops!(U32, l, r),
|
||||||
(U64(l), U64(r)) => int_binops!(U64, l, r),
|
(U64(l), U64(r)) => int_binops!(U64, l, r),
|
||||||
|
(F32(l), F32(r)) => float_binops!(F32, l, r),
|
||||||
|
(F64(l), F64(r)) => float_binops!(F64, l, r),
|
||||||
(Char(l), Char(r)) => match bin_op {
|
(Char(l), Char(r)) => match bin_op {
|
||||||
Eq => Bool(l == r),
|
Eq => Bool(l == r),
|
||||||
Ne => Bool(l != r),
|
Ne => Bool(l != r),
|
||||||
@ -211,6 +243,9 @@ pub fn unary_op<'tcx>(un_op: mir::UnOp, val: PrimVal) -> EvalResult<'tcx, PrimVa
|
|||||||
(Not, U16(n)) => Ok(U16(!n)),
|
(Not, U16(n)) => Ok(U16(!n)),
|
||||||
(Not, U32(n)) => Ok(U32(!n)),
|
(Not, U32(n)) => Ok(U32(!n)),
|
||||||
(Not, U64(n)) => Ok(U64(!n)),
|
(Not, U64(n)) => Ok(U64(!n)),
|
||||||
|
|
||||||
|
(Neg, F64(n)) => Ok(F64(-n)),
|
||||||
|
(Neg, F32(n)) => Ok(F32(-n)),
|
||||||
_ => Err(EvalError::Unimplemented(format!("unimplemented unary op: {:?}, {:?}", un_op, val))),
|
_ => Err(EvalError::Unimplemented(format!("unimplemented unary op: {:?}, {:?}", un_op, val))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
tests/run-pass/floats.rs
Normal file
8
tests/run-pass/floats.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(6.0_f32*6.0_f32, 36.0_f32);
|
||||||
|
assert_eq!(6.0_f64*6.0_f64, 36.0_f64);
|
||||||
|
assert_eq!(-{5.0_f32}, -5.0_f32);
|
||||||
|
assert!((5.0_f32/0.0).is_infinite());
|
||||||
|
assert!((-5.0_f32).sqrt().is_nan());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user