@@ -29,7 +29,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
29
29
30
30
use syntax:: ast:: Mutability ;
31
31
32
- use super :: { Machine , IsStatic } ;
32
+ use super :: Machine ;
33
33
34
34
#[ derive( Debug , PartialEq , Eq , Copy , Clone , Hash ) ]
35
35
pub enum MemoryKind < T > {
@@ -39,23 +39,16 @@ pub enum MemoryKind<T> {
39
39
Machine ( T ) ,
40
40
}
41
41
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
-
51
42
#[ derive( Clone ) ]
52
43
pub struct Memory < ' a , ' mir , ' tcx : ' a + ' mir , M : Machine < ' mir , ' tcx > > {
53
44
/// Additional data required by the Machine
54
45
pub data : M :: MemoryData ,
55
46
56
47
/// Allocations local to this instance of the miri engine. The kind
57
48
/// 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.
59
52
alloc_map : FxHashMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation ) > ,
60
53
61
54
pub tcx : TyCtxtAt < ' a , ' tcx , ' tcx > ,
@@ -223,10 +216,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
223
216
Ok ( new_ptr)
224
217
}
225
218
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
-
230
219
/// Deallocate a local, or do nothing if that local has been made into a static
231
220
pub fn deallocate_local ( & mut self , ptr : Pointer ) -> EvalResult < ' tcx > {
232
221
// 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> {
354
343
/// Allocation accessors
355
344
impl < ' a , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > Memory < ' a , ' mir , ' tcx , M > {
356
345
pub fn get ( & self , id : AllocId ) -> EvalResult < ' tcx , & Allocation > {
357
- // normal alloc?
358
346
match self . alloc_map . get ( & id) {
347
+ // Normal alloc?
359
348
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
361
350
// memory in tcx.
362
351
None => const_eval_static :: < M > ( self . tcx , id) ,
363
352
}
@@ -368,14 +357,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
368
357
id : AllocId ,
369
358
) -> EvalResult < ' tcx , & mut Allocation > {
370
359
// 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
379
372
if alloc. mutability == Mutability :: Immutable {
380
373
err ! ( ModifiedConstantMemory )
381
374
} else {
@@ -489,10 +482,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
489
482
490
483
pub fn leak_report ( & self ) -> usize {
491
484
trace ! ( "### LEAK REPORT ###" ) ;
485
+ let mut_static_kind = M :: MUT_STATIC_KIND . map ( |k| MemoryKind :: Machine ( k) ) ;
492
486
let leaks: Vec < _ > = self . alloc_map
493
487
. 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) } )
496
491
. collect ( ) ;
497
492
let n = leaks. len ( ) ;
498
493
self . dump_allocs ( leaks) ;
@@ -609,7 +604,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
609
604
610
605
/// The alloc_id must refer to a (mutable) static; a deep copy of that
611
606
/// static is made into this memory.
612
- pub fn deep_copy_static (
607
+ fn deep_copy_static (
613
608
& mut self ,
614
609
id : AllocId ,
615
610
kind : MemoryKind < M :: MemoryKinds > ,
@@ -619,7 +614,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
619
614
return err ! ( ModifiedConstantMemory ) ;
620
615
}
621
616
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 " ) ;
623
618
Ok ( ( ) )
624
619
}
625
620
0 commit comments