@@ -321,14 +321,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
321
321
322
322
/// Allocation accessors
323
323
impl < ' a , ' mir , ' tcx , M : Machine < ' a , ' mir , ' tcx > > Memory < ' a , ' mir , ' tcx , M > {
324
- /// Helper function to obtain the global (tcx) allocation for a static
324
+ /// Helper function to obtain the global (tcx) allocation for a static.
325
+ /// This attempts to return a reference to an existing allocation if
326
+ /// one can be found in `tcx`. That, however, is only possible if `tcx` and
327
+ /// this machine use the same pointer tag, so it is indirected through
328
+ /// `M::static_with_default_tag`.
325
329
fn get_static_alloc (
326
330
tcx : TyCtxtAt < ' a , ' tcx , ' tcx > ,
327
331
id : AllocId ,
328
332
) -> EvalResult < ' tcx , Cow < ' tcx , Allocation < M :: PointerTag > > > {
329
333
let alloc = tcx. alloc_map . lock ( ) . get ( id) ;
330
334
let def_id = match alloc {
331
335
Some ( AllocType :: Memory ( mem) ) => {
336
+ // We got tcx memory. Let the machine figure out whether and how to
337
+ // turn that into memory with the right pointer tag.
332
338
return Ok ( M :: static_with_default_tag ( mem) )
333
339
}
334
340
Some ( AllocType :: Function ( ..) ) => {
@@ -356,6 +362,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
356
362
EvalErrorKind :: ReferencedConstant ( err) . into ( )
357
363
} ) . map ( |const_val| {
358
364
if let ConstValue :: ByRef ( _, allocation, _) = const_val. val {
365
+ // We got tcx memory. Let the machine figure out whether and how to
366
+ // turn that into memory with the right pointer tag.
359
367
M :: static_with_default_tag ( allocation)
360
368
} else {
361
369
bug ! ( "Matching on non-ByRef static" )
@@ -372,7 +380,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
372
380
let alloc = Self :: get_static_alloc ( self . tcx , id) . map_err ( Err ) ?;
373
381
match alloc {
374
382
Cow :: Borrowed ( alloc) => {
375
- // We got a ref, cheaply return that as an "error"
383
+ // We got a ref, cheaply return that as an "error" so that the
384
+ // map does not get mutated.
376
385
Err ( Ok ( alloc) )
377
386
}
378
387
Cow :: Owned ( alloc) => {
@@ -392,30 +401,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
392
401
}
393
402
}
394
403
395
- pub fn get_size_and_align ( & self , id : AllocId ) -> ( Size , Align ) {
396
- if let Ok ( alloc) = self . get ( id) {
397
- return ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ;
398
- }
399
- // Could also be a fn ptr or extern static
400
- match self . tcx . alloc_map . lock ( ) . get ( id) {
401
- Some ( AllocType :: Function ( ..) ) => ( Size :: ZERO , Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ,
402
- Some ( AllocType :: Static ( did) ) => {
403
- // The only way `get` couldnÄt have worked here is if this is an extern static
404
- assert ! ( self . tcx. is_foreign_item( did) ) ;
405
- // Use size and align of the type
406
- let ty = self . tcx . type_of ( did) ;
407
- let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
408
- ( layout. size , layout. align )
409
- }
410
- _ => {
411
- // Must be a deallocated pointer
412
- * self . dead_alloc_map . get ( & id) . expect (
413
- "allocation missing in dead_alloc_map"
414
- )
415
- }
416
- }
417
- }
418
-
419
404
pub fn get_mut (
420
405
& mut self ,
421
406
id : AllocId ,
@@ -429,8 +414,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
429
414
return err ! ( ModifiedConstantMemory ) ;
430
415
}
431
416
let kind = M :: STATIC_KIND . expect (
432
- "I got an owned allocation that I have to copy but the machine does \
433
- not expect that to happen"
417
+ "An allocation is being mutated but the machine does not expect that to happen"
434
418
) ;
435
419
Ok ( ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) )
436
420
} ) ;
@@ -448,6 +432,30 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
448
432
}
449
433
}
450
434
435
+ pub fn get_size_and_align ( & self , id : AllocId ) -> ( Size , Align ) {
436
+ if let Ok ( alloc) = self . get ( id) {
437
+ return ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ;
438
+ }
439
+ // Could also be a fn ptr or extern static
440
+ match self . tcx . alloc_map . lock ( ) . get ( id) {
441
+ Some ( AllocType :: Function ( ..) ) => ( Size :: ZERO , Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ,
442
+ Some ( AllocType :: Static ( did) ) => {
443
+ // The only way `get` couldn't have worked here is if this is an extern static
444
+ assert ! ( self . tcx. is_foreign_item( did) ) ;
445
+ // Use size and align of the type
446
+ let ty = self . tcx . type_of ( did) ;
447
+ let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
448
+ ( layout. size , layout. align )
449
+ }
450
+ _ => {
451
+ // Must be a deallocated pointer
452
+ * self . dead_alloc_map . get ( & id) . expect (
453
+ "allocation missing in dead_alloc_map"
454
+ )
455
+ }
456
+ }
457
+ }
458
+
451
459
pub fn get_fn ( & self , ptr : Pointer < M :: PointerTag > ) -> EvalResult < ' tcx , Instance < ' tcx > > {
452
460
if ptr. offset . bytes ( ) != 0 {
453
461
return err ! ( InvalidFunctionPointer ) ;
0 commit comments