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.