vihaco_stdlib/execution_state/
execution.rs1use super::program;
7use super::{
8 ExecutionState,
9 messages::{BranchMessage, CallMessage},
10};
11
12use vihaco_abi::word::Word;
13use vihaco_module::PopStack;
14use vihaco_runtime::{Execute, NoMessage};
15
16impl ExecutionState {
17 fn enter(
19 &mut self,
20 function: usize,
21 arity: usize,
22 locals: usize,
23 target: u32,
24 indirect: bool,
25 ) -> eyre::Result<()> {
26 let required = arity
27 .checked_add(usize::from(indirect))
28 .ok_or_else(|| eyre::eyre!("argument count overflow"))?;
29 self.require_operands(required)?;
30 let ret_pc = self.pc;
31 let base = self.stack.len() - required;
32 let end = base
33 .checked_add(locals)
34 .ok_or_else(|| eyre::eyre!("frame size overflow"))?;
35 self.stack
36 .try_reserve(end.saturating_sub(self.stack.len()))?;
37 self.frames.try_reserve(1)?;
38 if indirect {
39 self.stack.pop();
40 }
41 self.stack.resize(end, 0);
42 self.frames.push(vihaco_abi::frame::Frame {
43 base,
44 local_count: locals,
45 span: (0, 0, 0),
46 function: Some(function),
47 ret_pc,
48 });
49 self.pc = target;
50 Ok(())
51 }
52}
53
54impl Execute<program::ConstI32> for ExecutionState {
55 type Message = NoMessage;
56 type Effect = ();
57 type Error = eyre::Report;
58
59 #[inline]
60 fn execute(&mut self, instruction: &program::ConstI32, _: NoMessage) -> eyre::Result<()> {
61 self.ensure_running()?;
62 self.stack.push(instruction.0);
63 Ok(())
64 }
65}
66
67impl Execute<program::ConstI64> for ExecutionState {
68 type Message = NoMessage;
69 type Effect = ();
70 type Error = eyre::Report;
71
72 #[inline]
73 fn execute(&mut self, instruction: &program::ConstI64, _: NoMessage) -> eyre::Result<()> {
74 self.ensure_running()?;
75 self.stack.push(instruction.0);
76 Ok(())
77 }
78}
79
80impl Execute<program::ConstU32> for ExecutionState {
81 type Message = NoMessage;
82 type Effect = ();
83 type Error = eyre::Report;
84
85 #[inline]
86 fn execute(&mut self, instruction: &program::ConstU32, _: NoMessage) -> eyre::Result<()> {
87 self.ensure_running()?;
88 self.stack.push(instruction.0);
89 Ok(())
90 }
91}
92
93impl Execute<program::ConstU64> for ExecutionState {
94 type Message = NoMessage;
95 type Effect = ();
96 type Error = eyre::Report;
97
98 #[inline]
99 fn execute(&mut self, instruction: &program::ConstU64, _: NoMessage) -> eyre::Result<()> {
100 self.ensure_running()?;
101 self.stack.push(instruction.0);
102 Ok(())
103 }
104}
105
106impl Execute<program::ConstF32> for ExecutionState {
107 type Message = NoMessage;
108 type Effect = ();
109 type Error = eyre::Report;
110
111 #[inline]
112 fn execute(&mut self, instruction: &program::ConstF32, _: NoMessage) -> eyre::Result<()> {
113 self.ensure_running()?;
114 self.stack.push(instruction.0);
115 Ok(())
116 }
117}
118
119impl Execute<program::ConstF64> for ExecutionState {
120 type Message = NoMessage;
121 type Effect = ();
122 type Error = eyre::Report;
123
124 #[inline]
125 fn execute(&mut self, instruction: &program::ConstF64, _: NoMessage) -> eyre::Result<()> {
126 self.ensure_running()?;
127 self.stack.push(instruction.0);
128 Ok(())
129 }
130}
131
132impl Execute<program::ConstBool> for ExecutionState {
133 type Message = NoMessage;
134 type Effect = ();
135 type Error = eyre::Report;
136
137 #[inline]
138 fn execute(&mut self, instruction: &program::ConstBool, _: NoMessage) -> eyre::Result<()> {
139 self.ensure_running()?;
140 self.stack.push(instruction.0);
141 Ok(())
142 }
143}
144
145impl Execute<program::ConstString> for ExecutionState {
146 type Message = NoMessage;
147 type Effect = ();
148 type Error = eyre::Report;
149
150 #[inline]
151 fn execute(&mut self, instruction: &program::ConstString, _: NoMessage) -> eyre::Result<()> {
152 self.ensure_running()?;
153 self.stack.push(instruction.0);
154 Ok(())
155 }
156}
157
158impl Execute<program::ConstFunctionRef> for ExecutionState {
159 type Message = NoMessage;
160 type Effect = ();
161 type Error = eyre::Report;
162
163 #[inline]
164 fn execute(
165 &mut self,
166 instruction: &program::ConstFunctionRef,
167 _: NoMessage,
168 ) -> eyre::Result<()> {
169 self.ensure_running()?;
170 self.stack.push(instruction.0);
171 Ok(())
172 }
173}
174
175impl Execute<program::ConstHeapRef> for ExecutionState {
176 type Message = NoMessage;
177 type Effect = ();
178 type Error = eyre::Report;
179
180 #[inline]
181 fn execute(&mut self, instruction: &program::ConstHeapRef, _: NoMessage) -> eyre::Result<()> {
182 self.ensure_running()?;
183 self.stack.push(instruction.0);
184 Ok(())
185 }
186}
187
188impl Execute<program::LoadI32> for ExecutionState {
189 type Message = NoMessage;
190 type Effect = ();
191 type Error = eyre::Report;
192
193 #[inline]
194 fn execute(&mut self, instruction: &program::LoadI32, _: NoMessage) -> eyre::Result<()> {
195 self.ensure_running()?;
196 let address = self.local_address(instruction.0)?;
197 self.stack.push(self.stack[address]);
198 Ok(())
199 }
200}
201
202impl Execute<program::LoadI64> for ExecutionState {
203 type Message = NoMessage;
204 type Effect = ();
205 type Error = eyre::Report;
206
207 #[inline]
208 fn execute(&mut self, instruction: &program::LoadI64, _: NoMessage) -> eyre::Result<()> {
209 self.ensure_running()?;
210 let address = self.local_address(instruction.0)?;
211 self.stack.push(self.stack[address]);
212 Ok(())
213 }
214}
215
216impl Execute<program::LoadU32> for ExecutionState {
217 type Message = NoMessage;
218 type Effect = ();
219 type Error = eyre::Report;
220
221 #[inline]
222 fn execute(&mut self, instruction: &program::LoadU32, _: NoMessage) -> eyre::Result<()> {
223 self.ensure_running()?;
224 let address = self.local_address(instruction.0)?;
225 self.stack.push(self.stack[address]);
226 Ok(())
227 }
228}
229
230impl Execute<program::LoadU64> for ExecutionState {
231 type Message = NoMessage;
232 type Effect = ();
233 type Error = eyre::Report;
234
235 #[inline]
236 fn execute(&mut self, instruction: &program::LoadU64, _: NoMessage) -> eyre::Result<()> {
237 self.ensure_running()?;
238 let address = self.local_address(instruction.0)?;
239 self.stack.push(self.stack[address]);
240 Ok(())
241 }
242}
243
244impl Execute<program::LoadF32> for ExecutionState {
245 type Message = NoMessage;
246 type Effect = ();
247 type Error = eyre::Report;
248
249 #[inline]
250 fn execute(&mut self, instruction: &program::LoadF32, _: NoMessage) -> eyre::Result<()> {
251 self.ensure_running()?;
252 let address = self.local_address(instruction.0)?;
253 self.stack.push(self.stack[address]);
254 Ok(())
255 }
256}
257
258impl Execute<program::LoadF64> for ExecutionState {
259 type Message = NoMessage;
260 type Effect = ();
261 type Error = eyre::Report;
262
263 #[inline]
264 fn execute(&mut self, instruction: &program::LoadF64, _: NoMessage) -> eyre::Result<()> {
265 self.ensure_running()?;
266 let address = self.local_address(instruction.0)?;
267 self.stack.push(self.stack[address]);
268 Ok(())
269 }
270}
271
272impl Execute<program::LoadBool> for ExecutionState {
273 type Message = NoMessage;
274 type Effect = ();
275 type Error = eyre::Report;
276
277 #[inline]
278 fn execute(&mut self, instruction: &program::LoadBool, _: NoMessage) -> eyre::Result<()> {
279 self.ensure_running()?;
280 let address = self.local_address(instruction.0)?;
281 self.stack.push(self.stack[address]);
282 Ok(())
283 }
284}
285
286impl Execute<program::StoreI32> for ExecutionState {
287 type Message = NoMessage;
288 type Effect = ();
289 type Error = eyre::Report;
290
291 #[inline]
292 fn execute(&mut self, instruction: &program::StoreI32, _: NoMessage) -> eyre::Result<()> {
293 self.ensure_running()?;
294 let address = self.local_address(instruction.0)?;
295 let value = <Self as PopStack<Word>>::pop(self)?;
296 self.stack[address] = value;
297 Ok(())
298 }
299}
300
301impl Execute<program::StoreI64> for ExecutionState {
302 type Message = NoMessage;
303 type Effect = ();
304 type Error = eyre::Report;
305
306 #[inline]
307 fn execute(&mut self, instruction: &program::StoreI64, _: NoMessage) -> eyre::Result<()> {
308 self.ensure_running()?;
309 let address = self.local_address(instruction.0)?;
310 let value = <Self as PopStack<Word>>::pop(self)?;
311 self.stack[address] = value;
312 Ok(())
313 }
314}
315
316impl Execute<program::StoreU32> for ExecutionState {
317 type Message = NoMessage;
318 type Effect = ();
319 type Error = eyre::Report;
320
321 #[inline]
322 fn execute(&mut self, instruction: &program::StoreU32, _: NoMessage) -> eyre::Result<()> {
323 self.ensure_running()?;
324 let address = self.local_address(instruction.0)?;
325 let value = <Self as PopStack<Word>>::pop(self)?;
326 self.stack[address] = value;
327 Ok(())
328 }
329}
330
331impl Execute<program::StoreU64> for ExecutionState {
332 type Message = NoMessage;
333 type Effect = ();
334 type Error = eyre::Report;
335
336 #[inline]
337 fn execute(&mut self, instruction: &program::StoreU64, _: NoMessage) -> eyre::Result<()> {
338 self.ensure_running()?;
339 let address = self.local_address(instruction.0)?;
340 let value = <Self as PopStack<Word>>::pop(self)?;
341 self.stack[address] = value;
342 Ok(())
343 }
344}
345
346impl Execute<program::StoreF32> for ExecutionState {
347 type Message = NoMessage;
348 type Effect = ();
349 type Error = eyre::Report;
350
351 #[inline]
352 fn execute(&mut self, instruction: &program::StoreF32, _: NoMessage) -> eyre::Result<()> {
353 self.ensure_running()?;
354 let address = self.local_address(instruction.0)?;
355 let value = <Self as PopStack<Word>>::pop(self)?;
356 self.stack[address] = value;
357 Ok(())
358 }
359}
360
361impl Execute<program::StoreF64> for ExecutionState {
362 type Message = NoMessage;
363 type Effect = ();
364 type Error = eyre::Report;
365
366 #[inline]
367 fn execute(&mut self, instruction: &program::StoreF64, _: NoMessage) -> eyre::Result<()> {
368 self.ensure_running()?;
369 let address = self.local_address(instruction.0)?;
370 let value = <Self as PopStack<Word>>::pop(self)?;
371 self.stack[address] = value;
372 Ok(())
373 }
374}
375
376impl Execute<program::StoreBool> for ExecutionState {
377 type Message = NoMessage;
378 type Effect = ();
379 type Error = eyre::Report;
380
381 #[inline]
382 fn execute(&mut self, instruction: &program::StoreBool, _: NoMessage) -> eyre::Result<()> {
383 self.ensure_running()?;
384 let address = self.local_address(instruction.0)?;
385 let value = <Self as PopStack<Word>>::pop(self)?;
386 self.stack[address] = value;
387 Ok(())
388 }
389}
390
391impl Execute<program::Dup> for ExecutionState {
392 type Message = NoMessage;
393 type Effect = ();
394 type Error = eyre::Report;
395
396 #[inline]
397 fn execute(&mut self, _instruction: &program::Dup, _: NoMessage) -> eyre::Result<()> {
398 self.ensure_running()?;
399 let value = self.peek_operand()?;
400 self.stack.push(value);
401 Ok(())
402 }
403}
404
405impl Execute<program::Return> for ExecutionState {
406 type Message = NoMessage;
407 type Effect = ();
408 type Error = eyre::Report;
409
410 #[inline]
411 fn execute(&mut self, instruction: &program::Return, _: NoMessage) -> eyre::Result<()> {
412 self.ensure_running()?;
413 let keep = instruction.0 as usize;
414 self.require_operands(keep)?;
415 let frame = *self
416 .frames
417 .last()
418 .ok_or_else(|| eyre::eyre!("no current frame"))?;
419 let len = self.stack.len();
420 self.stack.copy_within(len - keep..len, frame.base);
421 self.stack.truncate(frame.base + keep);
422 self.frames.pop();
423 if self.frames.is_empty() {
424 self.halted = true;
425 } else {
426 self.pc = frame.ret_pc;
427 }
428 Ok(())
429 }
430}
431
432impl Execute<program::Halt> for ExecutionState {
433 type Message = NoMessage;
434 type Effect = ();
435 type Error = eyre::Report;
436
437 #[inline]
438 fn execute(&mut self, _instruction: &program::Halt, _: NoMessage) -> eyre::Result<()> {
439 self.ensure_running()?;
440 self.halted = true;
441 Ok(())
442 }
443}
444
445impl Execute<program::Branch> for ExecutionState {
446 type Message = BranchMessage;
447 type Effect = ();
448 type Error = eyre::Report;
449 #[inline]
450 fn execute(&mut self, _: &program::Branch, message: BranchMessage) -> eyre::Result<()> {
451 self.ensure_running()?;
452 self.pc = message.target;
453 Ok(())
454 }
455}
456
457impl Execute<program::ConditionalBranch> for ExecutionState {
458 type Message = BranchMessage;
459 type Effect = ();
460 type Error = eyre::Report;
461 #[inline]
462 fn execute(
463 &mut self,
464 _: &program::ConditionalBranch,
465 message: BranchMessage,
466 ) -> eyre::Result<()> {
467 self.ensure_running()?;
468 self.pc = message.target;
469 Ok(())
470 }
471}
472
473impl Execute<program::Call> for ExecutionState {
474 type Message = CallMessage;
475 type Effect = ();
476 type Error = eyre::Report;
477 #[inline]
478 fn execute(&mut self, _: &program::Call, message: CallMessage) -> eyre::Result<()> {
479 self.enter(
480 message.function,
481 message.arity,
482 message.locals,
483 message.target,
484 message.indirect,
485 )
486 }
487}
488
489impl Execute<program::IndirectCall> for ExecutionState {
490 type Message = CallMessage;
491 type Effect = ();
492 type Error = eyre::Report;
493 #[inline]
494 fn execute(&mut self, _: &program::IndirectCall, message: CallMessage) -> eyre::Result<()> {
495 self.enter(
496 message.function,
497 message.arity,
498 message.locals,
499 message.target,
500 message.indirect,
501 )
502 }
503}