@@ -21,8 +21,8 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
21
21
22
22
use super :: {
23
23
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 ,
26
26
} ;
27
27
use crate :: errors:: { self , ErroneousConstUsed } ;
28
28
use crate :: util;
@@ -155,17 +155,26 @@ pub enum StackPopCleanup {
155
155
}
156
156
157
157
/// State of a local variable including a memoized layout
158
- #[ derive( Clone , Debug ) ]
158
+ #[ derive( Clone ) ]
159
159
pub struct LocalState < ' tcx , Prov : Provenance = AllocId > {
160
- pub value : LocalValue < Prov > ,
160
+ value : LocalValue < Prov > ,
161
161
/// Don't modify if `Some`, this is only used to prevent computing the layout twice.
162
162
/// 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
+ }
164
173
}
165
174
166
175
/// Current value of a local variable
167
176
#[ derive( Copy , Clone , Debug ) ] // Miri debug-prints these
168
- pub enum LocalValue < Prov : Provenance = AllocId > {
177
+ pub ( super ) enum LocalValue < Prov : Provenance = AllocId > {
169
178
/// This local is not currently alive, and cannot be used at all.
170
179
Dead ,
171
180
/// A normal, live local.
@@ -176,10 +185,27 @@ pub enum LocalValue<Prov: Provenance = AllocId> {
176
185
Live ( Operand < Prov > ) ,
177
186
}
178
187
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
+
180
206
/// Read the local's value or error if the local is not yet live or not live anymore.
181
207
#[ inline( always) ]
182
- pub fn access ( & self ) -> InterpResult < ' tcx , & Operand < Prov > > {
208
+ pub ( super ) fn access ( & self ) -> InterpResult < ' tcx , & Operand < Prov > > {
183
209
match & self . value {
184
210
LocalValue :: Dead => throw_ub ! ( DeadLocal ) , // could even be "invalid program"?
185
211
LocalValue :: Live ( val) => Ok ( val) ,
@@ -189,10 +215,10 @@ impl<'tcx, Prov: Provenance + 'static> LocalState<'tcx, Prov> {
189
215
/// Overwrite the local. If the local can be overwritten in place, return a reference
190
216
/// to do so; otherwise return the `MemPlace` to consult instead.
191
217
///
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 !
194
220
#[ 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 > > {
196
222
match & mut self . value {
197
223
LocalValue :: Dead => throw_ub ! ( DeadLocal ) , // could even be "invalid program"?
198
224
LocalValue :: Live ( val) => Ok ( val) ,
@@ -694,7 +720,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694
720
& self ,
695
721
mplace : & MPlaceTy < ' tcx , M :: Provenance > ,
696
722
) -> 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 )
698
724
}
699
725
700
726
#[ 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> {
826
852
. expect ( "return place should always be live" ) ;
827
853
let dest = self . frame ( ) . return_place . clone ( ) ;
828
854
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) ) ;
830
856
// We delay actually short-circuiting on this error until *after* the stack frame is
831
857
// popped, since we want this error to be attributed to the caller, whose type defines
832
858
// this transmute.
@@ -974,7 +1000,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
974
1000
}
975
1001
// Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
976
1002
let dest_place = self . allocate_dyn ( layout, MemoryKind :: Stack , meta) ?;
977
- Operand :: Indirect ( * dest_place)
1003
+ Operand :: Indirect ( * dest_place. mplace ( ) )
978
1004
} else {
979
1005
assert ! ( !meta. has_meta( ) ) ; // we're dropping the metadata
980
1006
// Just make this an efficient immediate.
@@ -1068,8 +1094,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1068
1094
}
1069
1095
1070
1096
#[ 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 ( ) }
1073
1102
}
1074
1103
1075
1104
#[ must_use]
0 commit comments