@@ -29,7 +29,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
2929
3030use syntax:: ast:: Mutability ;
3131
32- use super :: { Machine , IsStatic } ;
32+ use super :: Machine ;
3333
3434#[ derive( Debug , PartialEq , Eq , Copy , Clone , Hash ) ]
3535pub enum MemoryKind < T > {
@@ -39,23 +39,16 @@ pub enum MemoryKind<T> {
3939 Machine ( T ) ,
4040}
4141
42- impl < T : IsStatic > IsStatic for MemoryKind < T > {
43- fn is_static ( self ) -> bool {
44- match self {
45- MemoryKind :: Stack => false ,
46- MemoryKind :: Machine ( kind) => kind. is_static ( ) ,
47- }
48- }
49- }
50-
5142#[ derive( Clone ) ]
5243pub struct Memory < ' a , ' mir , ' tcx : ' a + ' mir , M : Machine < ' mir , ' tcx > > {
5344 /// Additional data required by the Machine
5445 pub data : M :: MemoryData ,
5546
5647 /// Allocations local to this instance of the miri engine. The kind
5748 /// helps ensure that the same mechanism is used for allocation and
58- /// deallocation.
49+ /// deallocation. When an allocation is not found here, it is a
50+ /// static and looked up in the `tcx` for read access. Writing to
51+ /// a static creates a copy here, in the machine.
5952 alloc_map : FxHashMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation ) > ,
6053
6154 pub tcx : TyCtxtAt < ' a , ' tcx , ' tcx > ,
@@ -223,10 +216,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
223216 Ok ( new_ptr)
224217 }
225218
226- pub fn is_static ( & self , alloc_id : AllocId ) -> bool {
227- self . alloc_map . get ( & alloc_id) . map_or ( true , |& ( kind, _) | kind. is_static ( ) )
228- }
229-
230219 /// Deallocate a local, or do nothing if that local has been made into a static
231220 pub fn deallocate_local ( & mut self , ptr : Pointer ) -> EvalResult < ' tcx > {
232221 // The allocation might be already removed by static interning.
@@ -354,10 +343,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
354343/// Allocation accessors
355344impl < ' a , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > Memory < ' a , ' mir , ' tcx , M > {
356345 pub fn get ( & self , id : AllocId ) -> EvalResult < ' tcx , & Allocation > {
357- // normal alloc?
358346 match self . alloc_map . get ( & id) {
347+ // Normal alloc?
359348 Some ( alloc) => Ok ( & alloc. 1 ) ,
360- // No need to make any copies, just provide read access to the global static
349+ // Static. No need to make any copies, just provide read access to the global static
361350 // memory in tcx.
362351 None => const_eval_static :: < M > ( self . tcx , id) ,
363352 }
@@ -368,14 +357,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
368357 id : AllocId ,
369358 ) -> EvalResult < ' tcx , & mut Allocation > {
370359 // Static?
371- let alloc = if self . alloc_map . contains_key ( & id) {
372- & mut self . alloc_map . get_mut ( & id) . unwrap ( ) . 1
373- } else {
374- // The machine controls to what extend we are allowed to mutate global
375- // statics. (We do not want to allow that during CTFE, but miri needs it.)
376- M :: access_static_mut ( self , id) ?
377- } ;
378- // See if we can use this
360+ if !self . alloc_map . contains_key ( & id) {
361+ // Ask the machine for what to do
362+ if let Some ( kind) = M :: MUT_STATIC_KIND {
363+ // The machine supports mutating statics. Make a copy, use that.
364+ self . deep_copy_static ( id, MemoryKind :: Machine ( kind) ) ?;
365+ } else {
366+ return err ! ( ModifiedConstantMemory )
367+ }
368+ }
369+ // If we come here, we know the allocation is in our map
370+ let alloc = & mut self . alloc_map . get_mut ( & id) . unwrap ( ) . 1 ;
371+ // See if we are allowed to mutate this
379372 if alloc. mutability == Mutability :: Immutable {
380373 err ! ( ModifiedConstantMemory )
381374 } else {
@@ -489,10 +482,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
489482
490483 pub fn leak_report ( & self ) -> usize {
491484 trace ! ( "### LEAK REPORT ###" ) ;
485+ let mut_static_kind = M :: MUT_STATIC_KIND . map ( |k| MemoryKind :: Machine ( k) ) ;
492486 let leaks: Vec < _ > = self . alloc_map
493487 . iter ( )
494- . filter_map ( |( & id, ( kind, _) ) |
495- if kind. is_static ( ) { None } else { Some ( id) } )
488+ . filter_map ( |( & id, & ( kind, _) ) |
489+ // exclude mutable statics
490+ if Some ( kind) == mut_static_kind { None } else { Some ( id) } )
496491 . collect ( ) ;
497492 let n = leaks. len ( ) ;
498493 self . dump_allocs ( leaks) ;
@@ -609,7 +604,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
609604
610605 /// The alloc_id must refer to a (mutable) static; a deep copy of that
611606 /// static is made into this memory.
612- pub fn deep_copy_static (
607+ fn deep_copy_static (
613608 & mut self ,
614609 id : AllocId ,
615610 kind : MemoryKind < M :: MemoryKinds > ,
@@ -619,7 +614,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
619614 return err ! ( ModifiedConstantMemory ) ;
620615 }
621616 let old = self . alloc_map . insert ( id, ( kind, alloc. clone ( ) ) ) ;
622- assert ! ( old. is_none( ) , "deep_copy_static: must not overwrite memory with " ) ;
617+ assert ! ( old. is_none( ) , "deep_copy_static: must not overwrite existing memory " ) ;
623618 Ok ( ( ) )
624619 }
625620
0 commit comments