Struct miri::MiriMachine
source · pub struct MiriMachine<'mir, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub borrow_tracker: Option<RefCell<GlobalStateInner>>,
pub data_race: Option<GlobalState>,
pub alloc_addresses: RefCell<GlobalStateInner>,
pub native_lib: Option<!>,
/* private fields */
}
Expand description
The machine itself.
If you add anything here that stores machine values, remember to update
visit_all_machine_values
!
Fields§
§tcx: TyCtxt<'tcx>
§borrow_tracker: Option<RefCell<GlobalStateInner>>
Global data for borrow tracking.
data_race: Option<GlobalState>
Data race detector global data.
alloc_addresses: RefCell<GlobalStateInner>
Ptr-int-cast module global data.
native_lib: Option<!>
Implementations§
source§impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
pub fn free_alloc_id( &mut self, dead_id: AllocId, size: Size, align: Align, kind: MemoryKind )
source§impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic)
source§impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
sourcepub fn current_span(&self) -> Span
pub fn current_span(&self) -> Span
Get the current span in the topmost function which is workspace-local and not
#[track_caller]
.
This function is backed by a cache, and can be assumed to be very fast.
It will work even when the stack is empty.
sourcepub fn caller_span(&self) -> Span
pub fn caller_span(&self) -> Span
Returns the span of the caller of the current operation, again walking down the stack to find the closest frame in a local crate, if the caller of the current operation is not in a local crate. This is useful when we are processing something which occurs on function-entry and we want to point at the call to the function, not the function definition generally.
sourcepub fn is_user_relevant(&self, frame: &Frame<'mir, 'tcx, Provenance>) -> bool
pub fn is_user_relevant(&self, frame: &Frame<'mir, 'tcx, Provenance>) -> bool
This is the source of truth for the is_user_relevant
flag in our FrameExtra
.
source§impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx>
sourcepub fn init_extern_statics(
this: &mut MiriInterpCx<'mir, 'tcx>
) -> InterpResult<'tcx>
pub fn init_extern_statics( this: &mut MiriInterpCx<'mir, 'tcx> ) -> InterpResult<'tcx>
Sets up the “extern statics” for this machine.
Trait Implementations§
source§impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx>
impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx>
Machine hook implementations.
source§fn ptr_from_addr_cast(
ecx: &MiriInterpCx<'mir, 'tcx>,
addr: u64
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>
fn ptr_from_addr_cast( ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64 ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>
Called on usize as ptr
casts.
source§fn expose_ptr(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ptr: Pointer<Self::Provenance>
) -> InterpResult<'tcx>
fn expose_ptr( ecx: &mut InterpCx<'mir, 'tcx, Self>, ptr: Pointer<Self::Provenance> ) -> InterpResult<'tcx>
Called on ptr as usize
casts.
(Actually computing the resulting usize
doesn’t need machine help,
that’s just Scalar::try_to_int
.)
source§fn ptr_get_alloc(
ecx: &MiriInterpCx<'mir, 'tcx>,
ptr: Pointer<Self::Provenance>
) -> Option<(AllocId, Size, Self::ProvenanceExtra)>
fn ptr_get_alloc( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer<Self::Provenance> ) -> Option<(AllocId, Size, Self::ProvenanceExtra)>
Convert a pointer with provenance into an allocation-offset pair,
or a None
with an absolute address if that conversion is not possible.
This is called when a pointer is about to be used for memory access,
an in-bounds check, or anything else that requires knowing which allocation it points to.
The resulting AllocId
will just be used for that one step and the forgotten again
(i.e., we’ll never turn the data returned here back into a Pointer
that might be
stored in machine state).
§type MemoryKind = MiriMemoryKind
type MemoryKind = MiriMemoryKind
§type ExtraFnVal = DynSym
type ExtraFnVal = DynSym
dlsym
that can later be called to execute the right thing.§type FrameExtra = FrameExtra<'tcx>
type FrameExtra = FrameExtra<'tcx>
§type AllocExtra = AllocExtra<'tcx>
type AllocExtra = AllocExtra<'tcx>
§type Provenance = Provenance
type Provenance = Provenance
AllocId
they belong to.§type ProvenanceExtra = ProvenanceExtra
type ProvenanceExtra = ProvenanceExtra
§type Bytes = MiriAllocBytes
type Bytes = MiriAllocBytes
§type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Provenance, <MiriMachine<'mir, 'tcx> as Machine<'mir, 'tcx>>::AllocExtra, <MiriMachine<'mir, 'tcx> as Machine<'mir, 'tcx>>::Bytes>)>
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Provenance, <MiriMachine<'mir, 'tcx> as Machine<'mir, 'tcx>>::AllocExtra, <MiriMachine<'mir, 'tcx> as Machine<'mir, 'tcx>>::Bytes>)>
source§const GLOBAL_KIND: Option<MiriMemoryKind> = _
const GLOBAL_KIND: Option<MiriMemoryKind> = _
tcx
) –
or None if such memory should not be mutated and thus any such attempt will cause
a ModifiedStatic
error to be raised.
Statics are copied under two circumstances: When they are mutated, and when
adjust_allocation
(see below) returns an owned allocation
that is added to the memory so that the work is not done twice.source§const PANIC_ON_ALLOC_FAIL: bool = false
const PANIC_ON_ALLOC_FAIL: bool = false
source§fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
source§fn alignment_check(
ecx: &MiriInterpCx<'mir, 'tcx>,
alloc_id: AllocId,
alloc_align: Align,
alloc_kind: AllocKind,
offset: Size,
align: Align
) -> Option<Misalignment>
fn alignment_check( ecx: &MiriInterpCx<'mir, 'tcx>, alloc_id: AllocId, alloc_align: Align, alloc_kind: AllocKind, offset: Size, align: Align ) -> Option<Misalignment>
source§fn enforce_validity(
ecx: &MiriInterpCx<'mir, 'tcx>,
_layout: TyAndLayout<'tcx>
) -> bool
fn enforce_validity( ecx: &MiriInterpCx<'mir, 'tcx>, _layout: TyAndLayout<'tcx> ) -> bool
source§fn enforce_abi(_ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
fn enforce_abi(_ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
source§fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool
source§fn find_mir_or_eval_fn(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
instance: Instance<'tcx>,
abi: Abi,
args: &[FnArg<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
ret: Option<BasicBlock>,
unwind: UnwindAction
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, Instance<'tcx>)>>
fn find_mir_or_eval_fn( ecx: &mut MiriInterpCx<'mir, 'tcx>, instance: Instance<'tcx>, abi: Abi, args: &[FnArg<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, ret: Option<BasicBlock>, unwind: UnwindAction ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, Instance<'tcx>)>>
source§fn call_extra_fn(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
fn_val: DynSym,
abi: Abi,
args: &[FnArg<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
ret: Option<BasicBlock>,
unwind: UnwindAction
) -> InterpResult<'tcx>
fn call_extra_fn( ecx: &mut MiriInterpCx<'mir, 'tcx>, fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, ret: Option<BasicBlock>, unwind: UnwindAction ) -> InterpResult<'tcx>
fn_val
. It is the hook’s responsibility to advance the instruction
pointer as appropriate.source§fn call_intrinsic(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
instance: Instance<'tcx>,
args: &[OpTy<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
ret: Option<BasicBlock>,
unwind: UnwindAction
) -> InterpResult<'tcx, Option<Instance<'tcx>>>
fn call_intrinsic( ecx: &mut MiriInterpCx<'mir, 'tcx>, instance: Instance<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, ret: Option<BasicBlock>, unwind: UnwindAction ) -> InterpResult<'tcx, Option<Instance<'tcx>>>
source§fn assert_panic(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
msg: &AssertMessage<'tcx>,
unwind: UnwindAction
) -> InterpResult<'tcx>
fn assert_panic( ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: &AssertMessage<'tcx>, unwind: UnwindAction ) -> InterpResult<'tcx>
Assert
MIR terminators that trigger a panic.source§fn panic_nounwind(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
msg: &str
) -> InterpResult<'tcx>
fn panic_nounwind( ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str ) -> InterpResult<'tcx>
source§fn unwind_terminate(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
reason: UnwindTerminateReason
) -> InterpResult<'tcx>
fn unwind_terminate( ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: UnwindTerminateReason ) -> InterpResult<'tcx>
source§fn binary_ptr_op(
ecx: &MiriInterpCx<'mir, 'tcx>,
bin_op: BinOp,
left: &ImmTy<'tcx, Provenance>,
right: &ImmTy<'tcx, Provenance>
) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)>
fn binary_ptr_op( ecx: &MiriInterpCx<'mir, 'tcx>, bin_op: BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance> ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)>
source§fn generate_nan<F1: Float + FloatConvert<F2>, F2: Float>(
ecx: &InterpCx<'mir, 'tcx, Self>,
inputs: &[F1]
) -> F2
fn generate_nan<F1: Float + FloatConvert<F2>, F2: Float>( ecx: &InterpCx<'mir, 'tcx, Self>, inputs: &[F1] ) -> F2
source§fn thread_local_static_pointer(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
def_id: DefId
) -> InterpResult<'tcx, Pointer<Provenance>>
fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'mir, 'tcx>, def_id: DefId ) -> InterpResult<'tcx, Pointer<Provenance>>
AllocId
for the given thread-local static in the current thread.source§fn extern_static_pointer(
ecx: &MiriInterpCx<'mir, 'tcx>,
def_id: DefId
) -> InterpResult<'tcx, Pointer<Provenance>>
fn extern_static_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, def_id: DefId ) -> InterpResult<'tcx, Pointer<Provenance>>
AllocId
for the given extern static
.source§fn adjust_allocation<'b>(
ecx: &MiriInterpCx<'mir, 'tcx>,
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind>
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
fn adjust_allocation<'b>( ecx: &MiriInterpCx<'mir, 'tcx>, id: AllocId, alloc: Cow<'b, Allocation>, kind: Option<MemoryKind> ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
source§fn adjust_alloc_root_pointer(
ecx: &MiriInterpCx<'mir, 'tcx>,
ptr: Pointer<CtfeProvenance>,
kind: Option<MemoryKind>
) -> InterpResult<'tcx, Pointer<Provenance>>
fn adjust_alloc_root_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer<CtfeProvenance>, kind: Option<MemoryKind> ) -> InterpResult<'tcx, Pointer<Provenance>>
source§fn before_memory_read(
_tcx: TyCtxtAt<'tcx>,
machine: &Self,
alloc_extra: &AllocExtra<'tcx>,
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
range: AllocRange
) -> InterpResult<'tcx>
fn before_memory_read( _tcx: TyCtxtAt<'tcx>, machine: &Self, alloc_extra: &AllocExtra<'tcx>, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), range: AllocRange ) -> InterpResult<'tcx>
source§fn before_memory_write(
_tcx: TyCtxtAt<'tcx>,
machine: &mut Self,
alloc_extra: &mut AllocExtra<'tcx>,
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
range: AllocRange
) -> InterpResult<'tcx>
fn before_memory_write( _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), range: AllocRange ) -> InterpResult<'tcx>
source§fn before_memory_deallocation(
_tcx: TyCtxtAt<'tcx>,
machine: &mut Self,
alloc_extra: &mut AllocExtra<'tcx>,
(alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra),
size: Size,
align: Align,
kind: MemoryKind
) -> InterpResult<'tcx>
fn before_memory_deallocation( _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), size: Size, align: Align, kind: MemoryKind ) -> InterpResult<'tcx>
source§fn retag_ptr_value(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
kind: RetagKind,
val: &ImmTy<'tcx, Provenance>
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>>
fn retag_ptr_value( ecx: &mut InterpCx<'mir, 'tcx, Self>, kind: RetagKind, val: &ImmTy<'tcx, Provenance> ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>>
source§fn retag_place_contents(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
kind: RetagKind,
place: &PlaceTy<'tcx, Provenance>
) -> InterpResult<'tcx>
fn retag_place_contents( ecx: &mut InterpCx<'mir, 'tcx, Self>, kind: RetagKind, place: &PlaceTy<'tcx, Provenance> ) -> InterpResult<'tcx>
source§fn protect_in_place_function_argument(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
place: &MPlaceTy<'tcx, Provenance>
) -> InterpResult<'tcx>
fn protect_in_place_function_argument( ecx: &mut InterpCx<'mir, 'tcx, Self>, place: &MPlaceTy<'tcx, Provenance> ) -> InterpResult<'tcx>
source§fn init_frame_extra(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
frame: Frame<'mir, 'tcx, Provenance>
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>>
fn init_frame_extra( ecx: &mut InterpCx<'mir, 'tcx, Self>, frame: Frame<'mir, 'tcx, Provenance> ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>>
source§fn stack<'a>(
ecx: &'a InterpCx<'mir, 'tcx, Self>
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>]
fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self> ) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>]
source§fn stack_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>
fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self> ) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>
source§fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
source§fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
source§fn before_stack_pop(
ecx: &InterpCx<'mir, 'tcx, Self>,
frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>
) -> InterpResult<'tcx>
fn before_stack_pop( ecx: &InterpCx<'mir, 'tcx, Self>, frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra> ) -> InterpResult<'tcx>
source§fn after_stack_pop(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
unwinding: bool
) -> InterpResult<'tcx, StackPopJump>
fn after_stack_pop( ecx: &mut InterpCx<'mir, 'tcx, Self>, frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>, unwinding: bool ) -> InterpResult<'tcx, StackPopJump>
locals
have already been destroyed!source§fn after_local_allocated(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
local: Local,
mplace: &MPlaceTy<'tcx, Provenance>
) -> InterpResult<'tcx>
fn after_local_allocated( ecx: &mut InterpCx<'mir, 'tcx, Self>, local: Local, mplace: &MPlaceTy<'tcx, Provenance> ) -> InterpResult<'tcx>
source§fn eval_mir_constant<F>(
ecx: &InterpCx<'mir, 'tcx, Self>,
val: Const<'tcx>,
span: Span,
layout: Option<TyAndLayout<'tcx>>,
eval: F
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>where
F: Fn(&InterpCx<'mir, 'tcx, Self>, Const<'tcx>, Span, Option<TyAndLayout<'tcx>>) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>,
fn eval_mir_constant<F>(
ecx: &InterpCx<'mir, 'tcx, Self>,
val: Const<'tcx>,
span: Span,
layout: Option<TyAndLayout<'tcx>>,
eval: F
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>where
F: Fn(&InterpCx<'mir, 'tcx, Self>, Const<'tcx>, Span, Option<TyAndLayout<'tcx>>) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>,
eval
function will do all the required evaluation,
but this hook has the chance to do some pre/postprocessing.§const ALL_CONSTS_ARE_PRECHECKED: bool = true
const ALL_CONSTS_ARE_PRECHECKED: bool = true
eval_mir_constant
can never fail because all required consts have
already been checked before.§fn load_mir(
ecx: &InterpCx<'mir, 'tcx, Self>,
instance: InstanceDef<'tcx>
) -> Result<&'tcx Body<'tcx>, InterpErrorInfo<'tcx>>
fn load_mir( ecx: &InterpCx<'mir, 'tcx, Self>, instance: InstanceDef<'tcx> ) -> Result<&'tcx Body<'tcx>, InterpErrorInfo<'tcx>>
§fn increment_const_eval_counter(
_ecx: &mut InterpCx<'mir, 'tcx, Self>
) -> Result<(), InterpErrorInfo<'tcx>>
fn increment_const_eval_counter( _ecx: &mut InterpCx<'mir, 'tcx, Self> ) -> Result<(), InterpErrorInfo<'tcx>>
StatementKind::ConstEvalCounter
instruction.
You can use this to detect long or endlessly running programs.§fn before_access_global(
_tcx: TyCtxtAt<'tcx>,
_machine: &Self,
_alloc_id: AllocId,
_allocation: ConstAllocation<'tcx>,
_static_def_id: Option<DefId>,
_is_write: bool
) -> Result<(), InterpErrorInfo<'tcx>>
fn before_access_global( _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_id: AllocId, _allocation: ConstAllocation<'tcx>, _static_def_id: Option<DefId>, _is_write: bool ) -> Result<(), InterpErrorInfo<'tcx>>
def_id
is Some
if this is the “lazy” allocation of a static.