@@ -42,20 +42,19 @@ pub struct GlobalStateInner {
42
42
/// they do not have an `AllocExtra`.
43
43
/// This is the inverse of `int_to_ptr_map`.
44
44
base_addr : FxHashMap < AllocId , u64 > ,
45
- /// Temporarily store prepared memory space for global allocations the first time their memory
46
- /// address is required. This is used to ensure that the memory is allocated before Miri assigns
47
- /// it an internal address, which is important for matching the internal address to the machine
48
- /// address so FFI can read from pointers.
49
- prepared_alloc_bytes : FxHashMap < AllocId , MiriAllocBytes > ,
50
- /// A pool of addresses we can reuse for future allocations.
51
- reuse : ReusePool ,
52
- /// Whether an allocation has been exposed or not. This cannot be put
45
+ /// The set of exposed allocations. This cannot be put
53
46
/// into `AllocExtra` for the same reason as `base_addr`.
54
47
exposed : FxHashSet < AllocId > ,
55
- /// The generator for new addresses in a given range.
56
- address_generator : AddressGenerator ,
57
48
/// The provenance to use for int2ptr casts
58
49
provenance_mode : ProvenanceMode ,
50
+ /// The generator for new addresses in a given range, and a pool for address reuse. This is
51
+ /// `None` if addresses are generated elsewhere (in native-lib mode or with GenMC).
52
+ address_generation : Option < ( AddressGenerator , ReusePool ) > ,
53
+ /// Native-lib mode only: Temporarily store prepared memory space for global allocations the
54
+ /// first time their memory address is required. This is used to ensure that the memory is
55
+ /// allocated before Miri assigns it an internal address, which is important for matching the
56
+ /// internal address to the machine address so FFI can read from pointers.
57
+ prepared_alloc_bytes : Option < FxHashMap < AllocId , MiriAllocBytes > > ,
59
58
}
60
59
61
60
impl VisitProvenance for GlobalStateInner {
@@ -64,9 +63,8 @@ impl VisitProvenance for GlobalStateInner {
64
63
int_to_ptr_map : _,
65
64
base_addr : _,
66
65
prepared_alloc_bytes : _,
67
- reuse : _,
68
66
exposed : _,
69
- address_generator : _,
67
+ address_generation : _,
70
68
provenance_mode : _,
71
69
} = self ;
72
70
// Though base_addr, int_to_ptr_map, and exposed contain AllocIds, we do not want to visit them.
@@ -83,11 +81,16 @@ impl GlobalStateInner {
83
81
GlobalStateInner {
84
82
int_to_ptr_map : Vec :: default ( ) ,
85
83
base_addr : FxHashMap :: default ( ) ,
86
- prepared_alloc_bytes : FxHashMap :: default ( ) ,
87
- reuse : ReusePool :: new ( config) ,
88
84
exposed : FxHashSet :: default ( ) ,
89
- address_generator : AddressGenerator :: new ( stack_addr..tcx. target_usize_max ( ) ) ,
90
85
provenance_mode : config. provenance_mode ,
86
+ address_generation : ( config. native_lib . is_empty ( ) && config. genmc_config . is_none ( ) )
87
+ . then ( || {
88
+ (
89
+ AddressGenerator :: new ( stack_addr..tcx. target_usize_max ( ) ) ,
90
+ ReusePool :: new ( config) ,
91
+ )
92
+ } ) ,
93
+ prepared_alloc_bytes : ( !config. native_lib . is_empty ( ) ) . then ( FxHashMap :: default) ,
91
94
}
92
95
}
93
96
@@ -147,6 +150,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
147
150
// Store prepared allocation to be picked up for use later.
148
151
global_state
149
152
. prepared_alloc_bytes
153
+ . as_mut ( )
154
+ . unwrap ( )
150
155
. try_insert ( alloc_id, prepared_bytes)
151
156
. unwrap ( ) ;
152
157
ptr
@@ -173,29 +178,25 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
173
178
// We don't have to expose this pointer yet, we do that in `prepare_for_native_call`.
174
179
return interp_ok ( base_ptr. addr ( ) . to_u64 ( ) ) ;
175
180
}
176
- // We are not in native lib mode, so we control the addresses ourselves.
181
+ // We are not in native lib or genmc mode, so we control the addresses ourselves.
182
+ let ( addr_gen, reuse) = global_state. address_generation . as_mut ( ) . unwrap ( ) ;
177
183
let mut rng = this. machine . rng . borrow_mut ( ) ;
178
- if let Some ( ( reuse_addr, clock) ) = global_state. reuse . take_addr (
179
- & mut * rng,
180
- info. size ,
181
- info. align ,
182
- memory_kind,
183
- this. active_thread ( ) ,
184
- ) {
184
+ if let Some ( ( reuse_addr, clock) ) =
185
+ reuse. take_addr ( & mut * rng, info. size , info. align , memory_kind, this. active_thread ( ) )
186
+ {
185
187
if let Some ( clock) = clock {
186
188
this. acquire_clock ( & clock) ?;
187
189
}
188
190
interp_ok ( reuse_addr)
189
191
} else {
190
192
// We have to pick a fresh address.
191
- let new_addr =
192
- global_state. address_generator . generate ( info. size , info. align , & mut rng) ?;
193
+ let new_addr = addr_gen. generate ( info. size , info. align , & mut rng) ?;
193
194
194
195
// If we filled up more than half the address space, start aggressively reusing
195
196
// addresses to avoid running out.
196
- let remaining_range = global_state . address_generator . get_remaining ( ) ;
197
+ let remaining_range = addr_gen . get_remaining ( ) ;
197
198
if remaining_range. start > remaining_range. end / 2 {
198
- global_state . reuse . address_space_shortage ( ) ;
199
+ reuse. address_space_shortage ( ) ;
199
200
}
200
201
201
202
interp_ok ( new_addr)
@@ -414,6 +415,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
414
415
let mut global_state = this. machine . alloc_addresses . borrow_mut ( ) ;
415
416
let mut prepared_alloc_bytes = global_state
416
417
. prepared_alloc_bytes
418
+ . as_mut ( )
419
+ . unwrap ( )
417
420
. remove ( & id)
418
421
. unwrap_or_else ( || panic ! ( "alloc bytes for {id:?} have not been prepared" ) ) ;
419
422
// Sanity-check that the prepared allocation has the right size and alignment.
@@ -496,15 +499,17 @@ impl<'tcx> MiriMachine<'tcx> {
496
499
// `alloc_id_from_addr` any more.
497
500
global_state. exposed . remove ( & dead_id) ;
498
501
// Also remember this address for future reuse.
499
- let thread = self . threads . active_thread ( ) ;
500
- global_state. reuse . add_addr ( rng, addr, size, align, kind, thread, || {
501
- // We already excluded GenMC above. We cannot use `self.release_clock` as
502
- // `self.alloc_addresses` is borrowed.
503
- if let Some ( data_race) = self . data_race . as_vclocks_ref ( ) {
504
- data_race. release_clock ( & self . threads , |clock| clock. clone ( ) )
505
- } else {
506
- VClock :: default ( )
507
- }
508
- } )
502
+ if let Some ( ( _addr_gen, reuse) ) = global_state. address_generation . as_mut ( ) {
503
+ let thread = self . threads . active_thread ( ) ;
504
+ reuse. add_addr ( rng, addr, size, align, kind, thread, || {
505
+ // We cannot be in GenMC mode as then `address_generation` is `None`. We cannot use
506
+ // `self.release_clock` as `self.alloc_addresses` is borrowed.
507
+ if let Some ( data_race) = self . data_race . as_vclocks_ref ( ) {
508
+ data_race. release_clock ( & self . threads , |clock| clock. clone ( ) )
509
+ } else {
510
+ VClock :: default ( )
511
+ }
512
+ } )
513
+ }
509
514
}
510
515
}
0 commit comments