1use core::array;
2use core::convert::Infallible;
3use core::fmt;
4use core::mem::replace;
5use core::slice;
6#[cfg(feature = "cli")]
7use core::slice::SliceIndex;
8
9use crate::alloc::alloc::Global;
10use crate::alloc::prelude::*;
11use crate::alloc::{self, Vec};
12
13use super::{Address, IntoOutput, Output, Value, VmErrorKind};
14
15struct AssertSync<T>(T);
18unsafe impl<T> Sync for AssertSync<T> {}
19
20static EMPTY: AssertSync<Value> = AssertSync(Value::empty());
21
22#[derive(Debug)]
24#[cfg_attr(test, derive(PartialEq))]
25#[non_exhaustive]
26pub struct StackError {
27 addr: Address,
28}
29
30impl From<Infallible> for StackError {
31 #[inline]
32 fn from(value: Infallible) -> Self {
33 match value {}
34 }
35}
36
37impl fmt::Display for StackError {
38 #[inline]
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "Tried to access out-of-bounds stack entry {}", self.addr)
41 }
42}
43
44impl core::error::Error for StackError {}
45
46#[derive(Debug)]
48#[cfg_attr(test, derive(PartialEq))]
49#[non_exhaustive]
50pub struct SliceError {
51 addr: Address,
52 len: usize,
53 stack: usize,
54}
55
56impl fmt::Display for SliceError {
57 #[inline]
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(
60 f,
61 "Tried to access out-of-bounds stack slice {}-{} in 0-{}",
62 self.addr,
63 self.addr.offset() + self.len,
64 self.stack
65 )
66 }
67}
68
69impl core::error::Error for SliceError {}
70
71pub(crate) enum Pair<'a> {
72 Same(&'a mut Value),
73 Pair(&'a mut Value, &'a Value),
74}
75
76pub struct StoreError<E> {
78 kind: StoreErrorKind<E>,
79}
80
81impl<E> StoreError<E> {
82 #[inline]
83 pub(crate) fn into_kind(self) -> StoreErrorKind<E> {
84 self.kind
85 }
86}
87
88pub(crate) enum StoreErrorKind<E> {
89 Stack(StackError),
90 Error(E),
91}
92
93impl<E> From<StackError> for StoreError<E> {
94 #[inline]
95 fn from(error: StackError) -> Self {
96 Self {
97 kind: StoreErrorKind::Stack(error),
98 }
99 }
100}
101
102impl<E> StoreError<E> {
103 #[inline]
104 fn error(error: E) -> Self {
105 Self {
106 kind: StoreErrorKind::Error(error),
107 }
108 }
109}
110
111pub trait Memory {
113 fn slice_at(&self, addr: Address, len: usize) -> Result<&[Value], SliceError>;
132
133 fn slice_at_mut(&mut self, addr: Address, len: usize) -> Result<&mut [Value], SliceError>;
150
151 fn at_mut(&mut self, addr: Address) -> Result<&mut Value, StackError>;
167
168 fn array_at<const N: usize>(&self, addr: Address) -> Result<[&Value; N], SliceError>
170 where
171 Self: Sized,
172 {
173 let slice = self.slice_at(addr, N)?;
174 Ok(array::from_fn(|i| &slice[i]))
175 }
176}
177
178impl dyn Memory + '_ {
179 #[inline(always)]
204 pub fn store<O>(&mut self, out: Output, o: O) -> Result<(), StoreError<O::Error>>
205 where
206 O: IntoOutput,
207 {
208 if let Some(addr) = out.as_addr() {
209 *self.at_mut(addr)? = o.into_output().map_err(StoreError::error)?;
210 }
211
212 Ok(())
213 }
214}
215
216impl<M> Memory for &mut M
217where
218 M: Memory + ?Sized,
219{
220 #[inline]
221 fn slice_at(&self, addr: Address, len: usize) -> Result<&[Value], SliceError> {
222 (**self).slice_at(addr, len)
223 }
224
225 #[inline]
226 fn slice_at_mut(&mut self, addr: Address, len: usize) -> Result<&mut [Value], SliceError> {
227 (**self).slice_at_mut(addr, len)
228 }
229
230 #[inline]
231 fn at_mut(&mut self, addr: Address) -> Result<&mut Value, StackError> {
232 (**self).at_mut(addr)
233 }
234}
235
236impl<const N: usize> Memory for [Value; N] {
237 fn slice_at(&self, addr: Address, len: usize) -> Result<&[Value], SliceError> {
238 if len == 0 {
239 return Ok(&[]);
240 }
241
242 let start = addr.offset();
243
244 let Some(values) = start.checked_add(len).and_then(|end| self.get(start..end)) else {
245 return Err(SliceError {
246 addr,
247 len,
248 stack: N,
249 });
250 };
251
252 Ok(values)
253 }
254
255 fn slice_at_mut(&mut self, addr: Address, len: usize) -> Result<&mut [Value], SliceError> {
256 if len == 0 {
257 return Ok(&mut []);
258 }
259
260 let start = addr.offset();
261
262 let Some(values) = start
263 .checked_add(len)
264 .and_then(|end| self.get_mut(start..end))
265 else {
266 return Err(SliceError {
267 addr,
268 len,
269 stack: N,
270 });
271 };
272
273 Ok(values)
274 }
275
276 #[inline]
277 fn at_mut(&mut self, addr: Address) -> Result<&mut Value, StackError> {
278 let Some(value) = self.get_mut(addr.offset()) else {
279 return Err(StackError { addr });
280 };
281
282 Ok(value)
283 }
284}
285
286#[derive(Default, Debug)]
288pub struct Stack {
289 stack: Vec<Value>,
291 top: usize,
295}
296
297impl Stack {
298 #[inline]
300 pub(crate) const fn new() -> Self {
301 Self {
302 stack: Vec::new(),
303 top: 0,
304 }
305 }
306
307 #[inline(always)]
323 pub fn at(&self, addr: Address) -> &Value {
324 let n = self.top.wrapping_add(addr.offset());
325 self.stack.get(n).unwrap_or(&EMPTY.0)
326 }
327
328 #[inline]
346 pub fn at_mut(&mut self, addr: Address) -> Result<&mut Value, StackError> {
347 let n = self.top.wrapping_add(addr.offset());
348 self.stack.get_mut(n).ok_or(StackError { addr })
349 }
350
351 #[inline]
372 pub fn slice_at(&self, addr: Address, len: usize) -> Result<&[Value], SliceError> {
373 let stack_len = self.stack.len();
374
375 if let Some(slice) = inner_slice_at(&self.stack, self.top, addr, len) {
376 return Ok(slice);
377 }
378
379 Err(slice_error(stack_len, self.top, addr, len))
380 }
381
382 #[inline]
402 pub fn slice_at_mut(&mut self, addr: Address, len: usize) -> Result<&mut [Value], SliceError> {
403 let stack_len = self.stack.len();
404
405 if let Some(slice) = inner_slice_at_mut(&mut self.stack, self.top, addr, len) {
406 return Ok(slice);
407 }
408
409 Err(slice_error(stack_len, self.top, addr, len))
410 }
411
412 #[inline(always)]
437 pub fn store<O>(&mut self, out: Output, o: O) -> Result<(), StoreError<O::Error>>
438 where
439 O: IntoOutput,
440 {
441 if let Some(addr) = out.as_addr() {
442 *self.at_mut(addr)? = o.into_output().map_err(StoreError::error)?;
443 }
444
445 Ok(())
446 }
447
448 #[inline]
450 pub(crate) const fn addr(&self) -> Address {
451 Address::new(self.stack.len().saturating_sub(self.top))
452 }
453
454 #[inline]
456 pub(crate) fn resize(&mut self, size: usize) -> alloc::Result<()> {
457 if size == 0 {
458 return Ok(());
459 }
460
461 self.stack.try_resize_with(self.top + size, Value::empty)?;
462 Ok(())
463 }
464
465 #[inline]
467 pub(crate) fn with_capacity(capacity: usize) -> alloc::Result<Self> {
468 Ok(Self {
469 stack: Vec::try_with_capacity(capacity)?,
470 top: 0,
471 })
472 }
473
474 #[cfg(feature = "cli")]
481 #[inline]
482 pub(crate) fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[Value]>>::Output>
483 where
484 I: SliceIndex<[Value]>,
485 {
486 self.stack.get(index)
487 }
488
489 #[inline]
491 pub(crate) fn push<T>(&mut self, value: T) -> alloc::Result<()>
492 where
493 T: TryInto<Value, Error: Into<alloc::Error>>,
494 {
495 self.stack.try_push(value.try_into().map_err(Into::into)?)?;
496 Ok(())
497 }
498
499 #[inline]
501 pub(crate) fn truncate(&mut self, addr: Address) {
502 if let Some(len) = self.top.checked_add(addr.offset()) {
503 self.stack.truncate(len);
504 }
505 }
506
507 #[inline]
509 pub(crate) fn drain(&mut self) -> impl DoubleEndedIterator<Item = Value> + '_ {
510 self.stack.drain(self.top..)
511 }
512
513 #[inline]
515 pub(crate) fn clear(&mut self) {
516 self.stack.clear();
517 self.top = 0;
518 }
519
520 #[cfg_attr(not(feature = "tracing"), allow(unused))]
526 #[inline]
527 pub(crate) const fn top(&self) -> usize {
528 self.top
529 }
530
531 #[cfg_attr(not(feature = "tracing"), allow(unused))]
533 #[inline]
534 pub(crate) const fn len(&self) -> usize {
535 self.stack.len()
536 }
537
538 pub(crate) fn swap(&mut self, a: Address, b: Address) -> Result<(), StackError> {
540 if a == b {
541 return Ok(());
542 }
543
544 let a = self
545 .top
546 .checked_add(a.offset())
547 .filter(|&n| n < self.stack.len())
548 .ok_or(StackError { addr: a })?;
549
550 let b = self
551 .top
552 .checked_add(b.offset())
553 .filter(|&n| n < self.stack.len())
554 .ok_or(StackError { addr: b })?;
555
556 self.stack.swap(a, b);
557 Ok(())
558 }
559
560 #[tracing::instrument(skip_all)]
567 pub(crate) fn swap_top(&mut self, addr: Address, len: usize) -> Result<usize, VmErrorKind> {
568 let old_len = self.stack.len();
569
570 if len == 0 {
571 return Ok(replace(&mut self.top, old_len));
572 }
573
574 let Some(start) = self.top.checked_add(addr.offset()) else {
575 return Err(VmErrorKind::StackError {
576 error: StackError { addr },
577 });
578 };
579
580 let Some(new_len) = old_len.checked_add(len) else {
581 return Err(VmErrorKind::StackError {
582 error: StackError { addr },
583 });
584 };
585
586 if old_len < start + len {
587 return Err(VmErrorKind::StackError {
588 error: StackError { addr },
589 });
590 }
591
592 self.stack.try_reserve(len)?;
593
594 unsafe {
597 let ptr = self.stack.as_mut_ptr();
598 let from = slice::from_raw_parts_mut(ptr.add(start), len);
599
600 for (value, n) in from.iter_mut().zip(old_len..) {
601 ptr.add(n).write(replace(value, Value::empty()));
602 }
603
604 self.stack.set_len(new_len);
605 }
606
607 Ok(replace(&mut self.top, old_len))
608 }
609
610 #[inline]
612 #[tracing::instrument(skip_all)]
613 pub(crate) fn pop_stack_top(&mut self, top: usize) {
614 tracing::trace!(stack = self.stack.len(), self.top);
615 self.stack.truncate(self.top);
616 self.top = top;
617 }
618
619 pub(crate) fn copy(&mut self, from: Address, out: Output) -> Result<(), StackError> {
621 let Some(to) = out.as_addr() else {
622 return Ok(());
623 };
624
625 if from == to {
626 return Ok(());
627 }
628
629 let from = self.top.wrapping_add(from.offset());
630 let to = self.top.wrapping_add(to.offset());
631
632 if from.max(to) >= self.stack.len() {
633 return Err(StackError {
634 addr: Address::new(from.max(to).wrapping_sub(self.top)),
635 });
636 }
637
638 unsafe {
641 let ptr = self.stack.as_mut_ptr();
642 (*ptr.add(to)).clone_from(&*ptr.add(from).cast_const());
643 }
644
645 Ok(())
646 }
647
648 pub(crate) fn pair(&mut self, a: Address, b: Address) -> Result<Pair<'_>, StackError> {
650 if a == b {
651 return Ok(Pair::Same(self.at_mut(a)?));
652 }
653
654 let a = self
655 .top
656 .checked_add(a.offset())
657 .filter(|&n| n < self.stack.len())
658 .ok_or(StackError { addr: a })?;
659
660 let b = self
661 .top
662 .checked_add(b.offset())
663 .filter(|&n| n < self.stack.len())
664 .ok_or(StackError { addr: b })?;
665
666 let pair = unsafe {
667 let ptr = self.stack.as_mut_ptr();
668 Pair::Pair(&mut *ptr.add(a), &*ptr.add(b).cast_const())
669 };
670
671 Ok(pair)
672 }
673}
674
675impl Memory for Stack {
676 #[inline]
677 fn slice_at(&self, addr: Address, len: usize) -> Result<&[Value], SliceError> {
678 Stack::slice_at(self, addr, len)
679 }
680
681 #[inline]
682 fn slice_at_mut(&mut self, addr: Address, len: usize) -> Result<&mut [Value], SliceError> {
683 Stack::slice_at_mut(self, addr, len)
684 }
685
686 #[inline]
687 fn at_mut(&mut self, addr: Address) -> Result<&mut Value, StackError> {
688 Stack::at_mut(self, addr)
689 }
690}
691
692#[inline(always)]
693fn inner_slice_at(values: &[Value], top: usize, addr: Address, len: usize) -> Option<&[Value]> {
694 if len == 0 {
695 return Some(&[]);
696 }
697
698 let start = top.checked_add(addr.offset())?;
699 let end = start.checked_add(len)?;
700 values.get(start..end)
701}
702
703#[inline(always)]
704fn inner_slice_at_mut(
705 values: &mut [Value],
706 top: usize,
707 addr: Address,
708 len: usize,
709) -> Option<&mut [Value]> {
710 if len == 0 {
711 return Some(&mut []);
712 }
713
714 let start = top.checked_add(addr.offset())?;
715 let end = start.checked_add(len)?;
716 values.get_mut(start..end)
717}
718
719#[inline(always)]
720fn slice_error(stack: usize, bottom: usize, addr: Address, len: usize) -> SliceError {
721 SliceError {
722 addr,
723 len,
724 stack: stack.saturating_sub(bottom),
725 }
726}
727
728impl TryClone for Stack {
729 #[inline]
730 fn try_clone(&self) -> alloc::Result<Self> {
731 Ok(Self {
732 stack: self.stack.try_clone()?,
733 top: self.top,
734 })
735 }
736}
737
738impl TryFromIteratorIn<Value, Global> for Stack {
739 #[inline]
740 fn try_from_iter_in<T: IntoIterator<Item = Value>>(
741 iter: T,
742 alloc: Global,
743 ) -> alloc::Result<Self> {
744 Ok(Self {
745 stack: iter.into_iter().try_collect_in(alloc)?,
746 top: 0,
747 })
748 }
749}
750
751impl From<Vec<Value>> for Stack {
752 #[inline]
753 fn from(stack: Vec<Value>) -> Self {
754 Self { stack, top: 0 }
755 }
756}