@@ -37,6 +37,13 @@ pub trait AllocBytes:
37
37
/// Create a zeroed `AllocBytes` of the specified size and alignment.
38
38
/// Returns `None` if we ran out of memory on the host.
39
39
fn zeroed ( size : Size , _align : Align ) -> Option < Self > ;
40
+
41
+ /// Gives direct access to the raw underlying storage. Must be aligned according to the `align`
42
+ /// passed during construction.
43
+ ///
44
+ /// Crucially this pointer will *not* be invalidated by `deref`/`deref_mut` calls!
45
+ /// In Tree Borrows terms, this pointer is a parent of the references returned there.
46
+ fn get_bytes_unchecked_raw_mut ( & mut self ) -> * mut u8 ;
40
47
}
41
48
42
49
// Default `bytes` for `Allocation` is a `Box<[u8]>`.
@@ -51,6 +58,13 @@ impl AllocBytes for Box<[u8]> {
51
58
let bytes = unsafe { bytes. assume_init ( ) } ;
52
59
Some ( bytes)
53
60
}
61
+
62
+ fn get_bytes_unchecked_raw_mut ( & mut self ) -> * mut u8 {
63
+ // We didn't actually put the memory at the right alignment, so we can't support this.
64
+ // (That's okay, this function is only needed in Miri which implements this trait for its
65
+ // own type.)
66
+ panic ! ( "raw bytes access not supported" ) ;
67
+ }
54
68
}
55
69
56
70
/// This type represents an Allocation in the Miri/CTFE core engine.
@@ -399,10 +413,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
399
413
400
414
/// Byte accessors.
401
415
impl < Prov : Provenance , Extra , Bytes : AllocBytes > Allocation < Prov , Extra , Bytes > {
402
- pub fn base_addr ( & self ) -> * const u8 {
403
- self . bytes . as_ptr ( )
404
- }
405
-
406
416
/// This is the entirely abstraction-violating way to just grab the raw bytes without
407
417
/// caring about provenance or initialization.
408
418
///
@@ -452,13 +462,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
452
462
Ok ( self . get_bytes_unchecked ( range) )
453
463
}
454
464
455
- /// Just calling this already marks everything as defined and removes provenance,
456
- /// so be sure to actually put data there!
465
+ /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes.
466
+ /// Just calling this already marks everything as defined and removes provenance, so be sure to
467
+ /// actually overwrite all the data there!
457
468
///
458
469
/// It is the caller's responsibility to check bounds and alignment beforehand.
459
470
/// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods
460
471
/// on `InterpCx` instead.
461
- pub fn get_bytes_mut (
472
+ pub fn get_bytes_unchecked_for_overwrite (
462
473
& mut self ,
463
474
cx : & impl HasDataLayout ,
464
475
range : AllocRange ,
@@ -469,8 +480,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
469
480
Ok ( & mut self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ] )
470
481
}
471
482
472
- /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
473
- pub fn get_bytes_mut_ptr (
483
+ /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases
484
+ /// into this memory.
485
+ pub fn get_bytes_unchecked_for_overwrite_ptr (
474
486
& mut self ,
475
487
cx : & impl HasDataLayout ,
476
488
range : AllocRange ,
@@ -479,10 +491,20 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
479
491
self . provenance . clear ( range, cx) ?;
480
492
481
493
assert ! ( range. end( ) . bytes_usize( ) <= self . bytes. len( ) ) ; // need to do our own bounds-check
494
+ // FIXME: actually now that `self.bytes` is a `Box`, this *does* invalidate existing
495
+ // immutable aliases at least under Stacked Borrows...
482
496
let begin_ptr = self . bytes . as_mut_ptr ( ) . wrapping_add ( range. start . bytes_usize ( ) ) ;
483
497
let len = range. end ( ) . bytes_usize ( ) - range. start . bytes_usize ( ) ;
484
498
Ok ( ptr:: slice_from_raw_parts_mut ( begin_ptr, len) )
485
499
}
500
+
501
+ /// This gives direct mutable access to the entire buffer, just exposing their internal state
502
+ /// without reseting anything. Directly exposes the `AllocBytes` method of the same name. Only
503
+ /// works if `OFFSET_IS_ADDR` is true.
504
+ pub fn get_bytes_unchecked_raw_mut ( & mut self ) -> * mut u8 {
505
+ assert ! ( Prov :: OFFSET_IS_ADDR ) ;
506
+ self . bytes . get_bytes_unchecked_raw_mut ( )
507
+ }
486
508
}
487
509
488
510
/// Reading and writing.
@@ -589,7 +611,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
589
611
} ;
590
612
591
613
let endian = cx. data_layout ( ) . endian ;
592
- let dst = self . get_bytes_mut ( cx, range) ?;
614
+ // Yes we do overwrite all the bytes in `dst`.
615
+ let dst = self . get_bytes_unchecked_for_overwrite ( cx, range) ?;
593
616
write_target_uint ( endian, dst, bytes) . unwrap ( ) ;
594
617
595
618
// See if we have to also store some provenance.
0 commit comments