} else if Some(def_id) == self.tcx.lang_items().panic_fn() {
assert!(args.len() == 1);
// &(&'static str, &'static str, u32, u32)
- let ptr = self.read_immediate(args[0])?;
- let place = self.ref_to_mplace(ptr)?;
+ let place = self.deref_operand(args[0])?;
let (msg, file, line, col) = (
self.mplace_field(place, 0)?,
self.mplace_field(place, 1)?,
self.mplace_field(place, 3)?,
);
- let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
+ let msg_place = self.deref_operand(msg.into())?;
let msg = Symbol::intern(self.read_str(msg_place)?);
- let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
+ let file_place = self.deref_operand(file.into())?;
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
assert!(args.len() == 2);
// &'static str, &(&'static str, u32, u32)
let msg = args[0];
- let ptr = self.read_immediate(args[1])?;
- let place = self.ref_to_mplace(ptr)?;
+ let place = self.deref_operand(args[1])?;
let (file, line, col) = (
self.mplace_field(place, 0)?,
self.mplace_field(place, 1)?,
self.mplace_field(place, 2)?,
);
- let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
+ let msg_place = self.deref_operand(msg.into())?;
let msg = Symbol::intern(self.read_str(msg_place)?);
- let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
+ let file_place = self.deref_operand(file.into())?;
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
})
}
- // Take an operand, representing a pointer, and dereference it to a place -- that
- // will always be a MemPlace.
- pub(super) fn deref_operand(
- &self,
- src: OpTy<'tcx, M::PointerTag>,
- ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
- let val = self.read_immediate(src)?;
- trace!("deref to {} on {:?}", val.layout.ty, *val);
- Ok(self.ref_to_mplace(val)?)
- }
-
pub fn operand_projection(
&self,
base: OpTy<'tcx, M::PointerTag>,
{
/// Take a value, which represents a (thin or fat) reference, and make it a place.
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
+ /// This does NOT call the "deref" machine hook, so it does NOT count as a
+ /// deref as far as Stacked Borrows is concerned. Use `deref_operand` for that!
pub fn ref_to_mplace(
&self,
val: ImmTy<'tcx, M::PointerTag>,
let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty;
let layout = self.layout_of(pointee_type)?;
- let align = layout.align;
- let meta = val.to_meta()?;
- let ptr = val.to_scalar_ptr()?;
- let mplace = MemPlace { ptr, align, meta };
- let mut mplace = MPlaceTy { mplace, layout };
+ let mplace = MemPlace {
+ ptr: val.to_scalar_ptr()?,
+ align: layout.align,
+ meta: val.to_meta()?,
+ };
+ Ok(MPlaceTy { mplace, layout })
+ }
+
+ // Take an operand, representing a pointer, and dereference it to a place -- that
+ // will always be a MemPlace. Lives in `place.rs` because it creates a place.
+ // This calls the "deref" machine hook, and counts as a deref as far as
+ // Stacked Borrows is concerned.
+ pub fn deref_operand(
+ &self,
+ src: OpTy<'tcx, M::PointerTag>,
+ ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+ let val = self.read_immediate(src)?;
+ trace!("deref to {} on {:?}", val.layout.ty, *val);
+ let mut place = self.ref_to_mplace(val)?;
// Pointer tag tracking might want to adjust the tag.
let mutbl = match val.layout.ty.sty {
// `builtin_deref` considers boxes immutable, that's useless for our purposes
ty::RawPtr(_) => None,
_ => bug!("Unexpected pointer type {}", val.layout.ty.sty),
};
- mplace.mplace.ptr = M::tag_dereference(self, mplace, mutbl)?;
- // Done
- Ok(mplace)
+ place.mplace.ptr = M::tag_dereference(self, place, mutbl)?;
+ Ok(place)
}
/// Offset a pointer to project to a field. Unlike place_field, this is always
ty::InstanceDef::Virtual(_, idx) => {
let ptr_size = self.pointer_size();
let ptr_align = self.tcx.data_layout.pointer_align;
- let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
+ let ptr = self.deref_operand(args[0])?;
let vtable = ptr.vtable()?;
let fn_ptr = self.memory.read_ptr_sized(
vtable.offset(ptr_size * (idx as u64 + 3), self)?,
}
}
}
- // Turn ptr into place.
- // `ref_to_mplace` also calls the machine hook for (re)activating the tag,
- // which in turn will (in full miri) check if the pointer is dereferencable.
- let place = self.ecx.ref_to_mplace(value)?;
// Recursive checking
if let Some(ref mut ref_tracking) = self.ref_tracking {
assert!(self.const_mode, "We should only do recursie checking in const mode");
+ let place = self.ecx.ref_to_mplace(value)?;
if size != Size::ZERO {
// Non-ZST also have to be dereferencable
let ptr = try_validation!(place.ptr.to_ptr(),