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.
27///
28/// This is used by [`AddrVec`] to create and read address types.
29pub(crate) trait Addr: Copy + core::fmt::Debug + core::fmt::Display + Eq {
30    fn new_unchecked(inner: usize) -> Self;
31
32    fn into_inner(self) -> usize;
33}
34
35pub(crate) struct AddrVec<A: Addr, Inst> {
36    inner: Vec<Inst>,
37    _phantom: PhantomData<A>,
38}
39
40impl<A: Addr, Inst> Default for AddrVec<A, Inst> {
41    fn default() -> Self {
42        Self {
43            inner: Vec::default(),
44            _phantom: PhantomData,
45        }
46    }
47}
48
49impl<A: Addr, Inst> AddrVec<A, Inst> {
50    /// Returns an instance by its address `addr`.
51    pub fn get(&self, addr: A) -> &Inst {
52        self.inner
53            .get(addr.into_inner())
54            .expect("addrs to always be valid")
55    }
56
57    /// Returns a mutable reference to some instance by its address `addr`.
58    pub fn get_mut(&mut self, addr: A) -> &mut Inst {
59        self.inner
60            .get_mut(addr.into_inner())
61            .expect("addrs to always be valid")
62    }
63
64    /// Inserts a new instance into the current [`Store`](crate::Store) and returns its address.
65    ///
66    /// This method should always be used to insert new instances, as it is the only safe way of creating addrs.
67    pub(crate) fn insert(&mut self, instance: Inst) -> A {
68        let new_addr = self.inner.len();
69        self.inner.push(instance);
70        A::new_unchecked(new_addr)
71    }
72
73    /// Mutably borrows two instances by their addresses and returns those
74    /// references. In the case where both given addresses are equal, `None` is
75    /// returned instead.
76    pub(crate) fn get_two_mut(
77        &mut self,
78        addr_one: A,
79        addr_two: A,
80    ) -> Option<(&mut Inst, &mut Inst)> {
81        let addr_one = addr_one.into_inner();
82        let addr_two = addr_two.into_inner();
83
84        match addr_one.cmp(&addr_two) {
85            Ordering::Greater => {
86                let (left, right) = self.inner.split_at_mut(addr_one);
87                let one = right.get_mut(0).expect(
88                    "this to be exactly the same as addr_one and addresses to always be valid",
89                );
90                let two = left
91                    .get_mut(addr_two)
92                    .expect("addresses to always be valid");
93
94                Some((one, two))
95            }
96            Ordering::Less => {
97                let (left, right) = self.inner.split_at_mut(addr_two);
98                let one = left
99                    .get_mut(addr_one)
100                    .expect("addresses to always be valid");
101                let two = right.get_mut(0).expect(
102                    "this to be exactly the same as addr_two and addresses to always be valid",
103                );
104
105                Some((one, two))
106            }
107            Ordering::Equal => None,
108        }
109    }
110}
111
112/// An address to a function instance that lives in a specific [`Store`](crate::execution::store::Store).
113#[derive(Copy, Clone, Debug, PartialEq, Eq)]
114pub struct FuncAddr(usize);
115
116impl core::fmt::Display for FuncAddr {
117    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118        write!(f, "function address {}", self.0)
119    }
120}
121
122impl Addr for FuncAddr {
123    fn new_unchecked(inner: usize) -> Self {
124        Self(inner)
125    }
126
127    fn into_inner(self) -> usize {
128        self.0
129    }
130}
131
132/// An address to a table instance that lives in a specific [`Store`](crate::Store).
133#[derive(Copy, Clone, Debug, PartialEq, Eq)]
134pub struct TableAddr(usize);
135
136impl core::fmt::Display for TableAddr {
137    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138        write!(f, "table address {}", self.0)
139    }
140}
141
142impl Addr for TableAddr {
143    fn new_unchecked(inner: usize) -> Self {
144        Self(inner)
145    }
146
147    fn into_inner(self) -> usize {
148        self.0
149    }
150}
151
152/// An address to a memory instance that lives in a specific [`Store`](crate::Store).
153#[derive(Copy, Clone, Debug, PartialEq, Eq)]
154pub struct MemAddr(usize);
155
156impl core::fmt::Display for MemAddr {
157    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
158        write!(f, "memory address {}", self.0)
159    }
160}
161
162impl Addr for MemAddr {
163    fn new_unchecked(inner: usize) -> Self {
164        Self(inner)
165    }
166
167    fn into_inner(self) -> usize {
168        self.0
169    }
170}
171
172/// An address to a global instance that lives in a specific [`Store`](crate::Store).
173#[derive(Copy, Clone, Debug, PartialEq, Eq)]
174pub struct GlobalAddr(usize);
175
176impl core::fmt::Display for GlobalAddr {
177    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
178        write!(f, "global address {}", self.0)
179    }
180}
181
182impl Addr for GlobalAddr {
183    fn new_unchecked(inner: usize) -> Self {
184        Self(inner)
185    }
186
187    /// Returns the inner integer represented by this [`GlobalAddr`].
188    fn into_inner(self) -> usize {
189        self.0
190    }
191}
192
193/// An address to an element instance that lives in a specific [`Store`](crate::Store).
194#[derive(Copy, Clone, Debug, PartialEq, Eq)]
195pub struct ElemAddr(usize);
196
197impl core::fmt::Display for ElemAddr {
198    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
199        write!(f, "element segment address {}", self.0)
200    }
201}
202
203impl Addr for ElemAddr {
204    fn new_unchecked(inner: usize) -> Self {
205        Self(inner)
206    }
207
208    fn into_inner(self) -> usize {
209        self.0
210    }
211}
212
213/// An address to a data instance that lives in a specific [`Store`](crate::Store).
214#[derive(Copy, Clone, Debug, PartialEq, Eq)]
215pub struct DataAddr(usize);
216
217impl core::fmt::Display for DataAddr {
218    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
219        write!(f, "data segment address {}", self.0)
220    }
221}
222
223impl Addr for DataAddr {
224    fn new_unchecked(inner: usize) -> Self {
225        Self(inner)
226    }
227
228    fn into_inner(self) -> usize {
229        self.0
230    }
231}
232
233/// An address to a module instance that lives in a specific [`Store`](crate::Store).
234#[derive(Copy, Clone, Debug, PartialEq, Eq)]
235pub struct ModuleAddr(usize);
236
237impl core::fmt::Display for ModuleAddr {
238    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239        write!(f, "module address {}", self.0)
240    }
241}
242
243impl Addr for ModuleAddr {
244    fn new_unchecked(inner: usize) -> Self {
245        Self(inner)
246    }
247
248    fn into_inner(self) -> usize {
249        self.0
250    }
251}