Path: blob/main/cranelift/interpreter/src/state.rs
1692 views
//! Cranelift instructions modify the state of the machine; the [State] trait describes these1//! ways this can happen.2use crate::address::{Address, AddressSize};3use crate::frame::Frame;4use crate::interpreter::LibCallHandler;5use cranelift_codegen::data_value::DataValue;6use cranelift_codegen::ir::{7ExternalName, FuncRef, Function, GlobalValue, LibCall, MemFlags, Signature, StackSlot, Type,8Value, types,9};10use cranelift_codegen::isa::CallConv;11use smallvec::SmallVec;12use thiserror::Error;1314/// This trait manages the state necessary to interpret a single Cranelift instruction--it describes15/// all of the ways a Cranelift interpreter can interact with its virtual state. This makes it16/// possible to use the [Interpreter](crate::interpreter::Interpreter) in a range of situations:17/// - when interpretation needs to happen in a way isolated from the host a state which keeps a18/// stack and bound checks memory accesses can be used, like19/// [InterpreterState](crate::interpreter::InterpreterState).20/// - when interpretation needs to have access to the host a state which allows direct access to the21/// host memory and native functions can be used.22pub trait State<'a> {23/// Retrieve a reference to a [Function].24fn get_function(&self, func_ref: FuncRef) -> Option<&'a Function>;25/// Retrieve a reference to the currently executing [Function].26fn get_current_function(&self) -> &'a Function;27/// Retrieve the handler callback for a [LibCall]28fn get_libcall_handler(&self) -> LibCallHandler;2930/// Record that an interpreter has called into a new [Function].31fn push_frame(&mut self, function: &'a Function);32/// Record that an interpreter has returned from a called [Function].33fn pop_frame(&mut self);3435fn current_frame_mut(&mut self) -> &mut Frame<'a>;36fn current_frame(&self) -> &Frame<'a>;3738/// Collect a list of values `V` by their [value references](cranelift_codegen::ir::Value).39fn collect_values(&self, names: &[Value]) -> SmallVec<[DataValue; 1]> {40let frame = self.current_frame();41names.into_iter().map(|n| frame.get(*n).clone()).collect()42}4344/// Computes the stack address for this stack slot, including an offset.45fn stack_address(46&self,47size: AddressSize,48slot: StackSlot,49offset: u64,50) -> Result<Address, MemoryError>;51/// Retrieve a value `V` from memory at the given `address`, checking if it belongs either to the52/// stack or to one of the heaps; the number of bytes loaded corresponds to the specified [Type].53fn checked_load(54&self,55address: Address,56ty: Type,57mem_flags: MemFlags,58) -> Result<DataValue, MemoryError>;59/// Store a value `V` into memory at the given `address`, checking if it belongs either to the60/// stack or to one of the heaps; the number of bytes stored corresponds to the specified [Type].61fn checked_store(62&mut self,63address: Address,64v: DataValue,65mem_flags: MemFlags,66) -> Result<(), MemoryError>;6768/// Compute the address of a function given its name.69fn function_address(70&self,71size: AddressSize,72name: &ExternalName,73) -> Result<Address, MemoryError>;7475/// Retrieve a reference to a [Function] given its address.76fn get_function_from_address(&self, address: Address) -> Option<InterpreterFunctionRef<'a>>;7778/// Given a global value, compute the final value for that global value, applying all operations79/// in intermediate global values.80fn resolve_global_value(&self, gv: GlobalValue) -> Result<DataValue, MemoryError>;8182/// Retrieves the current pinned reg value83fn get_pinned_reg(&self) -> DataValue;84/// Sets a value for the pinned reg85fn set_pinned_reg(&mut self, v: DataValue);86}8788pub enum InterpreterFunctionRef<'a> {89Function(&'a Function),90LibCall(LibCall),91}9293impl<'a> InterpreterFunctionRef<'a> {94pub fn signature(&self) -> Signature {95match self {96InterpreterFunctionRef::Function(f) => f.stencil.signature.clone(),97// CallConv here is sort of irrelevant, since we don't use it for anything98// FIXME handle non-64bit systems99InterpreterFunctionRef::LibCall(lc) => lc.signature(CallConv::SystemV, types::I64),100}101}102}103104impl<'a> From<&'a Function> for InterpreterFunctionRef<'a> {105fn from(f: &'a Function) -> Self {106InterpreterFunctionRef::Function(f)107}108}109110impl From<LibCall> for InterpreterFunctionRef<'_> {111fn from(lc: LibCall) -> Self {112InterpreterFunctionRef::LibCall(lc)113}114}115116#[derive(Error, Debug)]117pub enum MemoryError {118#[error("Invalid DataValue passed as an address: {0}")]119InvalidAddress(DataValue),120#[error("Invalid type for address: {0}")]121InvalidAddressType(Type),122#[error("Requested an the entry {entry} but only {max} entries are allowed")]123InvalidEntry { entry: u64, max: u64 },124#[error("Requested an offset of {offset} but max was {max}")]125InvalidOffset { offset: u64, max: u64 },126#[error("Load of {load_size} bytes is larger than available size at address {addr:?}")]127OutOfBoundsLoad {128addr: Address,129load_size: usize,130mem_flags: MemFlags,131},132#[error("Store of {store_size} bytes is larger than available size at address {addr:?}")]133OutOfBoundsStore {134addr: Address,135store_size: usize,136mem_flags: MemFlags,137},138#[error("Load of {load_size} bytes is misaligned at address {addr:?}")]139MisalignedLoad { addr: Address, load_size: usize },140#[error("Store of {store_size} bytes is misaligned at address {addr:?}")]141MisalignedStore { addr: Address, store_size: usize },142}143144145