-use rustc::ty::{Ty, layout::TyLayout};
+use rustc::ty::Ty;
use rustc::mir;
use crate::*;
&self,
left: Scalar<Borrow>,
right: Scalar<Borrow>,
- size: Size,
) -> EvalResult<'tcx, bool>;
fn pointer_offset_inbounds(
) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
use rustc::mir::BinOp::*;
+ trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
+
+ // Operations that support fat pointers
+ match bin_op {
+ Eq | Ne => {
+ let eq = match (*left, *right) {
+ (Immediate::Scalar(left), Immediate::Scalar(right)) =>
+ self.ptr_eq(left.not_undef()?, right.not_undef()?)?,
+ (Immediate::ScalarPair(left1, left2), Immediate::ScalarPair(right1, right2)) =>
+ self.ptr_eq(left1.not_undef()?, right1.not_undef()?)? &&
+ self.ptr_eq(left2.not_undef()?, right2.not_undef()?)?,
+ _ => bug!("Type system should not allow comparing Scalar with ScalarPair"),
+ };
+ return Ok((Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false));
+ }
+ _ => {},
+ }
+
+ // Now we expect no more fat pointers
let left_layout = left.layout;
let left = left.to_scalar()?;
let right_layout = right.layout;
let right = right.to_scalar()?;
-
- trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);
match bin_op {
)?;
Ok((ptr, false))
}
- // These work on anything
- Eq =>
- Ok((Scalar::from_bool(self.ptr_eq(left, right, left_layout.size)?), false)),
- Ne =>
- Ok((Scalar::from_bool(!self.ptr_eq(left, right, left_layout.size)?), false)),
// These need both to be pointer, and fail if they are not in the same location
Lt | Le | Gt | Ge | Sub if left.is_ptr() && right.is_ptr() => {
let left = left.to_ptr().expect("we checked is_ptr");
&self,
left: Scalar<Borrow>,
right: Scalar<Borrow>,
- size: Size,
) -> EvalResult<'tcx, bool> {
+ let size = self.pointer_size();
Ok(match (left, right) {
(Scalar::Bits { .. }, Scalar::Bits { .. }) =>
left.to_bits(size)? == right.to_bits(size)?,