//! This module contains everything needed to instantiate an interpreter. //! This separation exists to ensure that no fancy miri features like //! interpreting common C functions leak into CTFE. use std::hash::Hash; use rustc::mir::interpret::{AllocId, EvalResult, Scalar, Pointer, AccessKind, GlobalId}; use super::{EvalContext, Place, ValTy, Memory}; use rustc::mir; use rustc::ty::{self, Ty}; use rustc::ty::layout::Size; use syntax::codemap::Span; use syntax::ast::Mutability; /// Methods of this trait signifies a point where CTFE evaluation would fail /// and some use case dependent behaviour can instead be applied pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash { /// Additional data that can be accessed via the Memory type MemoryData: Clone + Eq + Hash; /// Additional memory kinds a machine wishes to distinguish from the builtin ones type MemoryKinds: ::std::fmt::Debug + PartialEq + Copy + Clone; /// Entry point to all function calls. /// /// Returns Ok(true) when the function was handled completely /// e.g. due to missing mir /// /// Returns Ok(false) if a new stack frame was pushed fn eval_fn_call<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, destination: Option<(Place, mir::BasicBlock)>, args: &[ValTy<'tcx>], span: Span, sig: ty::FnSig<'tcx>, ) -> EvalResult<'tcx, bool>; /// directly process an intrinsic without pushing a stack frame. fn call_intrinsic<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[ValTy<'tcx>], dest: Place, dest_layout: ty::layout::TyLayout<'tcx>, target: mir::BasicBlock, ) -> EvalResult<'tcx>; /// Called for all binary operations except on float types. /// /// Returns `None` if the operation should be handled by the integer /// op code in order to share more code between machines /// /// Returns a (value, overflowed) pair if the operation succeeded fn try_ptr_op<'a>( ecx: &EvalContext<'a, 'mir, 'tcx, Self>, bin_op: mir::BinOp, left: Scalar, left_ty: Ty<'tcx>, right: Scalar, right_ty: Ty<'tcx>, ) -> EvalResult<'tcx, Option<(Scalar, bool)>>; /// Called when trying to mark machine defined `MemoryKinds` as static fn mark_static_initialized<'a>( _mem: &mut Memory<'a, 'mir, 'tcx, Self>, _id: AllocId, _mutability: Mutability, ) -> EvalResult<'tcx, bool>; /// Called when requiring a pointer to a static. Non const eval can /// create a mutable memory location for `static mut` fn init_static<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, cid: GlobalId<'tcx>, ) -> EvalResult<'tcx, AllocId>; /// Heap allocations via the `box` keyword /// /// Returns a pointer to the allocated memory fn box_alloc<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ty: Ty<'tcx>, dest: Place, ) -> EvalResult<'tcx>; /// Called when trying to access a global declared with a `linkage` attribute fn global_item_with_linkage<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, mutability: Mutability, ) -> EvalResult<'tcx>; fn check_locks<'a>( _mem: &Memory<'a, 'mir, 'tcx, Self>, _ptr: Pointer, _size: Size, _access: AccessKind, ) -> EvalResult<'tcx> { Ok(()) } fn add_lock<'a>( _mem: &mut Memory<'a, 'mir, 'tcx, Self>, _id: AllocId, ) {} fn free_lock<'a>( _mem: &mut Memory<'a, 'mir, 'tcx, Self>, _id: AllocId, _len: u64, ) -> EvalResult<'tcx> { Ok(()) } fn end_region<'a>( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, _reg: Option<::rustc::middle::region::Scope>, ) -> EvalResult<'tcx> { Ok(()) } fn validation_op<'a>( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, _op: ::rustc::mir::ValidationOp, _operand: &::rustc::mir::ValidationOperand<'tcx, ::rustc::mir::Place<'tcx>>, ) -> EvalResult<'tcx> { Ok(()) } }