use syntax::attr;
use syntax::symbol::sym;
use rustc::hir::def_id::DefId;
-use rustc::ty::{self, layout::{Size, LayoutOf}, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, layout::{Size, LayoutOf}};
use rustc::mir;
use crate::*;
bin_op: mir::BinOp,
left: ImmTy<'tcx, Tag>,
right: ImmTy<'tcx, Tag>,
- ) -> InterpResult<'tcx, (Scalar<Tag>, bool)> {
+ ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> {
ecx.binary_ptr_op(bin_op, left, right)
}
bin_op: mir::BinOp,
left: ImmTy<'tcx, Tag>,
right: ImmTy<'tcx, Tag>,
- ) -> InterpResult<'tcx, (Scalar<Tag>, bool)>;
+ ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)>;
fn ptr_eq(
&self,
bin_op: mir::BinOp,
left: ImmTy<'tcx, Tag>,
right: ImmTy<'tcx, Tag>,
- ) -> InterpResult<'tcx, (Scalar<Tag>, bool)> {
+ ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> {
use rustc::mir::BinOp::*;
trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
self.ptr_eq(left2.not_undef()?, right2.not_undef()?)?,
_ => bug!("Type system should not allow comparing Scalar with ScalarPair"),
};
- (Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false)
+ (Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false, self.tcx.types.bool)
}
Lt | Le | Gt | Ge => {
Ge => left >= right,
_ => bug!("We already established it has to be one of these operators."),
};
- (Scalar::from_bool(res), false)
+ (Scalar::from_bool(res), false, self.tcx.types.bool)
}
Offset => {
pointee_ty,
right.to_scalar()?.to_isize(self)?,
)?;
- (ptr, false)
+ (ptr, false, left.layout.ty)
}
_ => bug!("Invalid operator on pointers: {:?}", bin_op)
use rustc::ty;
use crate::{
- PlaceTy, OpTy, ImmTy, Immediate, Scalar, Tag,
+ PlaceTy, OpTy, Immediate, Scalar, Tag,
OperatorEvalContextExt
};
this.memory().check_ptr_access(place.ptr, place.layout.size, align)?;
// binary_op will bail if either of them is not a scalar
- let (eq, _) = this.binary_op(mir::BinOp::Eq, old, expect_old)?;
+ let eq = this.overflowing_binary_op(mir::BinOp::Eq, old, expect_old)?.0;
let res = Immediate::ScalarPair(old.to_scalar_or_undef(), eq.into());
this.write_immediate(res, dest)?; // old value is returned
// update ptr depending on comparison
_ => bug!(),
};
// Atomics wrap around on overflow.
- let (val, _overflowed) = this.binary_op(op, old, rhs)?;
+ let val = this.binary_op(op, old, rhs)?;
let val = if neg {
- this.unary_op(mir::UnOp::Not, ImmTy::from_scalar(val, old.layout))?
+ this.unary_op(mir::UnOp::Not, val)?
} else {
val
};
- this.write_scalar(val, place.into())?;
+ this.write_immediate(*val, place.into())?;
}
"breakpoint" => unimplemented!(), // halt miri
let a = this.read_immediate(args[0])?;
let b = this.read_immediate(args[1])?;
// check x % y != 0
- if this.binary_op(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 {
+ if this.overflowing_binary_op(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 {
// Check if `b` is -1, which is the "min_value / -1" case.
let minus1 = Scalar::from_int(-1, dest.layout.size);
return Err(if b.to_scalar().unwrap() == minus1 {
"unchecked_mul" => mir::BinOp::Mul,
_ => bug!(),
};
- let (res, overflowed) = this.binary_op(op, l, r)?;
+ let (res, overflowed, _ty) = this.overflowing_binary_op(op, l, r)?;
if overflowed {
throw_ub_format!("Overflowing arithmetic in {}", intrinsic_name.get());
}