@@ -27,12 +27,20 @@ use crate::ty;
2727
2828/// Functionality required for the bytes of an `Allocation`.
2929pub trait AllocBytes : Clone + fmt:: Debug + Deref < Target = [ u8 ] > + DerefMut < Target = [ u8 ] > {
30+ /// Used for giving extra metadata on creation. Miri uses this to allow
31+ /// machine memory to be allocated separately from other allocations.
32+ type ByteMetadata : Clone + fmt:: Debug ;
33+
3034 /// Create an `AllocBytes` from a slice of `u8`.
31- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , _align : Align ) -> Self ;
35+ fn from_bytes < ' a > (
36+ slice : impl Into < Cow < ' a , [ u8 ] > > ,
37+ _align : Align ,
38+ _dsc : Self :: ByteMetadata ,
39+ ) -> Self ;
3240
3341 /// Create a zeroed `AllocBytes` of the specified size and alignment.
3442 /// Returns `None` if we ran out of memory on the host.
35- fn zeroed ( size : Size , _align : Align ) -> Option < Self > ;
43+ fn zeroed ( size : Size , _align : Align , _dsc : Self :: ByteMetadata ) -> Option < Self > ;
3644
3745 /// Gives direct access to the raw underlying storage.
3846 ///
@@ -47,15 +55,20 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Targe
4755 /// - other pointers returned by this method, and
4856 /// - references returned from `deref()`, as long as there was no write.
4957 fn as_ptr ( & self ) -> * const u8 ;
58+
59+ /// Gets the allocation metadata.
60+ fn get_mdata ( & self ) -> Self :: ByteMetadata ;
5061}
5162
5263/// Default `bytes` for `Allocation` is a `Box<u8>`.
5364impl AllocBytes for Box < [ u8 ] > {
54- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , _align : Align ) -> Self {
65+ type ByteMetadata = ( ) ;
66+
67+ fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , _align : Align , _dsc : ( ) ) -> Self {
5568 Box :: < [ u8 ] > :: from ( slice. into ( ) )
5669 }
5770
58- fn zeroed ( size : Size , _align : Align ) -> Option < Self > {
71+ fn zeroed ( size : Size , _align : Align , _dsc : ( ) ) -> Option < Self > {
5972 let bytes = Box :: < [ u8 ] > :: try_new_zeroed_slice ( size. bytes ( ) . try_into ( ) . ok ( ) ?) . ok ( ) ?;
6073 // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
6174 let bytes = unsafe { bytes. assume_init ( ) } ;
@@ -69,6 +82,8 @@ impl AllocBytes for Box<[u8]> {
6982 fn as_ptr ( & self ) -> * const u8 {
7083 Box :: as_ptr ( self ) . cast ( )
7184 }
85+
86+ fn get_mdata ( & self ) -> ( ) { }
7287}
7388
7489/// This type represents an Allocation in the Miri/CTFE core engine.
@@ -175,6 +190,7 @@ fn all_zero(buf: &[u8]) -> bool {
175190impl < Prov : Provenance , Extra , Bytes , E : Encoder > Encodable < E > for Allocation < Prov , Extra , Bytes >
176191where
177192 Bytes : AllocBytes ,
193+ Bytes :: ByteMetadata : Encodable < E > ,
178194 ProvenanceMap < Prov > : Encodable < E > ,
179195 Extra : Encodable < E > ,
180196{
@@ -186,6 +202,7 @@ where
186202 if !all_zero {
187203 encoder. emit_raw_bytes ( & self . bytes ) ;
188204 }
205+ self . bytes . get_mdata ( ) . encode ( encoder) ;
189206 self . provenance . encode ( encoder) ;
190207 self . init_mask . encode ( encoder) ;
191208 self . extra . encode ( encoder) ;
@@ -195,6 +212,7 @@ where
195212impl < Prov : Provenance , Extra , Bytes , D : Decoder > Decodable < D > for Allocation < Prov , Extra , Bytes >
196213where
197214 Bytes : AllocBytes ,
215+ Bytes :: ByteMetadata : Decodable < D > ,
198216 ProvenanceMap < Prov > : Decodable < D > ,
199217 Extra : Decodable < D > ,
200218{
@@ -203,7 +221,9 @@ where
203221
204222 let len = decoder. read_usize ( ) ;
205223 let bytes = if all_zero { vec ! [ 0u8 ; len] } else { decoder. read_raw_bytes ( len) . to_vec ( ) } ;
206- let bytes = Bytes :: from_bytes ( bytes, align) ;
224+
225+ let mdata = Decodable :: decode ( decoder) ;
226+ let bytes = Bytes :: from_bytes ( bytes, align, mdata) ;
207227
208228 let provenance = Decodable :: decode ( decoder) ;
209229 let init_mask = Decodable :: decode ( decoder) ;
@@ -395,8 +415,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
395415 slice : impl Into < Cow < ' a , [ u8 ] > > ,
396416 align : Align ,
397417 mutability : Mutability ,
418+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
398419 ) -> Self {
399- let bytes = Bytes :: from_bytes ( slice, align) ;
420+ let bytes = Bytes :: from_bytes ( slice, align, dsc ) ;
400421 let size = Size :: from_bytes ( bytes. len ( ) ) ;
401422 Self {
402423 bytes,
@@ -408,14 +429,18 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
408429 }
409430 }
410431
411- pub fn from_bytes_byte_aligned_immutable < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > ) -> Self {
412- Allocation :: from_bytes ( slice, Align :: ONE , Mutability :: Not )
432+ pub fn from_bytes_byte_aligned_immutable < ' a > (
433+ slice : impl Into < Cow < ' a , [ u8 ] > > ,
434+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
435+ ) -> Self {
436+ Allocation :: from_bytes ( slice, Align :: ONE , Mutability :: Not , dsc)
413437 }
414438
415439 fn new_inner < R > (
416440 size : Size ,
417441 align : Align ,
418442 init : AllocInit ,
443+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
419444 fail : impl FnOnce ( ) -> R ,
420445 ) -> Result < Self , R > {
421446 // We raise an error if we cannot create the allocation on the host.
@@ -424,7 +449,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
424449 // deterministic. However, we can be non-deterministic here because all uses of const
425450 // evaluation (including ConstProp!) will make compilation fail (via hard error
426451 // or ICE) upon encountering a `MemoryExhausted` error.
427- let bytes = Bytes :: zeroed ( size, align) . ok_or_else ( fail) ?;
452+ let bytes = Bytes :: zeroed ( size, align, dsc ) . ok_or_else ( fail) ?;
428453
429454 Ok ( Allocation {
430455 bytes,
@@ -444,8 +469,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
444469
445470 /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
446471 /// available to the compiler to do so.
447- pub fn try_new < ' tcx > ( size : Size , align : Align , init : AllocInit ) -> InterpResult < ' tcx , Self > {
448- Self :: new_inner ( size, align, init, || {
472+ pub fn try_new < ' tcx > (
473+ size : Size ,
474+ align : Align ,
475+ init : AllocInit ,
476+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
477+ ) -> InterpResult < ' tcx , Self > {
478+ Self :: new_inner ( size, align, init, dsc, || {
449479 ty:: tls:: with ( |tcx| tcx. dcx ( ) . delayed_bug ( "exhausted memory during interpretation" ) ) ;
450480 InterpErrorKind :: ResourceExhaustion ( ResourceExhaustionInfo :: MemoryExhausted )
451481 } )
@@ -457,8 +487,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
457487 ///
458488 /// Example use case: To obtain an Allocation filled with specific data,
459489 /// first call this function and then call write_scalar to fill in the right data.
460- pub fn new ( size : Size , align : Align , init : AllocInit ) -> Self {
461- match Self :: new_inner ( size, align, init, || {
490+ pub fn new (
491+ size : Size ,
492+ align : Align ,
493+ init : AllocInit ,
494+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
495+ ) -> Self {
496+ match Self :: new_inner ( size, align, init, dsc, || {
462497 panic ! (
463498 "interpreter ran out of memory: cannot create allocation of {} bytes" ,
464499 size. bytes( )
0 commit comments