1use crate::host::Externals;
2use crate::isa;
3use crate::module::ModuleInstance;
4use crate::runner::{check_function_args, Interpreter, InterpreterState, StackRecycler};
5use crate::types::ValueType;
6use crate::value::RuntimeValue;
7use crate::{Signature, Trap};
8use alloc::{
9 borrow::Cow,
10 rc::{Rc, Weak},
11 vec::Vec,
12};
13use core::fmt;
14use tetsy_wasm::elements::Local;
15
16#[derive(Clone, Debug)]
22pub struct FuncRef(Rc<FuncInstance>);
23
24impl ::core::ops::Deref for FuncRef {
25 type Target = FuncInstance;
26 fn deref(&self) -> &FuncInstance {
27 &self.0
28 }
29}
30
31pub struct FuncInstance(FuncInstanceInternal);
46
47#[derive(Clone)]
48pub(crate) enum FuncInstanceInternal {
49 Internal {
50 signature: Rc<Signature>,
51 module: Weak<ModuleInstance>,
52 body: Rc<FuncBody>,
53 },
54 Host {
55 signature: Signature,
56 host_func_index: usize,
57 },
58}
59
60impl fmt::Debug for FuncInstance {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 match self.as_internal() {
63 &FuncInstanceInternal::Internal { ref signature, .. } => {
64 write!(f, "Internal {{ signature={:?} }}", signature,)
67 }
68 &FuncInstanceInternal::Host { ref signature, .. } => {
69 write!(f, "Host {{ signature={:?} }}", signature)
70 }
71 }
72 }
73}
74
75impl FuncInstance {
76 pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
85 let func = FuncInstanceInternal::Host {
86 signature,
87 host_func_index,
88 };
89 FuncRef(Rc::new(FuncInstance(func)))
90 }
91
92 pub fn signature(&self) -> &Signature {
98 match *self.as_internal() {
99 FuncInstanceInternal::Internal { ref signature, .. } => signature,
100 FuncInstanceInternal::Host { ref signature, .. } => signature,
101 }
102 }
103
104 pub(crate) fn as_internal(&self) -> &FuncInstanceInternal {
105 &self.0
106 }
107
108 pub(crate) fn alloc_internal(
109 module: Weak<ModuleInstance>,
110 signature: Rc<Signature>,
111 body: FuncBody,
112 ) -> FuncRef {
113 let func = FuncInstanceInternal::Internal {
114 signature,
115 module: module,
116 body: Rc::new(body),
117 };
118 FuncRef(Rc::new(FuncInstance(func)))
119 }
120
121 pub(crate) fn body(&self) -> Option<Rc<FuncBody>> {
122 match *self.as_internal() {
123 FuncInstanceInternal::Internal { ref body, .. } => Some(Rc::clone(body)),
124 FuncInstanceInternal::Host { .. } => None,
125 }
126 }
127
128 pub fn invoke<E: Externals>(
138 func: &FuncRef,
139 args: &[RuntimeValue],
140 externals: &mut E,
141 ) -> Result<Option<RuntimeValue>, Trap> {
142 check_function_args(func.signature(), &args)?;
143 match *func.as_internal() {
144 FuncInstanceInternal::Internal { .. } => {
145 let mut interpreter = Interpreter::new(func, args, None)?;
146 interpreter.start_execution(externals)
147 }
148 FuncInstanceInternal::Host {
149 ref host_func_index,
150 ..
151 } => externals.invoke_index(*host_func_index, args.into()),
152 }
153 }
154
155 pub fn invoke_with_stack<E: Externals>(
163 func: &FuncRef,
164 args: &[RuntimeValue],
165 externals: &mut E,
166 stack_recycler: &mut StackRecycler,
167 ) -> Result<Option<RuntimeValue>, Trap> {
168 check_function_args(func.signature(), &args)?;
169 match *func.as_internal() {
170 FuncInstanceInternal::Internal { .. } => {
171 let mut interpreter = Interpreter::new(func, args, Some(stack_recycler))?;
172 let return_value = interpreter.start_execution(externals);
173 stack_recycler.recycle(interpreter);
174 return_value
175 }
176 FuncInstanceInternal::Host {
177 ref host_func_index,
178 ..
179 } => externals.invoke_index(*host_func_index, args.into()),
180 }
181 }
182
183 pub fn invoke_resumable<'args>(
198 func: &FuncRef,
199 args: impl Into<Cow<'args, [RuntimeValue]>>,
200 ) -> Result<FuncInvocation<'args>, Trap> {
201 let args = args.into();
202 check_function_args(func.signature(), &args)?;
203 match *func.as_internal() {
204 FuncInstanceInternal::Internal { .. } => {
205 let interpreter = Interpreter::new(func, &*args, None)?;
206 Ok(FuncInvocation {
207 kind: FuncInvocationKind::Internal(interpreter),
208 })
209 }
210 FuncInstanceInternal::Host {
211 ref host_func_index,
212 ..
213 } => Ok(FuncInvocation {
214 kind: FuncInvocationKind::Host {
215 args,
216 host_func_index: *host_func_index,
217 finished: false,
218 },
219 }),
220 }
221 }
222}
223
224#[derive(Debug)]
226pub enum ResumableError {
227 Trap(Trap),
229 NotResumable,
240 AlreadyStarted,
246}
247
248impl From<Trap> for ResumableError {
249 fn from(trap: Trap) -> Self {
250 ResumableError::Trap(trap)
251 }
252}
253
254pub struct FuncInvocation<'args> {
256 kind: FuncInvocationKind<'args>,
257}
258
259enum FuncInvocationKind<'args> {
260 Internal(Interpreter),
261 Host {
262 args: Cow<'args, [RuntimeValue]>,
263 host_func_index: usize,
264 finished: bool,
265 },
266}
267
268impl<'args> FuncInvocation<'args> {
269 pub fn is_resumable(&self) -> bool {
271 match &self.kind {
272 &FuncInvocationKind::Internal(ref interpreter) => interpreter.state().is_resumable(),
273 &FuncInvocationKind::Host { .. } => false,
274 }
275 }
276
277 pub fn resumable_value_type(&self) -> Option<ValueType> {
279 match &self.kind {
280 &FuncInvocationKind::Internal(ref interpreter) => match interpreter.state() {
281 &InterpreterState::Resumable(ref value_type) => value_type.clone(),
282 _ => None,
283 },
284 &FuncInvocationKind::Host { .. } => None,
285 }
286 }
287
288 pub fn start_execution<'externals, E: Externals + 'externals>(
290 &mut self,
291 externals: &'externals mut E,
292 ) -> Result<Option<RuntimeValue>, ResumableError> {
293 match self.kind {
294 FuncInvocationKind::Internal(ref mut interpreter) => {
295 if interpreter.state() != &InterpreterState::Initialized {
296 return Err(ResumableError::AlreadyStarted);
297 }
298 Ok(interpreter.start_execution(externals)?)
299 }
300 FuncInvocationKind::Host {
301 ref args,
302 ref mut finished,
303 ref host_func_index,
304 } => {
305 if *finished {
306 return Err(ResumableError::AlreadyStarted);
307 }
308 *finished = true;
309 Ok(externals.invoke_index(*host_func_index, args.as_ref().into())?)
310 }
311 }
312 }
313
314 pub fn resume_execution<'externals, E: Externals + 'externals>(
323 &mut self,
324 return_val: Option<RuntimeValue>,
325 externals: &'externals mut E,
326 ) -> Result<Option<RuntimeValue>, ResumableError> {
327 use crate::TrapKind;
328
329 if return_val.map(|v| v.value_type()) != self.resumable_value_type() {
330 return Err(ResumableError::Trap(Trap::new(
331 TrapKind::UnexpectedSignature,
332 )));
333 }
334
335 match &mut self.kind {
336 FuncInvocationKind::Internal(interpreter) => {
337 if interpreter.state().is_resumable() {
338 Ok(interpreter.resume_execution(return_val, externals)?)
339 } else {
340 Err(ResumableError::AlreadyStarted)
341 }
342 }
343 FuncInvocationKind::Host { .. } => Err(ResumableError::NotResumable),
344 }
345 }
346}
347
348#[derive(Clone, Debug)]
349pub struct FuncBody {
350 pub locals: Vec<Local>,
351 pub code: isa::Instructions,
352}