Struct rustc_const_eval::interpret::Memory
source · [−]pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub(super) alloc_map: M::MemoryMap,
extra_fn_ptr_map: FxHashMap<AllocId, M::ExtraFnVal>,
pub(super) dead_alloc_map: FxHashMap<AllocId, (Size, Align)>,
pub extra: M::MemoryExtra,
pub tcx: TyCtxt<'tcx>,
}Fields
alloc_map: M::MemoryMapAllocations local to this instance of the miri engine. The kind
helps ensure that the same mechanism is used for allocation and
deallocation. When an allocation is not found here, it is a
global and looked up in the tcx for read access. Some machines may
have to mutate this map even on a read-only access to a global (because
they do pointer provenance tracking and the allocations in tcx have
the wrong type), so we let the machine override this type.
Either way, if the machine allows writing to a global, doing so will
create a copy of the global allocation here.
extra_fn_ptr_map: FxHashMap<AllocId, M::ExtraFnVal>Map for “extra” function pointers.
dead_alloc_map: FxHashMap<AllocId, (Size, Align)>To be able to compare pointers with null, and to check alignment for accesses to ZSTs (where pointers may dangle), we keep track of the size even for allocations that do not exist any more.
extra: M::MemoryExtraExtra data added by the machine.
tcx: TyCtxt<'tcx>Lets us implement HasDataLayout, which is awfully convenient.
Implementations
sourceimpl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self
sourcepub fn global_base_pointer(
&self,
ptr: Pointer<AllocId>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>
pub fn global_base_pointer(
&self,
ptr: Pointer<AllocId>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>
Call this to turn untagged “global” pointers (obtained via tcx) into
the machine pointer to the allocation. Must never be used
for any other pointers, nor for TLS statics.
Using the resulting pointer represents a direct access to that memory
(e.g. by directly using a static),
as opposed to access through a pointer that was created by the program.
This function can fail only if ptr points to an extern static.
pub fn create_fn_alloc(
&mut self,
fn_val: FnVal<'tcx, M::ExtraFnVal>
) -> Pointer<M::PointerTag>
pub fn allocate(
&mut self,
size: Size,
align: Align,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'static, Pointer<M::PointerTag>>
pub fn allocate_bytes(
&mut self,
bytes: &[u8],
align: Align,
kind: MemoryKind<M::MemoryKind>,
mutability: Mutability
) -> Pointer<M::PointerTag>
pub fn allocate_with(
&mut self,
alloc: Allocation,
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>
pub fn reallocate(
&mut self,
ptr: Pointer<Option<M::PointerTag>>,
old_size_and_align: Option<(Size, Align)>,
new_size: Size,
new_align: Align,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>
pub fn deallocate(
&mut self,
ptr: Pointer<Option<M::PointerTag>>,
old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'tcx>
sourcefn get_ptr_access(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>>
fn get_ptr_access(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>>
Internal helper function to determine the allocation and offset of a pointer (if any).
sourcepub fn check_ptr_access_align(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align,
msg: CheckInAllocMsg
) -> InterpResult<'tcx>
pub fn check_ptr_access_align(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align,
msg: CheckInAllocMsg
) -> InterpResult<'tcx>
Check if the given pointer points to live memory of given size and align
(ignoring M::enforce_alignment). The caller can control the error message for the
out-of-bounds case.
sourcefn check_and_deref_ptr<T>(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Option<Align>,
msg: CheckInAllocMsg,
alloc_size: impl FnOnce(AllocId, Size, Pointer<M::PointerTag>) -> InterpResult<'tcx, (Size, Align, T)>
) -> InterpResult<'tcx, Option<T>>
fn check_and_deref_ptr<T>(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Option<Align>,
msg: CheckInAllocMsg,
alloc_size: impl FnOnce(AllocId, Size, Pointer<M::PointerTag>) -> InterpResult<'tcx, (Size, Align, T)>
) -> InterpResult<'tcx, Option<T>>
Low-level helper function to check if a ptr is in-bounds and potentially return a reference
to the allocation it points to. Supports both shared and mutable references, as the actual
checking is offloaded to a helper closure. align defines whether and which alignment check
is done. Returns None for size 0, and otherwise Some of what alloc_size returned.
sourcepub fn ptr_may_be_null(&self, ptr: Pointer<Option<M::PointerTag>>) -> bool
pub fn ptr_may_be_null(&self, ptr: Pointer<Option<M::PointerTag>>) -> bool
Test if the pointer might be null.
sourceimpl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
Allocation accessors
sourcefn get_global_alloc(
&self,
id: AllocId,
is_write: bool
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>>
fn get_global_alloc(
&self,
id: AllocId,
is_write: bool
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>>
Helper function to obtain a global (tcx) allocation.
This attempts to return a reference to an existing allocation if
one can be found in tcx. That, however, is only possible if tcx and
this machine use the same pointer tag, so it is indirected through
M::tag_allocation.
sourcefn get_raw(
&self,
id: AllocId
) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>>
fn get_raw(
&self,
id: AllocId
) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>>
Gives raw access to the Allocation, without bounds or alignment checks.
The caller is responsible for calling the access hooks!
sourcepub fn get<'a>(
&'a self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::PointerTag, M::AllocExtra>>>
pub fn get<'a>(
&'a self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::PointerTag, M::AllocExtra>>>
“Safe” (bounds and align-checked) allocation access.
sourcepub fn get_alloc_extra<'a>(
&'a self,
id: AllocId
) -> InterpResult<'tcx, &'a M::AllocExtra>
pub fn get_alloc_extra<'a>(
&'a self,
id: AllocId
) -> InterpResult<'tcx, &'a M::AllocExtra>
Return the extra field of the given allocation.
sourcefn get_raw_mut(
&mut self,
id: AllocId
) -> InterpResult<'tcx, (&mut Allocation<M::PointerTag, M::AllocExtra>, &mut M::MemoryExtra)>
fn get_raw_mut(
&mut self,
id: AllocId
) -> InterpResult<'tcx, (&mut Allocation<M::PointerTag, M::AllocExtra>, &mut M::MemoryExtra)>
Gives raw mutable access to the Allocation, without bounds or alignment checks.
The caller is responsible for calling the access hooks!
Also returns a ptr to self.extra so that the caller can use it in parallel with the
allocation.
sourcepub fn get_mut<'a>(
&'a mut self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>>
pub fn get_mut<'a>(
&'a mut self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>>
“Safe” (bounds and align-checked) allocation access.
sourcepub fn get_alloc_extra_mut<'a>(
&'a mut self,
id: AllocId
) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M::MemoryExtra)>
pub fn get_alloc_extra_mut<'a>(
&'a mut self,
id: AllocId
) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M::MemoryExtra)>
Return the extra field of the given allocation.
sourcepub fn get_size_and_align(
&self,
id: AllocId,
liveness: AllocCheck
) -> InterpResult<'static, (Size, Align)>
pub fn get_size_and_align(
&self,
id: AllocId,
liveness: AllocCheck
) -> InterpResult<'static, (Size, Align)>
Obtain the size and alignment of an allocation, even if that allocation has been deallocated.
If liveness is AllocCheck::MaybeDead, this function always returns Ok.
fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>>
pub fn get_fn(
&self,
ptr: Pointer<Option<M::PointerTag>>
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>>
pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx>
sourcepub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M>
pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M>
Create a lazy debug printer that prints the given allocation and all allocations it points to, recursively.
sourcepub fn dump_allocs<'a>(
&'a self,
allocs: Vec<AllocId>
) -> DumpAllocs<'a, 'mir, 'tcx, M>
pub fn dump_allocs<'a>(
&'a self,
allocs: Vec<AllocId>
) -> DumpAllocs<'a, 'mir, 'tcx, M>
Create a lazy debug printer for a list of allocations and all allocations they point to, recursively.
sourceimpl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
sourcepub fn read_bytes(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size
) -> InterpResult<'tcx, &[u8]>
pub fn read_bytes(
&self,
ptr: Pointer<Option<M::PointerTag>>,
size: Size
) -> InterpResult<'tcx, &[u8]>
Reads the given number of bytes from memory. Returns them as a slice.
Performs appropriate bounds checks.
sourcepub fn write_bytes(
&mut self,
ptr: Pointer<Option<M::PointerTag>>,
src: impl IntoIterator<Item = u8>
) -> InterpResult<'tcx>
pub fn write_bytes(
&mut self,
ptr: Pointer<Option<M::PointerTag>>,
src: impl IntoIterator<Item = u8>
) -> InterpResult<'tcx>
Writes the given stream of bytes into memory.
Performs appropriate bounds checks.
pub fn copy(
&mut self,
src: Pointer<Option<M::PointerTag>>,
src_align: Align,
dest: Pointer<Option<M::PointerTag>>,
dest_align: Align,
size: Size,
nonoverlapping: bool
) -> InterpResult<'tcx>
pub fn copy_repeatedly(
&mut self,
src: Pointer<Option<M::PointerTag>>,
src_align: Align,
dest: Pointer<Option<M::PointerTag>>,
dest_align: Align,
size: Size,
num_copies: u64,
nonoverlapping: bool
) -> InterpResult<'tcx>
sourceimpl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>
Machine pointer introspection.
pub fn scalar_to_ptr(
&self,
scalar: Scalar<M::PointerTag>
) -> Pointer<Option<M::PointerTag>>
sourcepub fn ptr_try_get_alloc(
&self,
ptr: Pointer<Option<M::PointerTag>>
) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64>
pub fn ptr_try_get_alloc(
&self,
ptr: Pointer<Option<M::PointerTag>>
) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64>
Turning a “maybe pointer” into a proper pointer (and some information about where it points), or an absolute address.
sourcepub fn ptr_get_alloc(
&self,
ptr: Pointer<Option<M::PointerTag>>
) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)>
pub fn ptr_get_alloc(
&self,
ptr: Pointer<Option<M::PointerTag>>
) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)>
Turning a “maybe pointer” into a proper pointer (and some information about where it points).
Trait Implementations
sourceimpl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
fn data_layout(&self) -> &TargetDataLayout
Auto Trait Implementations
impl<'mir, 'tcx, M> !RefUnwindSafe for Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M> !Send for Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M> !Sync for Memory<'mir, 'tcx, M>
impl<'mir, 'tcx, M> Unpin for Memory<'mir, 'tcx, M> where
<M as Machine<'mir, 'tcx>>::ExtraFnVal: Unpin,
<M as Machine<'mir, 'tcx>>::MemoryExtra: Unpin,
<M as Machine<'mir, 'tcx>>::MemoryMap: Unpin,
impl<'mir, 'tcx, M> !UnwindSafe for Memory<'mir, 'tcx, M>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> PointerArithmetic for T where
T: HasDataLayout,
impl<T> PointerArithmetic for T where
T: HasDataLayout,
fn pointer_size(&self) -> Size
fn machine_usize_max(&self) -> u64
fn machine_isize_min(&self) -> i64
fn machine_isize_max(&self) -> i64
fn machine_usize_to_isize(&self, val: u64) -> i64
sourcefn truncate_to_ptr(&self, (u64, bool)) -> (u64, bool)
fn truncate_to_ptr(&self, (u64, bool)) -> (u64, bool)
Helper function: truncate given value-“overflowed flag” pair to pointer size and update “overflowed flag” if there was an overflow. This should be called by all the other methods before returning! Read more
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool)
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool)
fn offset<'tcx>(&self, val: u64, i: u64) -> Result<u64, InterpErrorInfo<'tcx>>
fn signed_offset<'tcx>(
&self,
val: u64,
i: i64
) -> Result<u64, InterpErrorInfo<'tcx>>
Layout
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.