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