1use core::array;
2use core::convert::Infallible;
3use core::fmt;
4use core::mem::replace;
5use core::slice;
6
7use crate::alloc::alloc::Global;
8use crate::alloc::prelude::*;
9use crate::alloc::{self, Vec};
10use crate::runtime::{InstAddress, Output, Value, VmErrorKind};
11
12struct AssertSync<T>(T);
15unsafe impl<T> Sync for AssertSync<T> {}
16
17static EMPTY: AssertSync<Value> = AssertSync(Value::empty());
18
19#[derive(Debug)]
21#[cfg_attr(test, derive(PartialEq))]
22#[non_exhaustive]
23pub struct StackError {
24 addr: InstAddress,
25}
26
27impl From<Infallible> for StackError {
28 #[inline]
29 fn from(value: Infallible) -> Self {
30 match value {}
31 }
32}
33
34impl fmt::Display for StackError {
35 #[inline]
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "Tried to access out-of-bounds stack entry {}", self.addr)
38 }
39}
40
41impl core::error::Error for StackError {}
42
43#[derive(Debug)]
45#[cfg_attr(test, derive(PartialEq))]
46#[non_exhaustive]
47pub struct SliceError {
48 addr: InstAddress,
49 len: usize,
50 stack: usize,
51}
52
53impl fmt::Display for SliceError {
54 #[inline]
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 write!(
57 f,
58 "Tried to access out-of-bounds stack slice {}-{} in 0-{}",
59 self.addr,
60 self.addr.offset() + self.len,
61 self.stack
62 )
63 }
64}
65
66impl core::error::Error for SliceError {}
67
68pub(crate) enum Pair<'a> {
69 Same(&'a mut Value),
70 Pair(&'a mut Value, &'a Value),
71}
72
73pub trait Memory {
75 fn slice_at(&self, addr: InstAddress, len: usize) -> Result<&[Value], SliceError>;
95
96 fn slice_at_mut(&mut self, addr: InstAddress, len: usize) -> Result<&mut [Value], SliceError>;
114
115 fn at_mut(&mut self, addr: InstAddress) -> Result<&mut Value, StackError>;
133
134 fn array_at<const N: usize>(&self, addr: InstAddress) -> Result<[&Value; N], SliceError>
136 where
137 Self: Sized,
138 {
139 let slice = self.slice_at(addr, N)?;
140 Ok(array::from_fn(|i| &slice[i]))
141 }
142}
143
144impl<M> Memory for &mut M
145where
146 M: Memory + ?Sized,
147{
148 #[inline]
149 fn slice_at(&self, addr: InstAddress, len: usize) -> Result<&[Value], SliceError> {
150 (**self).slice_at(addr, len)
151 }
152
153 #[inline]
154 fn slice_at_mut(&mut self, addr: InstAddress, len: usize) -> Result<&mut [Value], SliceError> {
155 (**self).slice_at_mut(addr, len)
156 }
157
158 #[inline]
159 fn at_mut(&mut self, addr: InstAddress) -> Result<&mut Value, StackError> {
160 (**self).at_mut(addr)
161 }
162}
163
164impl<const N: usize> Memory for [Value; N] {
165 fn slice_at(&self, addr: InstAddress, len: usize) -> Result<&[Value], SliceError> {
166 if len == 0 {
167 return Ok(&[]);
168 }
169
170 let start = addr.offset();
171
172 let Some(values) = start.checked_add(len).and_then(|end| self.get(start..end)) else {
173 return Err(SliceError {
174 addr,
175 len,
176 stack: N,
177 });
178 };
179
180 Ok(values)
181 }
182
183 fn slice_at_mut(&mut self, addr: InstAddress, len: usize) -> Result<&mut [Value], SliceError> {
184 if len == 0 {
185 return Ok(&mut []);
186 }
187
188 let start = addr.offset();
189
190 let Some(values) = start
191 .checked_add(len)
192 .and_then(|end| self.get_mut(start..end))
193 else {
194 return Err(SliceError {
195 addr,
196 len,
197 stack: N,
198 });
199 };
200
201 Ok(values)
202 }
203
204 #[inline]
205 fn at_mut(&mut self, addr: InstAddress) -> Result<&mut Value, StackError> {
206 let Some(value) = self.get_mut(addr.offset()) else {
207 return Err(StackError { addr });
208 };
209
210 Ok(value)
211 }
212}
213
214#[derive(Default, Debug)]
216pub struct Stack {
217 stack: Vec<Value>,
219 top: usize,
223}
224
225impl Stack {
226 pub(crate) const fn new() -> Self {
228 Self {
229 stack: Vec::new(),
230 top: 0,
231 }
232 }
233
234 #[inline(always)]
250 pub fn at(&self, addr: InstAddress) -> &Value {
251 self.top
252 .checked_add(addr.offset())
253 .and_then(|n| self.stack.get(n))
254 .unwrap_or(&EMPTY.0)
255 }
256
257 pub fn at_mut(&mut self, addr: InstAddress) -> Result<&mut Value, StackError> {
275 self.top
276 .checked_add(addr.offset())
277 .and_then(|n| self.stack.get_mut(n))
278 .ok_or(StackError { addr })
279 }
280
281 pub fn slice_at(&self, addr: InstAddress, len: usize) -> Result<&[Value], SliceError> {
302 let stack_len = self.stack.len();
303
304 if let Some(slice) = inner_slice_at(&self.stack, self.top, addr, len) {
305 return Ok(slice);
306 }
307
308 Err(slice_error(stack_len, self.top, addr, len))
309 }
310
311 pub fn slice_at_mut(
331 &mut self,
332 addr: InstAddress,
333 len: usize,
334 ) -> Result<&mut [Value], SliceError> {
335 let stack_len = self.stack.len();
336
337 if let Some(slice) = inner_slice_at_mut(&mut self.stack, self.top, addr, len) {
338 return Ok(slice);
339 }
340
341 Err(slice_error(stack_len, self.top, addr, len))
342 }
343
344 #[inline]
346 pub(crate) const fn addr(&self) -> InstAddress {
347 InstAddress::new(self.stack.len().saturating_sub(self.top))
348 }
349
350 pub(crate) fn resize(&mut self, size: usize) -> alloc::Result<()> {
352 if size == 0 {
353 return Ok(());
354 }
355
356 self.stack.try_resize_with(self.top + size, Value::empty)?;
357 Ok(())
358 }
359
360 pub(crate) fn with_capacity(capacity: usize) -> alloc::Result<Self> {
362 Ok(Self {
363 stack: Vec::try_with_capacity(capacity)?,
364 top: 0,
365 })
366 }
367
368 #[cfg(feature = "cli")]
375 pub(crate) fn get<I>(&self, index: I) -> Option<&<I as slice::SliceIndex<[Value]>>::Output>
376 where
377 I: slice::SliceIndex<[Value]>,
378 {
379 self.stack.get(index)
380 }
381
382 pub(crate) fn push<T>(&mut self, value: T) -> alloc::Result<()>
384 where
385 T: TryInto<Value, Error: Into<alloc::Error>>,
386 {
387 self.stack.try_push(value.try_into().map_err(Into::into)?)?;
388 Ok(())
389 }
390
391 pub(crate) fn truncate(&mut self, addr: InstAddress) {
393 if let Some(len) = self.top.checked_add(addr.offset()) {
394 self.stack.truncate(len);
395 }
396 }
397
398 pub(crate) fn drain(&mut self) -> impl DoubleEndedIterator<Item = Value> + '_ {
400 self.stack.drain(self.top..)
401 }
402
403 pub(crate) fn clear(&mut self) {
405 self.stack.clear();
406 self.top = 0;
407 }
408
409 #[cfg_attr(not(feature = "tracing"), allow(unused))]
415 pub(crate) const fn top(&self) -> usize {
416 self.top
417 }
418
419 #[cfg_attr(not(feature = "tracing"), allow(unused))]
421 pub(crate) const fn len(&self) -> usize {
422 self.stack.len()
423 }
424
425 pub(crate) fn swap(&mut self, a: InstAddress, b: InstAddress) -> Result<(), StackError> {
427 if a == b {
428 return Ok(());
429 }
430
431 let a = self
432 .top
433 .checked_add(a.offset())
434 .filter(|&n| n < self.stack.len())
435 .ok_or(StackError { addr: a })?;
436
437 let b = self
438 .top
439 .checked_add(b.offset())
440 .filter(|&n| n < self.stack.len())
441 .ok_or(StackError { addr: b })?;
442
443 self.stack.swap(a, b);
444 Ok(())
445 }
446
447 #[tracing::instrument(skip_all)]
454 pub(crate) fn swap_top(&mut self, addr: InstAddress, len: usize) -> Result<usize, VmErrorKind> {
455 let old_len = self.stack.len();
456
457 if len == 0 {
458 return Ok(replace(&mut self.top, old_len));
459 }
460
461 let Some(start) = self.top.checked_add(addr.offset()) else {
462 return Err(VmErrorKind::StackError {
463 error: StackError { addr },
464 });
465 };
466
467 let Some(new_len) = old_len.checked_add(len) else {
468 return Err(VmErrorKind::StackError {
469 error: StackError { addr },
470 });
471 };
472
473 if old_len < start + len {
474 return Err(VmErrorKind::StackError {
475 error: StackError { addr },
476 });
477 }
478
479 self.stack.try_reserve(len)?;
480
481 unsafe {
484 let ptr = self.stack.as_mut_ptr();
485 let from = slice::from_raw_parts_mut(ptr.add(start), len);
486
487 for (value, n) in from.iter_mut().zip(old_len..) {
488 ptr.add(n).write(replace(value, Value::empty()));
489 }
490
491 self.stack.set_len(new_len);
492 }
493
494 Ok(replace(&mut self.top, old_len))
495 }
496
497 #[tracing::instrument(skip_all)]
499 pub(crate) fn pop_stack_top(&mut self, top: usize) {
500 tracing::trace!(stack = self.stack.len(), self.top);
501 self.stack.truncate(self.top);
502 self.top = top;
503 }
504
505 pub(crate) fn copy(&mut self, from: InstAddress, out: Output) -> Result<(), StackError> {
507 let Some(to) = out.as_addr() else {
508 return Ok(());
509 };
510
511 if from == to {
512 return Ok(());
513 }
514
515 let from = self.top.wrapping_add(from.offset());
516 let to = self.top.wrapping_add(to.offset());
517
518 if from.max(to) >= self.stack.len() {
519 return Err(StackError {
520 addr: InstAddress::new(from.max(to).wrapping_sub(self.top)),
521 });
522 }
523
524 unsafe {
527 let ptr = self.stack.as_mut_ptr();
528 (*ptr.add(to)).clone_from(&*ptr.add(from).cast_const());
529 }
530
531 Ok(())
532 }
533
534 pub(crate) fn pair(&mut self, a: InstAddress, b: InstAddress) -> Result<Pair<'_>, StackError> {
536 if a == b {
537 return Ok(Pair::Same(self.at_mut(a)?));
538 }
539
540 let a = self
541 .top
542 .checked_add(a.offset())
543 .filter(|&n| n < self.stack.len())
544 .ok_or(StackError { addr: a })?;
545
546 let b = self
547 .top
548 .checked_add(b.offset())
549 .filter(|&n| n < self.stack.len())
550 .ok_or(StackError { addr: b })?;
551
552 let pair = unsafe {
553 let ptr = self.stack.as_mut_ptr();
554 Pair::Pair(&mut *ptr.add(a), &*ptr.add(b).cast_const())
555 };
556
557 Ok(pair)
558 }
559}
560
561impl Memory for Stack {
562 #[inline]
563 fn slice_at(&self, addr: InstAddress, len: usize) -> Result<&[Value], SliceError> {
564 Stack::slice_at(self, addr, len)
565 }
566
567 #[inline]
568 fn slice_at_mut(&mut self, addr: InstAddress, len: usize) -> Result<&mut [Value], SliceError> {
569 Stack::slice_at_mut(self, addr, len)
570 }
571
572 #[inline]
573 fn at_mut(&mut self, addr: InstAddress) -> Result<&mut Value, StackError> {
574 Stack::at_mut(self, addr)
575 }
576}
577
578#[inline(always)]
579fn inner_slice_at(values: &[Value], top: usize, addr: InstAddress, len: usize) -> Option<&[Value]> {
580 if len == 0 {
581 return Some(&[]);
582 }
583
584 let start = top.checked_add(addr.offset())?;
585 let end = start.checked_add(len)?;
586 values.get(start..end)
587}
588
589#[inline(always)]
590fn inner_slice_at_mut(
591 values: &mut [Value],
592 top: usize,
593 addr: InstAddress,
594 len: usize,
595) -> Option<&mut [Value]> {
596 if len == 0 {
597 return Some(&mut []);
598 }
599
600 let start = top.checked_add(addr.offset())?;
601 let end = start.checked_add(len)?;
602 values.get_mut(start..end)
603}
604
605#[inline(always)]
606fn slice_error(stack: usize, bottom: usize, addr: InstAddress, len: usize) -> SliceError {
607 SliceError {
608 addr,
609 len,
610 stack: stack.saturating_sub(bottom),
611 }
612}
613
614impl TryClone for Stack {
615 fn try_clone(&self) -> alloc::Result<Self> {
616 Ok(Self {
617 stack: self.stack.try_clone()?,
618 top: self.top,
619 })
620 }
621}
622
623impl TryFromIteratorIn<Value, Global> for Stack {
624 #[inline]
625 fn try_from_iter_in<T: IntoIterator<Item = Value>>(
626 iter: T,
627 alloc: Global,
628 ) -> alloc::Result<Self> {
629 Ok(Self {
630 stack: iter.into_iter().try_collect_in(alloc)?,
631 top: 0,
632 })
633 }
634}
635
636impl From<Vec<Value>> for Stack {
637 fn from(stack: Vec<Value>) -> Self {
638 Self { stack, top: 0 }
639 }
640}