wasm/execution/store/
addrs.rs

1//! Type definitions for addr types
2//!
3//! An addr (short for: address) is a dynamic index only known at runtime into a
4//! store. There are addr types for different index spaces, such as memories,
5//! globals or functions [`FuncAddr`].
6//!
7//!
8//! # A Note About Accessor Methods on Store Address Spaces
9//! At first, we stored a [`Vec`] directly in the [`Store`](crate::Store) for
10//! function instances, table instances, etc. However, implementing accessor
11//! methods on the [`Store`](crate::Store) causes problems, because either the
12//! entire [`Store`](crate::Store) has to be passed as an argument (preventing
13//! partial borrows) or a specific [`Vec`] has to be passed as an argument
14//! (exposing [`Store`](crate::Store) implementation details through a pretty
15//! unergonomic API).
16//!
17//! Because both of these solutions were not sufficient, a choice was made for
18//! newtype wrappers around every address space. This way, partial borrows of
19//! the [`Store`](crate::Store) are possible, while providing a nice API, even
20//! if it is just used internally.
21
22use core::{cmp::Ordering, marker::PhantomData};
23
24use alloc::vec::Vec;
25
26/// A trait for all address types.
27pub trait Addr: Copy + core::fmt::Debug + core::fmt::Display + Eq {
28    fn new(inner: usize) -> Self;
29
30    fn into_inner(self) -> usize;
31}
32
33pub(crate) struct AddrVec<A: Addr, Inst> {
34    inner: Vec<Inst>,
35    _phantom: PhantomData<A>,
36}
37
38impl<A: Addr, Inst> Default for AddrVec<A, Inst> {
39    fn default() -> Self {
40        Self {
41            inner: Vec::default(),
42            _phantom: PhantomData,
43        }
44    }
45}
46
47impl<A: Addr, Inst> AddrVec<A, Inst> {
48    /// Returns an instance by its address `addr`.
49    ///
50    /// # Safety
51    ///
52    /// The caller must ensure that the given address is valid in this vector.
53    pub unsafe fn get(&self, addr: A) -> &Inst {
54        // TODO use unwrap_unchecked instead
55        self.inner
56            .get(addr.into_inner())
57            .expect("addrs to always be valid")
58    }
59
60    /// Returns a mutable reference to some instance by its address `addr`.
61    ///
62    /// # Safety
63    ///
64    /// The caller must ensure that the given address is valid in this vector.
65    pub unsafe fn get_mut(&mut self, addr: A) -> &mut Inst {
66        // TODO use unwrap_unchecked instead
67        self.inner
68            .get_mut(addr.into_inner())
69            .expect("addrs to always be valid")
70    }
71
72    /// Inserts a new instance into the current [`Store`](crate::Store) and returns its address.
73    ///
74    /// This method should always be used to insert new instances, as it is the only safe way of creating addrs.
75    pub(crate) fn insert(&mut self, instance: Inst) -> A {
76        let new_addr = self.inner.len();
77        self.inner.push(instance);
78        A::new(new_addr)
79    }
80
81    /// Mutably borrows two instances by their addresses and returns those
82    /// references. In the case where both given addresses are equal, `None` is
83    /// returned instead.
84    ///
85    /// # Safety
86    ///
87    /// The caller must ensure that both given addresses are valid in this
88    /// vector.
89    pub(crate) unsafe fn get_two_mut(
90        &mut self,
91        addr_one: A,
92        addr_two: A,
93    ) -> Option<(&mut Inst, &mut Inst)> {
94        let addr_one = addr_one.into_inner();
95        let addr_two = addr_two.into_inner();
96
97        match addr_one.cmp(&addr_two) {
98            Ordering::Greater => {
99                let (left, right) = self.inner.split_at_mut(addr_one);
100                let one = right.get_mut(0).expect(
101                    "this to be exactly the same as addr_one and addresses to always be valid",
102                );
103                let two = left
104                    .get_mut(addr_two)
105                    .expect("addresses to always be valid");
106
107                Some((one, two))
108            }
109            Ordering::Less => {
110                let (left, right) = self.inner.split_at_mut(addr_two);
111                let one = left
112                    .get_mut(addr_one)
113                    .expect("addresses to always be valid");
114                let two = right.get_mut(0).expect(
115                    "this to be exactly the same as addr_two and addresses to always be valid",
116                );
117
118                Some((one, two))
119            }
120            Ordering::Equal => None,
121        }
122    }
123}
124
125/// An address to a function instance that lives in a specific [`Store`](crate::execution::store::Store).
126#[derive(Copy, Clone, Debug, PartialEq, Eq)]
127pub struct FuncAddr(usize);
128
129impl core::fmt::Display for FuncAddr {
130    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
131        write!(f, "function address {}", self.0)
132    }
133}
134
135impl Addr for FuncAddr {
136    fn new(inner: usize) -> Self {
137        Self(inner)
138    }
139
140    fn into_inner(self) -> usize {
141        self.0
142    }
143}
144
145/// An address to a table instance that lives in a specific [`Store`](crate::Store).
146#[derive(Copy, Clone, Debug, PartialEq, Eq)]
147pub struct TableAddr(usize);
148
149impl core::fmt::Display for TableAddr {
150    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
151        write!(f, "table address {}", self.0)
152    }
153}
154
155impl Addr for TableAddr {
156    fn new(inner: usize) -> Self {
157        Self(inner)
158    }
159
160    fn into_inner(self) -> usize {
161        self.0
162    }
163}
164
165/// An address to a memory instance that lives in a specific [`Store`](crate::Store).
166#[derive(Copy, Clone, Debug, PartialEq, Eq)]
167pub struct MemAddr(usize);
168
169impl core::fmt::Display for MemAddr {
170    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
171        write!(f, "memory address {}", self.0)
172    }
173}
174
175impl Addr for MemAddr {
176    fn new(inner: usize) -> Self {
177        Self(inner)
178    }
179
180    fn into_inner(self) -> usize {
181        self.0
182    }
183}
184
185/// An address to a global instance that lives in a specific [`Store`](crate::Store).
186#[derive(Copy, Clone, Debug, PartialEq, Eq)]
187pub struct GlobalAddr(usize);
188
189impl core::fmt::Display for GlobalAddr {
190    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
191        write!(f, "global address {}", self.0)
192    }
193}
194
195impl Addr for GlobalAddr {
196    fn new(inner: usize) -> Self {
197        Self(inner)
198    }
199
200    /// Returns the inner integer represented by this [`GlobalAddr`].
201    fn into_inner(self) -> usize {
202        self.0
203    }
204}
205
206/// An address to an element instance that lives in a specific [`Store`](crate::Store).
207#[derive(Copy, Clone, Debug, PartialEq, Eq)]
208pub struct ElemAddr(usize);
209
210impl core::fmt::Display for ElemAddr {
211    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212        write!(f, "element segment address {}", self.0)
213    }
214}
215
216impl Addr for ElemAddr {
217    fn new(inner: usize) -> Self {
218        Self(inner)
219    }
220
221    fn into_inner(self) -> usize {
222        self.0
223    }
224}
225
226/// An address to a data instance that lives in a specific [`Store`](crate::Store).
227#[derive(Copy, Clone, Debug, PartialEq, Eq)]
228pub struct DataAddr(usize);
229
230impl core::fmt::Display for DataAddr {
231    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
232        write!(f, "data segment address {}", self.0)
233    }
234}
235
236impl Addr for DataAddr {
237    fn new(inner: usize) -> Self {
238        Self(inner)
239    }
240
241    fn into_inner(self) -> usize {
242        self.0
243    }
244}
245
246/// An address to a module instance that lives in a specific [`Store`](crate::Store).
247#[derive(Copy, Clone, Debug, PartialEq, Eq)]
248pub struct ModuleAddr(usize);
249
250impl core::fmt::Display for ModuleAddr {
251    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
252        write!(f, "module address {}", self.0)
253    }
254}
255
256impl Addr for ModuleAddr {
257    fn new(inner: usize) -> Self {
258        Self(inner)
259    }
260
261    fn into_inner(self) -> usize {
262        self.0
263    }
264}