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 // TODO: Do we really want to *always* do that, even when comparing two live in-bounds pointers?
49 let left = self.force_bits(left.to_scalar()?, left.layout.size)?;
50 let right = self.force_bits(right.to_scalar()?, right.layout.size)?;
51 let res = match bin_op {
56 _ => bug!("We already established it has to be one of these operators."),
58 (Scalar::from_bool(res), false, self.tcx.types.bool)
63 left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
64 let ptr = self.ptr_offset_inbounds(
67 right.to_scalar()?.to_machine_isize(self)?,
69 (ptr, false, left.layout.ty)
72 _ => bug!("Invalid operator on pointers: {:?}", bin_op),
76 fn ptr_eq(&self, left: Scalar<Tag>, right: Scalar<Tag>) -> InterpResult<'tcx, bool> {
77 let size = self.pointer_size();
78 // Just compare the integers.
79 // TODO: Do we really want to *always* do that, even when comparing two live in-bounds pointers?
80 let left = self.force_bits(left, size)?;
81 let right = self.force_bits(right, size)?;