X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_mir%2Finterpret%2Foperator.rs;h=db7da9359de7b7762bfc153120bdce4bd56dc699;hb=2ad303eb07e51ce0c4f9dd6a253ab4e938ab65f0;hp=488f81d8f740ec776ff4897ffd1620a0fe0f7299;hpb=426ab8e018f2ce2559c1898cb53853b1b00c7cc9;p=rust.git diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 488f81d8f74..db7da9359de 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,9 +1,8 @@ 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; -use rustc::mir::interpret::{EvalResult, Scalar}; +use rustc::mir::interpret::{InterpResult, Scalar}; use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy}; @@ -17,7 +16,7 @@ pub fn binop_with_overflow( left: ImmTy<'tcx, M::PointerTag>, right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx> { + ) -> InterpResult<'tcx> { let (val, overflowed) = self.binary_op(op, left, right)?; let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); self.write_immediate(val, dest) @@ -31,7 +30,7 @@ pub fn binop_ignore_overflow( left: ImmTy<'tcx, M::PointerTag>, right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx> { + ) -> InterpResult<'tcx> { let (val, _overflowed) = self.binary_op(op, left, right)?; self.write_scalar(val, dest) } @@ -43,7 +42,7 @@ fn binary_char_op( bin_op: mir::BinOp, l: char, r: char, - ) -> EvalResult<'tcx, (Scalar, bool)> { + ) -> (Scalar, bool) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -55,7 +54,7 @@ fn binary_char_op( Ge => l >= r, _ => bug!("Invalid operation on char: {:?}", bin_op), }; - return Ok((Scalar::from_bool(res), false)); + return (Scalar::from_bool(res), false); } fn binary_bool_op( @@ -63,7 +62,7 @@ fn binary_bool_op( bin_op: mir::BinOp, l: bool, r: bool, - ) -> EvalResult<'tcx, (Scalar, bool)> { + ) -> (Scalar, bool) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -78,46 +77,32 @@ fn binary_bool_op( BitXor => l ^ r, _ => bug!("Invalid operation on bool: {:?}", bin_op), }; - return Ok((Scalar::from_bool(res), false)); + return (Scalar::from_bool(res), false); } - fn binary_float_op( + fn binary_float_op>>( &self, bin_op: mir::BinOp, - fty: FloatTy, - // passing in raw bits - l: u128, - r: u128, - ) -> EvalResult<'tcx, (Scalar, bool)> { + l: F, + r: F, + ) -> (Scalar, bool) { use rustc::mir::BinOp::*; - macro_rules! float_math { - ($ty:path, $size:expr) => {{ - 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), - _ => bug!("invalid float op: `{:?}`", bin_op), - }; - return Ok((val, false)); - }}; - } - match fty { - FloatTy::F32 => float_math!(Single, 4), - FloatTy::F64 => float_math!(Double, 8), - } + 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 => (l + r).value.into(), + Sub => (l - r).value.into(), + Mul => (l * r).value.into(), + Div => (l / r).value.into(), + Rem => (l % r).value.into(), + _ => bug!("invalid float op: `{:?}`", bin_op), + }; + return (val, false); } fn binary_int_op( @@ -128,7 +113,7 @@ fn binary_int_op( left_layout: TyLayout<'tcx>, r: u128, right_layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool)> { use rustc::mir::BinOp::*; // Shift ops can have an RHS with a different numeric type. @@ -279,35 +264,42 @@ pub fn binary_op( bin_op: mir::BinOp, left: ImmTy<'tcx, M::PointerTag>, right: ImmTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool)> { trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, *left, left.layout.ty, *right, right.layout.ty); match left.layout.ty.sty { ty::Char => { assert_eq!(left.layout.ty, right.layout.ty); - let left = left.to_scalar()?.to_char()?; - let right = right.to_scalar()?.to_char()?; - self.binary_char_op(bin_op, left, right) + let left = left.to_scalar()?; + let right = right.to_scalar()?; + Ok(self.binary_char_op(bin_op, left.to_char()?, right.to_char()?)) } ty::Bool => { assert_eq!(left.layout.ty, right.layout.ty); - let left = left.to_scalar()?.to_bool()?; - let right = right.to_scalar()?.to_bool()?; - self.binary_bool_op(bin_op, left, right) + let left = left.to_scalar()?; + let right = right.to_scalar()?; + Ok(self.binary_bool_op(bin_op, left.to_bool()?, right.to_bool()?)) } ty::Float(fty) => { assert_eq!(left.layout.ty, right.layout.ty); - let left = left.to_bits()?; - let right = right.to_bits()?; - self.binary_float_op(bin_op, fty, left, right) + let left = left.to_scalar()?; + let right = right.to_scalar()?; + Ok(match fty { + FloatTy::F32 => self.binary_float_op(bin_op, left.to_f32()?, right.to_f32()?), + FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?), + }) } _ => { // Must be integer(-like) types. Don't forget about == on fn pointers. - assert!(left.layout.ty.is_integral() || left.layout.ty.is_unsafe_ptr() || - left.layout.ty.is_fn()); - assert!(right.layout.ty.is_integral() || right.layout.ty.is_unsafe_ptr() || - right.layout.ty.is_fn()); + assert!( + left.layout.ty.is_integral() || + left.layout.ty.is_unsafe_ptr() || left.layout.ty.is_fn_ptr(), + "Unexpected LHS type {:?} for BinOp {:?}", left.layout.ty, bin_op); + assert!( + right.layout.ty.is_integral() || + right.layout.ty.is_unsafe_ptr() || right.layout.ty.is_fn_ptr(), + "Unexpected RHS type {:?} for BinOp {:?}", right.layout.ty, bin_op); // Handle operations that support pointer values if left.to_scalar_ptr()?.is_ptr() || @@ -329,7 +321,7 @@ pub fn unary_op( &self, un_op: mir::UnOp, val: ImmTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, Scalar> { use rustc::mir::UnOp::*; let layout = val.layout; @@ -346,13 +338,12 @@ pub fn unary_op( Ok(Scalar::from_bool(res)) } ty::Float(fty) => { - let val = val.to_bits(layout.size)?; let res = match (un_op, fty) { - (Neg, FloatTy::F32) => Single::to_bits(-Single::from_bits(val)), - (Neg, FloatTy::F64) => Double::to_bits(-Double::from_bits(val)), + (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?), + (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), _ => bug!("Invalid float op {:?}", un_op) }; - Ok(Scalar::from_uint(res, layout.size)) + Ok(res) } _ => { assert!(layout.ty.is_integral());