/// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST.
/// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
#[inline]
- pub fn normalize_op_ptr(
+ pub fn force_op_ptr(
&self,
op: OpTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
match op.try_as_mplace() {
- Ok(mplace) => Ok(self.normalize_mplace_ptr(mplace)?.into()),
- Err(imm) => Ok(imm.into()), // Nothing to normalize
+ Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
+ Err(imm) => Ok(imm.into()), // Nothing to cast/force
}
}
self.memory.check_ptr_access(place.ptr, size, place.align)
}
- /// Normalice `place.ptr` to a `Pointer` if this is not a ZST.
+ /// Force `place.ptr` to a `Pointer`.
/// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
- pub fn normalize_mplace_ptr(
+ pub fn force_mplace_ptr(
&self,
mut place: MPlaceTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
- if !place.layout.is_zst() {
- place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into();
- }
+ place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into();
Ok(place)
}
// `!` is a ZST and we want to validate it.
// Normalize before handing `place` to tracking because that will
// check for duplicates.
- let place = self.ecx.normalize_mplace_ptr(place)?;
+ let place = if size.bytes() > 0 {
+ self.ecx.force_mplace_ptr(place)
+ .expect("we already bounds-checked")
+ } else {
+ place
+ };
let path = &self.path;
ref_tracking.track(place, || {
// We need to clone the path anyway, make sure it gets created
let ty_size = self.ecx.layout_of(tys)?.size;
// This is the size in bytes of the whole array.
let size = ty_size * len;
- // Size is not 0, get a pointer (no cast because we normalized in validate_operand).
- let ptr = mplace.ptr.assert_ptr();
+ // Size is not 0, get a pointer.
+ let ptr = self.ecx.force_ptr(mplace.ptr)?;
// NOTE: Keep this in sync with the handling of integer and float
// types above, in `visit_primitive`.
ecx: self,
};
+ // Try to cast to ptr *once* instead of all the time.
+ let op = self.force_op_ptr(op).unwrap_or(op);
+
// Run it
- let op = self.normalize_op_ptr(op)?; // avoid doing ptr-to-int all the time
visitor.visit_value(op)
}
}