@@ -27,12 +27,20 @@ use crate::ty;
27
27
28
28
/// Functionality required for the bytes of an `Allocation`.
29
29
pub 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
+
30
34
/// 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 ;
32
40
33
41
/// Create a zeroed `AllocBytes` of the specified size and alignment.
34
42
/// 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 > ;
36
44
37
45
/// Gives direct access to the raw underlying storage.
38
46
///
@@ -47,15 +55,20 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Targe
47
55
/// - other pointers returned by this method, and
48
56
/// - references returned from `deref()`, as long as there was no write.
49
57
fn as_ptr ( & self ) -> * const u8 ;
58
+
59
+ /// Gets the allocation metadata.
60
+ fn get_mdata ( & self ) -> Self :: ByteMetadata ;
50
61
}
51
62
52
63
/// Default `bytes` for `Allocation` is a `Box<u8>`.
53
64
impl 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 {
55
68
Box :: < [ u8 ] > :: from ( slice. into ( ) )
56
69
}
57
70
58
- fn zeroed ( size : Size , _align : Align ) -> Option < Self > {
71
+ fn zeroed ( size : Size , _align : Align , _dsc : ( ) ) -> Option < Self > {
59
72
let bytes = Box :: < [ u8 ] > :: try_new_zeroed_slice ( size. bytes ( ) . try_into ( ) . ok ( ) ?) . ok ( ) ?;
60
73
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
61
74
let bytes = unsafe { bytes. assume_init ( ) } ;
@@ -69,6 +82,8 @@ impl AllocBytes for Box<[u8]> {
69
82
fn as_ptr ( & self ) -> * const u8 {
70
83
Box :: as_ptr ( self ) . cast ( )
71
84
}
85
+
86
+ fn get_mdata ( & self ) -> ( ) { }
72
87
}
73
88
74
89
/// This type represents an Allocation in the Miri/CTFE core engine.
@@ -175,6 +190,7 @@ fn all_zero(buf: &[u8]) -> bool {
175
190
impl < Prov : Provenance , Extra , Bytes , E : Encoder > Encodable < E > for Allocation < Prov , Extra , Bytes >
176
191
where
177
192
Bytes : AllocBytes ,
193
+ Bytes :: ByteMetadata : Encodable < E > ,
178
194
ProvenanceMap < Prov > : Encodable < E > ,
179
195
Extra : Encodable < E > ,
180
196
{
@@ -186,6 +202,7 @@ where
186
202
if !all_zero {
187
203
encoder. emit_raw_bytes ( & self . bytes ) ;
188
204
}
205
+ self . bytes . get_mdata ( ) . encode ( encoder) ;
189
206
self . provenance . encode ( encoder) ;
190
207
self . init_mask . encode ( encoder) ;
191
208
self . extra . encode ( encoder) ;
@@ -195,6 +212,7 @@ where
195
212
impl < Prov : Provenance , Extra , Bytes , D : Decoder > Decodable < D > for Allocation < Prov , Extra , Bytes >
196
213
where
197
214
Bytes : AllocBytes ,
215
+ Bytes :: ByteMetadata : Decodable < D > ,
198
216
ProvenanceMap < Prov > : Decodable < D > ,
199
217
Extra : Decodable < D > ,
200
218
{
@@ -203,7 +221,9 @@ where
203
221
204
222
let len = decoder. read_usize ( ) ;
205
223
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) ;
207
227
208
228
let provenance = Decodable :: decode ( decoder) ;
209
229
let init_mask = Decodable :: decode ( decoder) ;
@@ -395,8 +415,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
395
415
slice : impl Into < Cow < ' a , [ u8 ] > > ,
396
416
align : Align ,
397
417
mutability : Mutability ,
418
+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
398
419
) -> Self {
399
- let bytes = Bytes :: from_bytes ( slice, align) ;
420
+ let bytes = Bytes :: from_bytes ( slice, align, dsc ) ;
400
421
let size = Size :: from_bytes ( bytes. len ( ) ) ;
401
422
Self {
402
423
bytes,
@@ -408,14 +429,18 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
408
429
}
409
430
}
410
431
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)
413
437
}
414
438
415
439
fn new_inner < R > (
416
440
size : Size ,
417
441
align : Align ,
418
442
init : AllocInit ,
443
+ dsc : <Bytes as AllocBytes >:: ByteMetadata ,
419
444
fail : impl FnOnce ( ) -> R ,
420
445
) -> Result < Self , R > {
421
446
// 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> {
424
449
// deterministic. However, we can be non-deterministic here because all uses of const
425
450
// evaluation (including ConstProp!) will make compilation fail (via hard error
426
451
// 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) ?;
428
453
429
454
Ok ( Allocation {
430
455
bytes,
@@ -444,8 +469,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
444
469
445
470
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
446
471
/// 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, || {
449
479
ty:: tls:: with ( |tcx| tcx. dcx ( ) . delayed_bug ( "exhausted memory during interpretation" ) ) ;
450
480
InterpErrorKind :: ResourceExhaustion ( ResourceExhaustionInfo :: MemoryExhausted )
451
481
} )
@@ -457,8 +487,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
457
487
///
458
488
/// Example use case: To obtain an Allocation filled with specific data,
459
489
/// 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, || {
462
497
panic ! (
463
498
"interpreter ran out of memory: cannot create allocation of {} bytes" ,
464
499
size. bytes( )
0 commit comments