@@ -197,9 +197,7 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>(
197197 tcx : TyCtxt < ' tcx > ,
198198 alloc_id : AllocId ,
199199) -> Result < ( ) , E :: Error > {
200- let alloc: GlobalAlloc < ' tcx > =
201- tcx. alloc_map . lock ( ) . get ( alloc_id) . expect ( "no value for given alloc ID" ) ;
202- match alloc {
200+ match tcx. global_alloc ( alloc_id) {
203201 GlobalAlloc :: Memory ( alloc) => {
204202 trace ! ( "encoding {:?} with {:#?}" , alloc_id, alloc) ;
205203 AllocDiscriminant :: Alloc . encode ( encoder) ?;
@@ -294,7 +292,7 @@ impl<'s> AllocDecodingSession<'s> {
294292 AllocDiscriminant :: Alloc => {
295293 // If this is an allocation, we need to reserve an
296294 // `AllocId` so we can decode cyclic graphs.
297- let alloc_id = decoder. tcx ( ) . alloc_map . lock ( ) . reserve ( ) ;
295+ let alloc_id = decoder. tcx ( ) . reserve_alloc_id ( ) ;
298296 * entry =
299297 State :: InProgress ( TinyList :: new_single ( self . session_id ) , alloc_id) ;
300298 Some ( alloc_id)
@@ -338,23 +336,23 @@ impl<'s> AllocDecodingSession<'s> {
338336 // We already have a reserved `AllocId`.
339337 let alloc_id = alloc_id. unwrap ( ) ;
340338 trace ! ( "decoded alloc {:?}: {:#?}" , alloc_id, alloc) ;
341- decoder. tcx ( ) . alloc_map . lock ( ) . set_alloc_id_same_memory ( alloc_id, alloc) ;
339+ decoder. tcx ( ) . set_alloc_id_same_memory ( alloc_id, alloc) ;
342340 Ok ( alloc_id)
343341 }
344342 AllocDiscriminant :: Fn => {
345343 assert ! ( alloc_id. is_none( ) ) ;
346344 trace ! ( "creating fn alloc ID" ) ;
347345 let instance = ty:: Instance :: decode ( decoder) ?;
348346 trace ! ( "decoded fn alloc instance: {:?}" , instance) ;
349- let alloc_id = decoder. tcx ( ) . alloc_map . lock ( ) . create_fn_alloc ( instance) ;
347+ let alloc_id = decoder. tcx ( ) . create_fn_alloc ( instance) ;
350348 Ok ( alloc_id)
351349 }
352350 AllocDiscriminant :: Static => {
353351 assert ! ( alloc_id. is_none( ) ) ;
354352 trace ! ( "creating extern static alloc ID" ) ;
355353 let did = DefId :: decode ( decoder) ?;
356354 trace ! ( "decoded static def-ID: {:?}" , did) ;
357- let alloc_id = decoder. tcx ( ) . alloc_map . lock ( ) . create_static_alloc ( did) ;
355+ let alloc_id = decoder. tcx ( ) . create_static_alloc ( did) ;
358356 Ok ( alloc_id)
359357 }
360358 }
@@ -381,7 +379,29 @@ pub enum GlobalAlloc<'tcx> {
381379 Memory ( & ' tcx Allocation ) ,
382380}
383381
384- pub struct AllocMap < ' tcx > {
382+ impl GlobalAlloc < ' tcx > {
383+ /// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory`
384+ #[ track_caller]
385+ #[ inline]
386+ pub fn unwrap_memory ( & self ) -> & ' tcx Allocation {
387+ match * self {
388+ GlobalAlloc :: Memory ( mem) => mem,
389+ _ => bug ! ( "expected memory, got {:?}" , self ) ,
390+ }
391+ }
392+
393+ /// Panics if the `GlobalAlloc` is not `GlobalAlloc::Function`
394+ #[ track_caller]
395+ #[ inline]
396+ pub fn unwrap_fn ( & self ) -> Instance < ' tcx > {
397+ match * self {
398+ GlobalAlloc :: Function ( instance) => instance,
399+ _ => bug ! ( "expected function, got {:?}" , self ) ,
400+ }
401+ }
402+ }
403+
404+ crate struct AllocMap < ' tcx > {
385405 /// Maps `AllocId`s to their corresponding allocations.
386406 alloc_map : FxHashMap < AllocId , GlobalAlloc < ' tcx > > ,
387407
@@ -397,16 +417,10 @@ pub struct AllocMap<'tcx> {
397417}
398418
399419impl < ' tcx > AllocMap < ' tcx > {
400- pub fn new ( ) -> Self {
420+ crate fn new ( ) -> Self {
401421 AllocMap { alloc_map : Default :: default ( ) , dedup : Default :: default ( ) , next_id : AllocId ( 0 ) }
402422 }
403-
404- /// Obtains a new allocation ID that can be referenced but does not
405- /// yet have an allocation backing it.
406- ///
407- /// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
408- /// an `AllocId` from a query.
409- pub fn reserve ( & mut self ) -> AllocId {
423+ fn reserve ( & mut self ) -> AllocId {
410424 let next = self . next_id ;
411425 self . next_id . 0 = self . next_id . 0 . checked_add ( 1 ) . expect (
412426 "You overflowed a u64 by incrementing by 1... \
@@ -415,34 +429,46 @@ impl<'tcx> AllocMap<'tcx> {
415429 ) ;
416430 next
417431 }
432+ }
433+
434+ impl < ' tcx > TyCtxt < ' tcx > {
435+ /// Obtains a new allocation ID that can be referenced but does not
436+ /// yet have an allocation backing it.
437+ ///
438+ /// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
439+ /// an `AllocId` from a query.
440+ pub fn reserve_alloc_id ( & self ) -> AllocId {
441+ self . alloc_map . lock ( ) . reserve ( )
442+ }
418443
419444 /// Reserves a new ID *if* this allocation has not been dedup-reserved before.
420445 /// Should only be used for function pointers and statics, we don't want
421446 /// to dedup IDs for "real" memory!
422- fn reserve_and_set_dedup ( & mut self , alloc : GlobalAlloc < ' tcx > ) -> AllocId {
447+ fn reserve_and_set_dedup ( & self , alloc : GlobalAlloc < ' tcx > ) -> AllocId {
448+ let mut alloc_map = self . alloc_map . lock ( ) ;
423449 match alloc {
424450 GlobalAlloc :: Function ( ..) | GlobalAlloc :: Static ( ..) => { }
425451 GlobalAlloc :: Memory ( ..) => bug ! ( "Trying to dedup-reserve memory with real data!" ) ,
426452 }
427- if let Some ( & alloc_id) = self . dedup . get ( & alloc) {
453+ if let Some ( & alloc_id) = alloc_map . dedup . get ( & alloc) {
428454 return alloc_id;
429455 }
430- let id = self . reserve ( ) ;
456+ let id = alloc_map . reserve ( ) ;
431457 debug ! ( "creating alloc {:?} with id {}" , alloc, id) ;
432- self . alloc_map . insert ( id, alloc. clone ( ) ) ;
433- self . dedup . insert ( alloc, id) ;
458+ alloc_map . alloc_map . insert ( id, alloc. clone ( ) ) ;
459+ alloc_map . dedup . insert ( alloc, id) ;
434460 id
435461 }
436462
437463 /// Generates an `AllocId` for a static or return a cached one in case this function has been
438464 /// called on the same static before.
439- pub fn create_static_alloc ( & mut self , static_id : DefId ) -> AllocId {
465+ pub fn create_static_alloc ( & self , static_id : DefId ) -> AllocId {
440466 self . reserve_and_set_dedup ( GlobalAlloc :: Static ( static_id) )
441467 }
442468
443469 /// Generates an `AllocId` for a function. Depending on the function type,
444470 /// this might get deduplicated or assigned a new ID each time.
445- pub fn create_fn_alloc ( & mut self , instance : Instance < ' tcx > ) -> AllocId {
471+ pub fn create_fn_alloc ( & self , instance : Instance < ' tcx > ) -> AllocId {
446472 // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
447473 // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
448474 // duplicated across crates.
@@ -456,8 +482,9 @@ impl<'tcx> AllocMap<'tcx> {
456482 } ) ;
457483 if is_generic {
458484 // Get a fresh ID.
459- let id = self . reserve ( ) ;
460- self . alloc_map . insert ( id, GlobalAlloc :: Function ( instance) ) ;
485+ let mut alloc_map = self . alloc_map . lock ( ) ;
486+ let id = alloc_map. reserve ( ) ;
487+ alloc_map. alloc_map . insert ( id, GlobalAlloc :: Function ( instance) ) ;
461488 id
462489 } else {
463490 // Deduplicate.
@@ -470,8 +497,8 @@ impl<'tcx> AllocMap<'tcx> {
470497 /// Statics with identical content will still point to the same `Allocation`, i.e.,
471498 /// their data will be deduplicated through `Allocation` interning -- but they
472499 /// are different places in memory and as such need different IDs.
473- pub fn create_memory_alloc ( & mut self , mem : & ' tcx Allocation ) -> AllocId {
474- let id = self . reserve ( ) ;
500+ pub fn create_memory_alloc ( & self , mem : & ' tcx Allocation ) -> AllocId {
501+ let id = self . reserve_alloc_id ( ) ;
475502 self . set_alloc_id_memory ( id, mem) ;
476503 id
477504 }
@@ -482,38 +509,35 @@ impl<'tcx> AllocMap<'tcx> {
482509 /// This function exists to allow const eval to detect the difference between evaluation-
483510 /// local dangling pointers and allocations in constants/statics.
484511 #[ inline]
485- pub fn get ( & self , id : AllocId ) -> Option < GlobalAlloc < ' tcx > > {
486- self . alloc_map . get ( & id) . cloned ( )
487- }
488-
489- /// Panics if the `AllocId` does not refer to an `Allocation`
490- pub fn unwrap_memory ( & self , id : AllocId ) -> & ' tcx Allocation {
491- match self . get ( id) {
492- Some ( GlobalAlloc :: Memory ( mem) ) => mem,
493- _ => bug ! ( "expected allocation ID {} to point to memory" , id) ,
494- }
512+ pub fn get_global_alloc ( & self , id : AllocId ) -> Option < GlobalAlloc < ' tcx > > {
513+ self . alloc_map . lock ( ) . alloc_map . get ( & id) . cloned ( )
495514 }
496515
497- /// Panics if the `AllocId` does not refer to a function
498- pub fn unwrap_fn ( & self , id : AllocId ) -> Instance < ' tcx > {
499- match self . get ( id) {
500- Some ( GlobalAlloc :: Function ( instance) ) => instance,
501- _ => bug ! ( "expected allocation ID {} to point to a function" , id) ,
516+ #[ inline]
517+ #[ track_caller]
518+ /// Panics in case the `AllocId` is dangling. Since that is impossible for `AllocId`s in
519+ /// constants (as all constants must pass interning and validation that check for dangling
520+ /// ids), this function is frequently used throughout rustc, but should not be used within
521+ /// the miri engine.
522+ pub fn global_alloc ( & self , id : AllocId ) -> GlobalAlloc < ' tcx > {
523+ match self . get_global_alloc ( id) {
524+ Some ( alloc) => alloc,
525+ None => bug ! ( "could not find allocation for {}" , id) ,
502526 }
503527 }
504528
505529 /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
506530 /// call this function twice, even with the same `Allocation` will ICE the compiler.
507- pub fn set_alloc_id_memory ( & mut self , id : AllocId , mem : & ' tcx Allocation ) {
508- if let Some ( old) = self . alloc_map . insert ( id, GlobalAlloc :: Memory ( mem) ) {
531+ pub fn set_alloc_id_memory ( & self , id : AllocId , mem : & ' tcx Allocation ) {
532+ if let Some ( old) = self . alloc_map . lock ( ) . alloc_map . insert ( id, GlobalAlloc :: Memory ( mem) ) {
509533 bug ! ( "tried to set allocation ID {}, but it was already existing as {:#?}" , id, old) ;
510534 }
511535 }
512536
513537 /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
514538 /// twice for the same `(AllocId, Allocation)` pair.
515- fn set_alloc_id_same_memory ( & mut self , id : AllocId , mem : & ' tcx Allocation ) {
516- self . alloc_map . insert_same ( id, GlobalAlloc :: Memory ( mem) ) ;
539+ fn set_alloc_id_same_memory ( & self , id : AllocId , mem : & ' tcx Allocation ) {
540+ self . alloc_map . lock ( ) . alloc_map . insert_same ( id, GlobalAlloc :: Memory ( mem) ) ;
517541 }
518542}
519543
0 commit comments