@@ -37,9 +37,16 @@ pub trait AllocBytes:
3737    /// Create a zeroed `AllocBytes` of the specified size and alignment. 
3838     /// Returns `None` if we ran out of memory on the host. 
3939     fn  zeroed ( size :  Size ,  _align :  Align )  -> Option < Self > ; 
40+ 
41+     /// Gives direct access to the raw underlying storage. 
42+      /// 
43+      /// Crucially this pointer is compatible with: 
44+      /// - other pointers retunred by this method, and 
45+      /// - references returned from `deref()`, as long as there was no write. 
46+      fn  as_mut_ptr ( & mut  self )  -> * mut  u8 ; 
4047} 
4148
42- // Default `bytes` for `Allocation` is a `Box<[u8] >`. 
49+ ///  Default `bytes` for `Allocation` is a `Box<u8 >`. 
4350impl  AllocBytes  for  Box < [ u8 ] >  { 
4451    fn  from_bytes < ' a > ( slice :  impl  Into < Cow < ' a ,  [ u8 ] > > ,  _align :  Align )  -> Self  { 
4552        Box :: < [ u8 ] > :: from ( slice. into ( ) ) 
@@ -51,6 +58,11 @@ impl AllocBytes for Box<[u8]> {
5158        let  bytes = unsafe  {  bytes. assume_init ( )  } ; 
5259        Some ( bytes) 
5360    } 
61+ 
62+     fn  as_mut_ptr ( & mut  self )  -> * mut  u8  { 
63+         // Carefully avoiding any intermediate references. 
64+         ptr:: addr_of_mut!( * * self ) . cast ( ) 
65+     } 
5466} 
5567
5668/// This type represents an Allocation in the Miri/CTFE core engine. 
@@ -399,10 +411,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
399411
400412/// Byte accessors. 
401413impl < Prov :  Provenance ,  Extra ,  Bytes :  AllocBytes >  Allocation < Prov ,  Extra ,  Bytes >  { 
402-     pub  fn  base_addr ( & self )  -> * const  u8  { 
403-         self . bytes . as_ptr ( ) 
404-     } 
405- 
406414    /// This is the entirely abstraction-violating way to just grab the raw bytes without 
407415     /// caring about provenance or initialization. 
408416     /// 
@@ -452,13 +460,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
452460        Ok ( self . get_bytes_unchecked ( range) ) 
453461    } 
454462
455-     /// Just calling this already marks everything as defined and removes provenance, 
456-      /// so be sure to actually put data there! 
463+     /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes. 
464+      /// Just calling this already marks everything as defined and removes provenance, so be sure to 
465+      /// actually overwrite all the data there! 
457466     /// 
458467     /// It is the caller's responsibility to check bounds and alignment beforehand. 
459468     /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods 
460469     /// on `InterpCx` instead. 
461-      pub  fn  get_bytes_mut ( 
470+      pub  fn  get_bytes_unchecked_for_overwrite ( 
462471        & mut  self , 
463472        cx :  & impl  HasDataLayout , 
464473        range :  AllocRange , 
@@ -469,8 +478,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
469478        Ok ( & mut  self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ] ) 
470479    } 
471480
472-     /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. 
473-      pub  fn  get_bytes_mut_ptr ( 
481+     /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases 
482+      /// into this memory. 
483+      pub  fn  get_bytes_unchecked_for_overwrite_ptr ( 
474484        & mut  self , 
475485        cx :  & impl  HasDataLayout , 
476486        range :  AllocRange , 
@@ -479,10 +489,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
479489        self . provenance . clear ( range,  cx) ?; 
480490
481491        assert ! ( range. end( ) . bytes_usize( )  <= self . bytes. len( ) ) ;  // need to do our own bounds-check 
492+         // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. 
482493        let  begin_ptr = self . bytes . as_mut_ptr ( ) . wrapping_add ( range. start . bytes_usize ( ) ) ; 
483494        let  len = range. end ( ) . bytes_usize ( )  - range. start . bytes_usize ( ) ; 
484495        Ok ( ptr:: slice_from_raw_parts_mut ( begin_ptr,  len) ) 
485496    } 
497+ 
498+     /// This gives direct mutable access to the entire buffer, just exposing their internal state 
499+      /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if 
500+      /// `OFFSET_IS_ADDR` is true. 
501+      pub  fn  get_bytes_unchecked_raw_mut ( & mut  self )  -> * mut  u8  { 
502+         assert ! ( Prov :: OFFSET_IS_ADDR ) ; 
503+         self . bytes . as_mut_ptr ( ) 
504+     } 
486505} 
487506
488507/// Reading and writing. 
@@ -589,7 +608,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
589608        } ; 
590609
591610        let  endian = cx. data_layout ( ) . endian ; 
592-         let  dst = self . get_bytes_mut ( cx,  range) ?; 
611+         // Yes we do overwrite all the bytes in `dst`. 
612+         let  dst = self . get_bytes_unchecked_for_overwrite ( cx,  range) ?; 
593613        write_target_uint ( endian,  dst,  bytes) . unwrap ( ) ; 
594614
595615        // See if we have to also store some provenance. 
0 commit comments