@@ -21,8 +21,8 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
2121
2222use super :: {
2323 AllocId , GlobalId , Immediate , InterpErrorInfo , InterpResult , MPlaceTy , Machine , MemPlace ,
24- MemPlaceMeta , Memory , MemoryKind , Operand , Place , PlaceTy , PointerArithmetic , Provenance ,
25- Scalar , StackPopJump ,
24+ MemPlaceMeta , Memory , MemoryKind , Operand , Place , PlaceTy , Pointer , PointerArithmetic ,
25+ Projectable , Provenance , Scalar , StackPopJump ,
2626} ;
2727use crate :: errors:: { self , ErroneousConstUsed } ;
2828use crate :: util;
@@ -155,17 +155,26 @@ pub enum StackPopCleanup {
155155}
156156
157157/// State of a local variable including a memoized layout
158- #[ derive( Clone , Debug ) ]
158+ #[ derive( Clone ) ]
159159pub struct LocalState < ' tcx , Prov : Provenance = AllocId > {
160- pub value : LocalValue < Prov > ,
160+ value : LocalValue < Prov > ,
161161 /// Don't modify if `Some`, this is only used to prevent computing the layout twice.
162162 /// Avoids computing the layout of locals that are never actually initialized.
163- pub layout : Cell < Option < TyAndLayout < ' tcx > > > ,
163+ layout : Cell < Option < TyAndLayout < ' tcx > > > ,
164+ }
165+
166+ impl < Prov : Provenance > std:: fmt:: Debug for LocalState < ' _ , Prov > {
167+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
168+ f. debug_struct ( "LocalState" )
169+ . field ( "value" , & self . value )
170+ . field ( "ty" , & self . layout . get ( ) . map ( |l| l. ty ) )
171+ . finish ( )
172+ }
164173}
165174
166175/// Current value of a local variable
167176#[ derive( Copy , Clone , Debug ) ] // Miri debug-prints these
168- pub enum LocalValue < Prov : Provenance = AllocId > {
177+ pub ( super ) enum LocalValue < Prov : Provenance = AllocId > {
169178 /// This local is not currently alive, and cannot be used at all.
170179 Dead ,
171180 /// A normal, live local.
@@ -176,10 +185,27 @@ pub enum LocalValue<Prov: Provenance = AllocId> {
176185 Live ( Operand < Prov > ) ,
177186}
178187
179- impl < ' tcx , Prov : Provenance + ' static > LocalState < ' tcx , Prov > {
188+ impl < ' tcx , Prov : Provenance > LocalState < ' tcx , Prov > {
189+ pub fn make_live_uninit ( & mut self ) {
190+ self . value = LocalValue :: Live ( Operand :: Immediate ( Immediate :: Uninit ) ) ;
191+ }
192+
193+ /// This is a hack because Miri needs a way to visit all the provenance in a `LocalState`
194+ /// without having a layout or `TyCtxt` available, and we want to keep the `Operand` type
195+ /// private.
196+ pub fn as_mplace_or_imm (
197+ & self ,
198+ ) -> Option < Either < ( Pointer < Option < Prov > > , MemPlaceMeta < Prov > ) , Immediate < Prov > > > {
199+ match self . value {
200+ LocalValue :: Dead => None ,
201+ LocalValue :: Live ( Operand :: Indirect ( mplace) ) => Some ( Left ( ( mplace. ptr , mplace. meta ) ) ) ,
202+ LocalValue :: Live ( Operand :: Immediate ( imm) ) => Some ( Right ( imm) ) ,
203+ }
204+ }
205+
180206 /// Read the local's value or error if the local is not yet live or not live anymore.
181207 #[ inline( always) ]
182- pub fn access ( & self ) -> InterpResult < ' tcx , & Operand < Prov > > {
208+ pub ( super ) fn access ( & self ) -> InterpResult < ' tcx , & Operand < Prov > > {
183209 match & self . value {
184210 LocalValue :: Dead => throw_ub ! ( DeadLocal ) , // could even be "invalid program"?
185211 LocalValue :: Live ( val) => Ok ( val) ,
@@ -189,10 +215,10 @@ impl<'tcx, Prov: Provenance + 'static> LocalState<'tcx, Prov> {
189215 /// Overwrite the local. If the local can be overwritten in place, return a reference
190216 /// to do so; otherwise return the `MemPlace` to consult instead.
191217 ///
192- /// Note: This may only be invoked from the `Machine::access_local_mut` hook and not from
193- /// anywhere else. You may be invalidating machine invariants if you do !
218+ /// Note: Before calling this, call the `before_access_local_mut` machine hook! You may be
219+ /// invalidating machine invariants otherwise !
194220 #[ inline( always) ]
195- pub fn access_mut ( & mut self ) -> InterpResult < ' tcx , & mut Operand < Prov > > {
221+ pub ( super ) fn access_mut ( & mut self ) -> InterpResult < ' tcx , & mut Operand < Prov > > {
196222 match & mut self . value {
197223 LocalValue :: Dead => throw_ub ! ( DeadLocal ) , // could even be "invalid program"?
198224 LocalValue :: Live ( val) => Ok ( val) ,
@@ -694,7 +720,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694720 & self ,
695721 mplace : & MPlaceTy < ' tcx , M :: Provenance > ,
696722 ) -> InterpResult < ' tcx , Option < ( Size , Align ) > > {
697- self . size_and_align_of ( & mplace. meta , & mplace. layout )
723+ self . size_and_align_of ( & mplace. meta ( ) , & mplace. layout )
698724 }
699725
700726 #[ instrument( skip( self , body, return_place, return_to_block) , level = "debug" ) ]
@@ -826,7 +852,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
826852 . expect ( "return place should always be live" ) ;
827853 let dest = self . frame ( ) . return_place . clone ( ) ;
828854 let err = self . copy_op ( & op, & dest, /*allow_transmute*/ true ) ;
829- trace ! ( "return value: {:?}" , self . dump_place( * dest) ) ;
855+ trace ! ( "return value: {:?}" , self . dump_place( & dest) ) ;
830856 // We delay actually short-circuiting on this error until *after* the stack frame is
831857 // popped, since we want this error to be attributed to the caller, whose type defines
832858 // this transmute.
@@ -974,7 +1000,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9741000 }
9751001 // Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
9761002 let dest_place = self . allocate_dyn ( layout, MemoryKind :: Stack , meta) ?;
977- Operand :: Indirect ( * dest_place)
1003+ Operand :: Indirect ( * dest_place. mplace ( ) )
9781004 } else {
9791005 assert ! ( !meta. has_meta( ) ) ; // we're dropping the metadata
9801006 // Just make this an efficient immediate.
@@ -1068,8 +1094,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10681094 }
10691095
10701096 #[ must_use]
1071- pub fn dump_place ( & self , place : Place < M :: Provenance > ) -> PlacePrinter < ' _ , ' mir , ' tcx , M > {
1072- PlacePrinter { ecx : self , place }
1097+ pub fn dump_place (
1098+ & self ,
1099+ place : & PlaceTy < ' tcx , M :: Provenance > ,
1100+ ) -> PlacePrinter < ' _ , ' mir , ' tcx , M > {
1101+ PlacePrinter { ecx : self , place : * place. place ( ) }
10731102 }
10741103
10751104 #[ must_use]
0 commit comments