3 use rustc_middle::{mir, ty::Ty};
7 pub trait EvalContextExt<'tcx> {
11 left: &ImmTy<'tcx, Tag>,
12 right: &ImmTy<'tcx, Tag>,
13 ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)>;
15 fn ptr_eq(&self, left: Scalar<Tag>, right: Scalar<Tag>) -> InterpResult<'tcx, bool>;
18 impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
22 left: &ImmTy<'tcx, Tag>,
23 right: &ImmTy<'tcx, Tag>,
24 ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> {
25 use rustc_middle::mir::BinOp::*;
27 trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
31 // This supports fat pointers.
33 let eq = match (**left, **right) {
34 (Immediate::Scalar(left), Immediate::Scalar(right)) => {
35 self.ptr_eq(left.check_init()?, right.check_init()?)?
37 (Immediate::ScalarPair(left1, left2), Immediate::ScalarPair(right1, right2)) => {
38 self.ptr_eq(left1.check_init()?, right1.check_init()?)?
39 && self.ptr_eq(left2.check_init()?, right2.check_init()?)?
41 _ => bug!("Type system should not allow comparing Scalar with ScalarPair"),
43 (Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false, self.tcx.types.bool)
46 Lt | Le | Gt | Ge => {
47 // Just compare the integers.
48 let left = left.to_scalar()?.to_bits(left.layout.size)?;
49 let right = right.to_scalar()?.to_bits(right.layout.size)?;
50 let res = match bin_op {
55 _ => bug!("We already established it has to be one of these operators."),
57 (Scalar::from_bool(res), false, self.tcx.types.bool)
62 left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
63 let ptr = self.ptr_offset_inbounds(
64 self.scalar_to_ptr(left.to_scalar()?)?,
66 right.to_scalar()?.to_machine_isize(self)?,
68 (Scalar::from_maybe_pointer(ptr, self), false, left.layout.ty)
71 _ => bug!("Invalid operator on pointers: {:?}", bin_op),
75 fn ptr_eq(&self, left: Scalar<Tag>, right: Scalar<Tag>) -> InterpResult<'tcx, bool> {
76 let size = self.pointer_size();
77 // Just compare the integers.
78 let left = left.to_bits(size)?;
79 let right = right.to_bits(size)?;