@@ -492,13 +492,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
492
492
id : AllocId ,
493
493
liveness : AllocCheck ,
494
494
) -> InterpResult < ' static , ( Size , Align ) > {
495
- if let Ok ( alloc) = self . get ( id) {
495
+ // # Regular allocations
496
+ // Don't use `self.get` here as that will
497
+ // a) cause cycles in case `id` refers to a static
498
+ // b) duplicate a static's allocation in miri
499
+ if let Some ( ( _, alloc) ) = self . alloc_map . get ( id) {
496
500
return Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ;
497
501
}
498
- // can't do this in the match argument, we may get cycle errors since the lock would get
499
- // dropped after the match.
502
+
503
+ // # Statics and function pointers
504
+ // Can't do this in the match argument, we may get cycle errors since the lock would
505
+ // be held throughout the match.
500
506
let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
501
- // Could also be a fn ptr or extern static
502
507
match alloc {
503
508
Some ( GlobalAlloc :: Function ( ..) ) => {
504
509
if let AllocCheck :: Dereferencable = liveness {
@@ -507,28 +512,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
507
512
} else {
508
513
Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
509
514
}
510
- }
511
- // `self.get` would also work, but can cause cycles if a static refers to itself
515
+ } ,
512
516
Some ( GlobalAlloc :: Static ( did) ) => {
513
- // The only way `get` couldn't have worked here is if this is an extern static
514
- assert ! ( self . tcx. is_foreign_item( did) ) ;
515
- // Use size and align of the type
517
+ // Use size and align of the type.
516
518
let ty = self . tcx . type_of ( did) ;
517
519
let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
518
520
Ok ( ( layout. size , layout. align . abi ) )
519
- }
520
- _ => {
521
- if let Ok ( alloc) = self . get ( id) {
522
- Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) )
523
- }
524
- else if let AllocCheck :: MaybeDead = liveness {
525
- // Deallocated pointers are allowed, we should be able to find
526
- // them in the map.
527
- Ok ( * self . dead_alloc_map . get ( & id)
528
- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
529
- } else {
530
- err ! ( DanglingPointerDeref )
531
- }
521
+ } ,
522
+ Some ( GlobalAlloc :: Memory ( alloc) ) =>
523
+ // Need to duplicate the logic here, because the global allocations have
524
+ // different associated types than the interpreter-local ones.
525
+ Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
526
+ // The rest must be dead.
527
+ None => if let AllocCheck :: MaybeDead = liveness {
528
+ // Deallocated pointers are allowed, we should be able to find
529
+ // them in the map.
530
+ Ok ( * self . dead_alloc_map . get ( & id)
531
+ . expect ( "deallocated pointers should all be recorded in \
532
+ `dead_alloc_map`") )
533
+ } else {
534
+ err ! ( DanglingPointerDeref )
532
535
} ,
533
536
}
534
537
}
0 commit comments