diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 9a26ac04b85a3..9d0c490822561 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -630,6 +630,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } + /// Gives raw, immutable access to the `Allocation` address, without bounds or alignment checks. + /// The caller is responsible for calling the access hooks! + pub fn get_alloc_bytes_unchecked_raw(&self, id: AllocId) -> InterpResult<'tcx, *const u8> { + let alloc = self.get_alloc_raw(id)?; + Ok(alloc.get_bytes_unchecked_raw()) + } + /// Bounds-checked *but not align-checked* allocation access. pub fn get_ptr_alloc<'a>( &'a self, @@ -713,6 +720,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok((alloc, &mut self.machine)) } + /// Gives raw, mutable access to the `Allocation` address, without bounds or alignment checks. + /// The caller is responsible for calling the access hooks! + pub fn get_alloc_bytes_unchecked_raw_mut( + &mut self, + id: AllocId, + ) -> InterpResult<'tcx, *mut u8> { + let alloc = self.get_alloc_raw_mut(id)?.0; + Ok(alloc.get_bytes_unchecked_raw_mut()) + } + /// Bounds-checked *but not align-checked* allocation access. pub fn get_ptr_alloc_mut<'a>( &'a mut self, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 2fc466c0e7e91..cac3bf948a0c1 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -40,9 +40,16 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref + DerefMut *mut u8; + + /// Gives direct access to the raw underlying storage. + /// + /// Crucially this pointer is compatible with: + /// - other pointers returned by this method, and + /// - references returned from `deref()`, as long as there was no write. + fn as_ptr(&self) -> *const u8; } /// Default `bytes` for `Allocation` is a `Box`. @@ -62,6 +69,11 @@ impl AllocBytes for Box<[u8]> { // Carefully avoiding any intermediate references. ptr::addr_of_mut!(**self).cast() } + + fn as_ptr(&self) -> *const u8 { + // Carefully avoiding any intermediate references. + ptr::addr_of!(**self).cast() + } } /// This type represents an Allocation in the Miri/CTFE core engine. @@ -490,19 +502,27 @@ impl Allocation self.provenance.clear(range, cx)?; assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check - // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. + // Crucially, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); let len = range.end().bytes_usize() - range.start.bytes_usize(); Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len)) } /// This gives direct mutable access to the entire buffer, just exposing their internal state - /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if + /// without resetting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if /// `OFFSET_IS_ADDR` is true. pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 { assert!(Prov::OFFSET_IS_ADDR); self.bytes.as_mut_ptr() } + + /// This gives direct immutable access to the entire buffer, just exposing their internal state + /// without resetting anything. Directly exposes `AllocBytes::as_ptr`. Only works if + /// `OFFSET_IS_ADDR` is true. + pub fn get_bytes_unchecked_raw(&self) -> *const u8 { + assert!(Prov::OFFSET_IS_ADDR); + self.bytes.as_ptr() + } } /// Reading and writing. diff --git a/src/tools/miri/src/alloc_bytes.rs b/src/tools/miri/src/alloc_bytes.rs index 97841a05cdebf..8f691456a596d 100644 --- a/src/tools/miri/src/alloc_bytes.rs +++ b/src/tools/miri/src/alloc_bytes.rs @@ -108,4 +108,8 @@ impl AllocBytes for MiriAllocBytes { fn as_mut_ptr(&mut self) -> *mut u8 { self.ptr } + + fn as_ptr(&self) -> *const u8 { + self.ptr + } }