[−][src]Struct rustc_mir::interpret::memory::Memory
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
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>[src]
pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self[src]
pub fn global_base_pointer(
&self,
ptr: Pointer
) -> InterpResult<'tcx, Pointer<M::PointerTag>>[src]
&self,
ptr: Pointer
) -> 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>[src]
&mut self,
fn_val: FnVal<'tcx, M::ExtraFnVal>
) -> Pointer<M::PointerTag>
pub fn allocate(
&mut self,
size: Size,
align: Align,
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>[src]
&mut self,
size: Size,
align: Align,
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>
pub fn allocate_bytes(
&mut self,
bytes: &[u8],
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>[src]
&mut self,
bytes: &[u8],
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>
pub fn allocate_with(
&mut self,
alloc: Allocation,
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>[src]
&mut self,
alloc: Allocation,
kind: MemoryKind<M::MemoryKind>
) -> Pointer<M::PointerTag>
pub fn reallocate(
&mut self,
ptr: Pointer<M::PointerTag>,
old_size_and_align: Option<(Size, Align)>,
new_size: Size,
new_align: Align,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>[src]
&mut self,
ptr: Pointer<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_local(
&mut self,
ptr: Pointer<M::PointerTag>
) -> InterpResult<'tcx>[src]
&mut self,
ptr: Pointer<M::PointerTag>
) -> InterpResult<'tcx>
Deallocate a local, or do nothing if that local has been made into a global.
pub fn deallocate(
&mut self,
ptr: Pointer<M::PointerTag>,
old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'tcx>[src]
&mut self,
ptr: Pointer<M::PointerTag>,
old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKind>
) -> InterpResult<'tcx>
pub fn check_ptr_access(
&self,
sptr: Scalar<M::PointerTag>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>>[src]
&self,
sptr: Scalar<M::PointerTag>,
size: Size,
align: Align
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>>
Check if the given scalar is allowed to do a memory access of given size
and align. On success, returns None for zero-sized accesses (where
nothing else is left to do) and a Pointer to use for the actual access otherwise.
Crucially, if the input is a Pointer, we will test it for liveness
even if the size is 0.
Everyone accessing memory based on a Scalar should use this method to get the
Pointer they need. And even if you already have a Pointer, call this method
to make sure it is sufficiently aligned and not dangling. Not doing that may
cause ICEs.
Most of the time you should use check_mplace_access, but when you just have a pointer,
this method is still appropriate.
pub fn check_ptr_access_align(
&self,
sptr: Scalar<M::PointerTag>,
size: Size,
align: Option<Align>,
msg: CheckInAllocMsg
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>>[src]
&self,
sptr: Scalar<M::PointerTag>,
size: Size,
align: Option<Align>,
msg: CheckInAllocMsg
) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>>
Like check_ptr_access, but definitely checks alignment when align
is Some (overriding M::enforce_alignment). Also lets the caller control
the error message for the out-of-bounds case.
pub fn ptr_may_be_null(&self, ptr: Pointer<M::PointerTag>) -> bool[src]
Test if the pointer might be NULL.
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>[src]
Allocation accessors
pub(in interpret::memory) fn get_global_alloc(
memory_extra: &M::MemoryExtra,
tcx: TyCtxt<'tcx>,
id: AllocId,
is_write: bool
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>>[src]
memory_extra: &M::MemoryExtra,
tcx: TyCtxt<'tcx>,
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.
pub fn get_raw(
&self,
id: AllocId
) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>>[src]
&self,
id: AllocId
) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>>
Gives raw access to the Allocation, without bounds or alignment checks.
Use the higher-level, PlaceTy- and OpTy-based APIs in InterpCx instead!
pub fn get_raw_mut(
&mut self,
id: AllocId
) -> InterpResult<'tcx, &mut Allocation<M::PointerTag, M::AllocExtra>>[src]
&mut self,
id: AllocId
) -> InterpResult<'tcx, &mut Allocation<M::PointerTag, M::AllocExtra>>
Gives raw mutable access to the Allocation, without bounds or alignment checks.
Use the higher-level, PlaceTy- and OpTy-based APIs in InterpCx instead!
pub fn get_size_and_align(
&self,
id: AllocId,
liveness: AllocCheck
) -> InterpResult<'static, (Size, Align)>[src]
&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.
pub(in interpret::memory) fn get_fn_alloc(
&self,
id: AllocId
) -> Option<FnVal<'tcx, M::ExtraFnVal>>[src]
&self,
id: AllocId
) -> Option<FnVal<'tcx, M::ExtraFnVal>>
pub fn get_fn(
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>>[src]
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>>
pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx>[src]
#[must_use]pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M>[src]
Create a lazy debug printer that prints the given allocation and all allocations it points to, recursively.
#[must_use]pub fn dump_allocs<'a>(
&'a self,
allocs: Vec<AllocId>
) -> DumpAllocs<'a, 'mir, 'tcx, M>[src]
&'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.
pub fn leak_report(&self, static_roots: &[AllocId]) -> usize[src]
Print leaked memory. Allocations reachable from static_roots or a Global allocation
are not considered leaked. Leaks whose kind may_leak() returns true are not reported.
pub fn alloc_map(&self) -> &M::MemoryMap[src]
This is used by priroda
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>[src]
Reading and writing.
pub fn read_bytes(
&self,
ptr: Scalar<M::PointerTag>,
size: Size
) -> InterpResult<'tcx, &[u8]>[src]
&self,
ptr: Scalar<M::PointerTag>,
size: Size
) -> InterpResult<'tcx, &[u8]>
Reads the given number of bytes from memory. Returns them as a slice.
Performs appropriate bounds checks.
pub fn read_c_str(
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, &[u8]>[src]
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, &[u8]>
Reads a 0-terminated sequence of bytes from memory. Returns them as a slice.
Performs appropriate bounds checks.
pub fn read_wide_str(
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, Vec<u16>>[src]
&self,
ptr: Scalar<M::PointerTag>
) -> InterpResult<'tcx, Vec<u16>>
Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec
Performs appropriate bounds checks.
pub fn write_bytes(
&mut self,
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u8>
) -> InterpResult<'tcx>[src]
&mut self,
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u8>
) -> InterpResult<'tcx>
Writes the given stream of bytes into memory.
Performs appropriate bounds checks.
pub fn write_u16s(
&mut self,
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u16>
) -> InterpResult<'tcx>[src]
&mut self,
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u16>
) -> InterpResult<'tcx>
Writes the given stream of u16s into memory.
Performs appropriate bounds checks.
pub fn copy(
&mut self,
src: Pointer<M::PointerTag>,
dest: Pointer<M::PointerTag>,
size: Size,
nonoverlapping: bool
) -> InterpResult<'tcx>[src]
&mut self,
src: Pointer<M::PointerTag>,
dest: Pointer<M::PointerTag>,
size: Size,
nonoverlapping: bool
) -> InterpResult<'tcx>
Expects the caller to have checked bounds and alignment.
pub fn copy_repeatedly(
&mut self,
src: Pointer<M::PointerTag>,
dest: Pointer<M::PointerTag>,
size: Size,
length: u64,
nonoverlapping: bool
) -> InterpResult<'tcx>[src]
&mut self,
src: Pointer<M::PointerTag>,
dest: Pointer<M::PointerTag>,
size: Size,
length: u64,
nonoverlapping: bool
) -> InterpResult<'tcx>
Expects the caller to have checked bounds and alignment.
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M>[src]
Machine pointer introspection.
pub fn force_ptr(
&self,
scalar: Scalar<M::PointerTag>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>[src]
&self,
scalar: Scalar<M::PointerTag>
) -> InterpResult<'tcx, Pointer<M::PointerTag>>
pub fn force_bits(
&self,
scalar: Scalar<M::PointerTag>,
size: Size
) -> InterpResult<'tcx, u128>[src]
&self,
scalar: Scalar<M::PointerTag>,
size: Size
) -> InterpResult<'tcx, u128>
Trait Implementations
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>[src]
pub fn data_layout(&self) -> &TargetDataLayout[src]
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,
<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
impl<T> Any for T where
T: 'static + ?Sized, [src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized, [src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized, [src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T[src]
impl<T> From<T> for T[src]
impl<T, U> Into<U> for T where
U: From<T>, [src]
U: From<T>,
impl<T> PointerArithmetic for T where
T: HasDataLayout, [src]
T: HasDataLayout,
pub fn pointer_size(&self) -> Size[src]
pub fn machine_usize_max(&self) -> u64[src]
pub fn machine_isize_min(&self) -> i64[src]
pub fn machine_isize_max(&self) -> i64[src]
pub fn truncate_to_ptr(&self, (u64, bool)) -> (u64, bool)[src]
pub fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool)[src]
pub fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool)[src]
pub fn offset<'tcx>(
&self,
val: u64,
i: u64
) -> Result<u64, InterpErrorInfo<'tcx>>[src]
&self,
val: u64,
i: u64
) -> Result<u64, InterpErrorInfo<'tcx>>
pub fn signed_offset<'tcx>(
&self,
val: u64,
i: i64
) -> Result<u64, InterpErrorInfo<'tcx>>[src]
&self,
val: u64,
i: i64
) -> Result<u64, InterpErrorInfo<'tcx>>
impl<T, U> TryFrom<U> for T where
U: Into<T>, [src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>, [src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.