From c8e471fac3f803d7c332ffea677dcd2b585910a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Oct 2018 19:52:10 +0100 Subject: [PATCH] also allow visiting places and mplaces --- src/librustc_mir/interpret/visitor.rs | 85 ++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 7d6029d6424..79b400a821f 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -10,7 +10,7 @@ }; use super::{ - Machine, EvalContext, MPlaceTy, OpTy, + Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, }; // A thing that we can project into, and that has a layout. @@ -21,13 +21,16 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy // Get this value's layout. fn layout(&self) -> TyLayout<'tcx>; - // Get the underlying `MPlaceTy`, or panic if there is no such thing. - fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag>; + // Make this a `MPlaceTy`, or panic if that's not possible. + fn force_allocation( + self, + ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>>; - // Create this from an `MPlaceTy` + // Create this from an `MPlaceTy`. fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self; - // Project to the n-th field + // Project to the n-th field. fn project_field( self, ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, @@ -45,8 +48,11 @@ fn layout(&self) -> TyLayout<'tcx> { } #[inline(always)] - fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag> { - self.to_mem_place() + fn force_allocation( + self, + _ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + Ok(self.to_mem_place()) } #[inline(always)] @@ -63,6 +69,66 @@ fn project_field( ectx.operand_field(self, field) } } +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> + for MPlaceTy<'tcx, M::PointerTag> +{ + #[inline(always)] + fn layout(&self) -> TyLayout<'tcx> { + self.layout + } + + #[inline(always)] + fn force_allocation( + self, + _ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + Ok(self) + } + + #[inline(always)] + fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self { + mplace + } + + #[inline(always)] + fn project_field( + self, + ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + field: u64, + ) -> EvalResult<'tcx, Self> { + ectx.mplace_field(self, field) + } +} +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> + for PlaceTy<'tcx, M::PointerTag> +{ + #[inline(always)] + fn layout(&self) -> TyLayout<'tcx> { + self.layout + } + + #[inline(always)] + fn force_allocation( + self, + ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + ectx.force_allocation(self) + } + + #[inline(always)] + fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self { + mplace.into() + } + + #[inline(always)] + fn project_field( + self, + ectx: &mut EvalContext<'a, 'mir, 'tcx, M>, + field: u64, + ) -> EvalResult<'tcx, Self> { + ectx.place_field(self, field) + } +} // How to traverse a value and what to do when we are at the leaves. pub trait ValueVisitor<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: fmt::Debug { @@ -135,7 +201,8 @@ pub fn visit_value>( // If it is a trait object, switch to the actual type that was used to create it. match v.layout().ty.sty { ty::Dynamic(..) => { - let dest = v.value().to_mem_place(); // immediate trait objects are not a thing + // immediate trait objects are not a thing + let dest = v.value().force_allocation(self)?; let inner = self.unpack_dyn_trait(dest)?.1; // recurse with the inner type return v.with_field(Value::from_mem_place(inner), 0, |v| self.visit_value(v)); @@ -201,7 +268,7 @@ pub fn visit_value>( MPlaceTy::dangling(v.layout(), self) } else { // non-ZST array/slice/str cannot be immediate - v.value().to_mem_place() + v.value().force_allocation(self)? }; // Now iterate over it. for (i, field) in self.mplace_array_fields(mplace)?.enumerate() {