+
+// Validity checks
+impl<'a, 'tcx> EvalContext<'a, 'tcx> {
+ pub(super) fn acquire_valid(&mut self, lvalue: Lvalue<'tcx>, ty: Ty<'tcx>, outer_mutbl: TyMutability) -> EvalResult<'tcx> {
+ use rustc::ty::TypeVariants::*;
+ use rustc::ty::RegionKind::*;
+ use self::TyMutability::*;
+
+ trace!("Validating {:?} at type {}, outer mutability {:?}", lvalue, ty, outer_mutbl);
+ match ty.sty {
+ TyChar | TyInt(_) | TyUint(_) | TyRawPtr(_) => {
+ // TODO: Make sure these are not undef.
+ // We could do a bounds-check and other sanity checks on the lvalue, but it would be a bug in miri for this to ever fail.
+ Ok(())
+ }
+ TyBool | TyFloat(_) | TyStr => {
+ // TODO: Check if these are valid bool/float/UTF-8, respectively (and in particular, not undef).
+ Ok(())
+ }
+ TyRef(region, TypeAndMut { ty: pointee_ty, mutbl }) => {
+ // Acquire lock
+ let val = self.read_lvalue(lvalue)?;
+ let (len, _) = self.size_and_align_of_dst(pointee_ty, val)?;
+ let ptr = val.into_ptr(&mut self.memory)?.to_ptr()?;
+ let combined_mutbl = match outer_mutbl { MutMutable => mutbl, MutImmutable => MutImmutable };
+ let access = match combined_mutbl { MutMutable => AccessKind::Write, MutImmutable => AccessKind::Read };
+ let region = match *region {
+ ReScope(extent) => Some(extent),
+ _ => None,
+ };
+ self.memory.acquire_lock(ptr, len, region, access)?;
+
+ // Recurse
+ let pointee_lvalue = self.val_to_lvalue(val, pointee_ty)?;
+ self.acquire_valid(pointee_lvalue, pointee_ty, combined_mutbl)
+ }
+ TySlice(elem_ty) => {
+ let len = match lvalue {
+ Lvalue::Ptr { extra: LvalueExtra::Length(len), .. } => len,
+ _ => bug!("acquire_valid of a TySlice given non-slice lvalue: {:?}", lvalue),
+ };
+ for i in 0..len {
+ let inner_lvalue = self.lvalue_index(lvalue, ty, i)?;
+ self.acquire_valid(inner_lvalue, elem_ty, outer_mutbl)?;
+ }
+ Ok(())
+ }
+ TyFnPtr(_sig) => {
+ // TODO: The function names here could need some improvement.
+ let ptr = self.read_lvalue(lvalue)?.into_ptr(&mut self.memory)?.to_ptr()?;
+ self.memory.get_fn(ptr)?;
+ // TODO: Check if the signature matches (should be the same check as what terminator/mod.rs already does on call?).
+ Ok(())
+ }
+ _ => unimplemented!("Unimplemented type encountered when checking validity.")
+ }
+ }
+}