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