1use crate::addrs::GlobalAddr;
2use crate::core::reader::types::global::GlobalType;
3use crate::resumable::{ResumableRef, RunState};
4use alloc::borrow::{Cow, ToOwned};
5use alloc::vec::Vec;
6
7use const_interpreter_loop::run_const_span;
8use store::addrs::{FuncAddr, ModuleAddr};
9use store::ExternVal;
10use store::HaltExecutionError;
11use store::InstantiationOutcome;
12use value_stack::Stack;
13
14use crate::core::reader::types::{FuncType, ResultType};
15use crate::execution::assert_validated::UnwrapValidatedExt;
16use crate::execution::config::Config;
17use crate::execution::store::Store;
18use crate::execution::value::Value;
19use crate::interop::InteropValueList;
20use crate::{RuntimeError, ValidationInfo};
21
22pub(crate) mod assert_validated;
23pub mod config;
24pub mod const_interpreter_loop;
25pub mod error;
26pub mod interop;
27mod interpreter_loop;
28pub mod linker;
29pub(crate) mod little_endian;
30pub mod registry;
31pub mod resumable;
32pub mod store;
33pub mod value;
34pub mod value_stack;
35
36pub const DEFAULT_MODULE: &str = "__interpreter_default__";
38
39pub struct RuntimeInstance<'b, T: Config = ()> {
40 pub store: Store<'b, T>,
41}
42
43impl<T: Config + Default> Default for RuntimeInstance<'_, T> {
44 fn default() -> Self {
45 Self::new(T::default())
46 }
47}
48
49impl<'b, T: Config> RuntimeInstance<'b, T> {
50 pub fn new(user_data: T) -> Self {
51 RuntimeInstance {
52 store: Store::new(user_data),
53 }
54 }
55
56 pub fn new_with_default_module(
58 user_data: T,
59 validation_info: &'_ ValidationInfo<'b>,
60 ) -> Result<(Self, ModuleAddr), RuntimeError> {
61 let mut instance = Self::new(user_data);
62 let module_addr = instance
63 .add_module(DEFAULT_MODULE, validation_info, None)?
64 .module_addr;
65 Ok((instance, module_addr))
66 }
67
68 pub fn new_named(
70 user_data: T,
71 module_name: &str,
72 validation_info: &'_ ValidationInfo<'b>,
73 ) -> Result<(Self, ModuleAddr), RuntimeError> {
75 let mut instance = Self::new(user_data);
76 let module_addr = instance
77 .add_module(module_name, validation_info, None)?
78 .module_addr;
79 Ok((instance, module_addr))
80 }
81
82 pub fn add_module(
85 &mut self,
86 module_name: &str,
87 validation_info: &'_ ValidationInfo<'b>,
88 maybe_fuel: Option<u32>,
89 ) -> Result<InstantiationOutcome, RuntimeError> {
90 self.store
91 .add_module(module_name, validation_info, maybe_fuel)
92 }
93
94 pub fn get_module_by_name(&self, module_name: &str) -> Option<ModuleAddr> {
95 self.store
97 .registry
98 .lookup_module(Cow::Owned(module_name.to_owned()))
99 }
100
101 pub fn get_function_by_name(
102 &self,
103 module_name: &str,
104 function_name: &str,
105 ) -> Result<FuncAddr, RuntimeError> {
106 self.store
108 .registry
109 .lookup(
110 Cow::Owned(module_name.to_owned()),
111 Cow::Owned(function_name.to_owned()),
112 )?
113 .as_func()
114 .ok_or(RuntimeError::FunctionNotFound)
115 }
116
117 pub fn get_function_by_index(
118 &self,
119 module_addr: ModuleAddr,
120 function_idx: usize,
121 ) -> Result<FuncAddr, RuntimeError> {
122 let module_inst = self.store.modules.get(module_addr);
123 let function = *module_inst
124 .func_addrs
125 .get(function_idx)
126 .ok_or(RuntimeError::FunctionNotFound)?;
127
128 Ok(function)
129 }
130
131 pub fn invoke_typed<Params: InteropValueList, Returns: InteropValueList>(
133 &mut self,
134 function: FuncAddr,
135 params: Params,
136 ) -> Result<Returns, RuntimeError> {
138 self.invoke(function, params.into_values())
139 .map(|values| Returns::try_from_values(values.into_iter()).unwrap_validated())
140 }
141
142 pub fn invoke(
144 &mut self,
145 function: FuncAddr,
146 params: Vec<Value>,
147 ) -> Result<Vec<Value>, RuntimeError> {
148 self.store
149 .invoke(function, params, None)
150 .map(|run_state| match run_state {
151 RunState::Finished { values, .. } => values,
152 _ => unreachable!("non metered invoke call"),
153 })
154 }
155
156 pub fn create_resumable(
160 &self,
161 function: FuncAddr,
162 params: Vec<Value>,
163 fuel: u32,
164 ) -> Result<ResumableRef, RuntimeError> {
165 self.store.create_resumable(function, params, Some(fuel))
166 }
167
168 pub fn resume(&mut self, resumable_ref: ResumableRef) -> Result<RunState, RuntimeError> {
171 self.store.resume(resumable_ref)
172 }
173
174 pub fn access_fuel_mut<R>(
193 &mut self,
194 resumable_ref: &mut ResumableRef,
195 f: impl FnOnce(&mut Option<u32>) -> R,
196 ) -> Result<R, RuntimeError> {
197 self.store.access_fuel_mut(resumable_ref, f)
198 }
199
200 pub fn add_host_function_typed<Params: InteropValueList, Returns: InteropValueList>(
204 &mut self,
205 module_name: &str,
206 name: &str,
207 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
208 ) -> Result<FuncAddr, RuntimeError> {
209 let host_func_ty = FuncType {
210 params: ResultType {
211 valtypes: Vec::from(Params::TYS),
212 },
213 returns: ResultType {
214 valtypes: Vec::from(Returns::TYS),
215 },
216 };
217 self.add_host_function(module_name, name, host_func_ty, host_func)
218 }
219
220 pub fn add_host_function(
221 &mut self,
222 module_name: &str,
223 name: &str,
224 host_func_ty: FuncType,
225 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
226 ) -> Result<FuncAddr, RuntimeError> {
227 let function = self.store.func_alloc(host_func_ty, host_func);
228 self.store.registry.register(
229 module_name.to_owned().into(),
230 name.to_owned().into(),
231 store::ExternVal::Func(function),
232 )?;
233 Ok(function)
234 }
235
236 pub fn user_data(&self) -> &T {
237 &self.store.user_data
238 }
239
240 pub fn user_data_mut(&mut self) -> &mut T {
241 &mut self.store.user_data
242 }
243
244 pub fn global_type(&self, global_addr: GlobalAddr) -> GlobalType {
246 self.store.global_type(global_addr)
247 }
248
249 pub fn global_read(&self, global_addr: GlobalAddr) -> Value {
251 self.store.global_read(global_addr)
252 }
253
254 pub fn global_write(
260 &mut self,
261 global_addr: GlobalAddr,
262 val: Value,
263 ) -> Result<(), RuntimeError> {
264 self.store.global_write(global_addr, val)
265 }
266
267 pub fn lookup_export(
269 &self,
270 module_name: Cow<'static, str>,
271 name: Cow<'static, str>,
272 ) -> Result<ExternVal, RuntimeError> {
273 self.store.registry.lookup(module_name, name).copied()
274 }
275}
276
277pub fn host_function_wrapper<Params: InteropValueList, Results: InteropValueList>(
295 params: Vec<Value>,
296 f: impl FnOnce(Params) -> Result<Results, HaltExecutionError>,
297) -> Result<Vec<Value>, HaltExecutionError> {
298 let params =
299 Params::try_from_values(params.into_iter()).expect("Params match the actual parameters");
300 f(params).map(Results::into_values)
301}