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};
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)
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)
}
bin_op: mir::BinOp,
l: char,
r: char,
- ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
+ ) -> (Scalar<M::PointerTag>, bool) {
use rustc::mir::BinOp::*;
let res = match bin_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(
bin_op: mir::BinOp,
l: bool,
r: bool,
- ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
+ ) -> (Scalar<M::PointerTag>, bool) {
use rustc::mir::BinOp::*;
let res = match bin_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<F: Float + Into<Scalar<M::PointerTag>>>(
&self,
bin_op: mir::BinOp,
- fty: FloatTy,
- // passing in raw bits
- l: u128,
- r: u128,
- ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
+ l: F,
+ r: F,
+ ) -> (Scalar<M::PointerTag>, 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(
left_layout: TyLayout<'tcx>,
r: u128,
right_layout: TyLayout<'tcx>,
- ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
+ ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, bool)> {
use rustc::mir::BinOp::*;
// Shift ops can have an RHS with a different numeric type.
bin_op: mir::BinOp,
left: ImmTy<'tcx, M::PointerTag>,
right: ImmTy<'tcx, M::PointerTag>,
- ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
+ ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, 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() ||
&self,
un_op: mir::UnOp,
val: ImmTy<'tcx, M::PointerTag>,
- ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
+ ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
use rustc::mir::UnOp::*;
let layout = val.layout;
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());