Coverage Report

Created: 2026-08-27 12:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/src/execution/runtime_structure/addresses.rs
Line
Count
Source
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
22
use alloc::vec::Vec;
23
use core::{cmp::Ordering, marker::PhantomData};
24
25
/// A trait for all address types.
26
pub(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
32
pub(crate) struct AddrVec<A: Addr, Inst> {
33
    inner: Vec<Inst>,
34
    _phantom: PhantomData<A>,
35
}
36
37
impl<A: Addr, Inst> Default for AddrVec<A, Inst> {
38
3.43k
    fn default() -> Self {
39
3.43k
        Self {
40
3.43k
            inner: Vec::default(),
41
3.43k
            _phantom: PhantomData,
42
3.43k
        }
43
3.43k
    }
44
}
45
46
impl<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
1.96M
    pub unsafe fn get(&self, addr: A) -> &Inst {
53
1.96M
        let addr = addr.into_inner();
54
55
1.96M
        debug_assert!(self.inner.get(addr).is_some());
56
        // SAFETY: The caller ensures that the given address is valid in this vector. Because this
57
        // vector cannot shrink the address must point to an existing element.
58
1.96M
        unsafe { self.inner.get_unchecked(addr) }
59
1.96M
    }
60
61
    /// Returns a mutable reference to some instance by its address `addr`.
62
    ///
63
    /// # Safety
64
    ///
65
    /// The caller must ensure that the given address is valid in this vector.
66
942k
    pub unsafe fn get_mut(&mut self, addr: A) -> &mut Inst {
67
942k
        let addr = addr.into_inner();
68
69
942k
        debug_assert!(self.inner.get_mut(addr).is_some());
70
        // SAFETY: The caller ensures that the given address is valid in this vector. Because this
71
        // vector cannot shrink, the address must still be valid.
72
942k
        unsafe { self.inner.get_unchecked_mut(addr) }
73
942k
    }
74
75
    /// Inserts a new instance into the current [`Store`](crate::Store) and returns its address.
76
    ///
77
    /// This method should always be used to insert new instances, as it is the only safe way of creating addrs.
78
12.5k
    pub fn insert(&mut self, instance: Inst) -> A {
79
12.5k
        let new_addr = self.inner.len();
80
12.5k
        self.inner.push(instance);
81
12.5k
        A::new(new_addr)
82
12.5k
    }
83
84
    /// Mutably borrows two instances by their addresses and returns those
85
    /// references. In the case where both given addresses are equal, `None` is
86
    /// returned instead.
87
    ///
88
    /// # Safety
89
    ///
90
    /// The caller must ensure that both given addresses are valid in this
91
    /// vector.
92
6
    pub unsafe fn get_two_mut(
93
6
        &mut self,
94
6
        addr_one: A,
95
6
        addr_two: A,
96
6
    ) -> Option<(&mut Inst, &mut Inst)> {
97
6
        let addr_one = addr_one.into_inner();
98
6
        let addr_two = addr_two.into_inner();
99
100
6
        match addr_one.cmp(&addr_two) {
101
            Ordering::Greater => {
102
1
                debug_assert!(self.inner.get(addr_one).is_some());
103
                // SAFETY: The caller ensures that the given address is valid in this vector.
104
                // Because this vector cannot shrink, the address must still point to an existing
105
                // element.
106
1
                let (left, right) = unsafe { self.inner.split_at_mut_unchecked(addr_one) };
107
108
1
                debug_assert!(!right.is_empty());
109
                // SAFETY: `right` starts with the element pointed to by `addr_one`, which was valid
110
                // in this vector. Therefore, `right` must contain at least one element.
111
1
                let one = unsafe { right.get_unchecked_mut(0) };
112
113
1
                debug_assert!(left.get(addr_two).is_some());
114
                // SAFETY: `left` contains the first `addr_one` elements from this vector. Because
115
                // `addr_one` is greater than `addr_two`, `addr_two` must be a valid index in
116
                // `left`.
117
1
                let two = unsafe { left.get_unchecked_mut(addr_two) };
118
119
1
                Some((one, two))
120
            }
121
            Ordering::Less => {
122
5
                debug_assert!(self.inner.get(addr_two).is_some());
123
                // SAFETY: The caller ensures that the given address is valid in this vector.
124
                // Because this vector cannot shrink, the address must still point to an existing
125
                // element.
126
5
                let (left, right) = unsafe { self.inner.split_at_mut_unchecked(addr_two) };
127
128
5
                debug_assert!(left.get(addr_one).is_some());
129
                // SAFETY: `left` contains the first `addr_two` elements from this vector. Because
130
                // `addr_one` is less than `addr_two`, `addr_one` must be a valid index in `left`.
131
5
                let one = unsafe { left.get_unchecked_mut(addr_one) };
132
133
5
                debug_assert!(!right.is_empty());
134
                // SAFETY: `right` starts with the element points to by `addr_two`, which was valid
135
                // in this vector. Therefore, `right` must contain at least one element.
136
5
                let two = unsafe { right.get_unchecked_mut(0) };
137
138
5
                Some((one, two))
139
            }
140
0
            Ordering::Equal => None,
141
        }
142
6
    }
143
}
144
145
/// An address to a function instance that lives in a specific [`Store`](crate::Store).
146
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
147
pub struct FuncAddr(usize);
148
149
impl core::fmt::Display for FuncAddr {
150
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
151
0
        write!(f, "function address {}", self.0)
152
0
    }
153
}
154
155
impl Addr for FuncAddr {
156
7.59k
    fn new(inner: usize) -> Self {
157
7.59k
        Self(inner)
158
7.59k
    }
159
160
412k
    fn into_inner(self) -> usize {
161
412k
        self.0
162
412k
    }
163
}
164
165
/// An address to a table instance that lives in a specific [`Store`](crate::Store).
166
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
167
pub struct TableAddr(usize);
168
169
impl core::fmt::Display for TableAddr {
170
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
171
0
        write!(f, "table address {}", self.0)
172
0
    }
173
}
174
175
impl Addr for TableAddr {
176
504
    fn new(inner: usize) -> Self {
177
504
        Self(inner)
178
504
    }
179
180
101k
    fn into_inner(self) -> usize {
181
101k
        self.0
182
101k
    }
183
}
184
185
/// An address to a memory instance that lives in a specific [`Store`](crate::Store).
186
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
187
pub struct MemAddr(usize);
188
189
impl core::fmt::Display for MemAddr {
190
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
191
0
        write!(f, "memory address {}", self.0)
192
0
    }
193
}
194
195
impl Addr for MemAddr {
196
546
    fn new(inner: usize) -> Self {
197
546
        Self(inner)
198
546
    }
199
200
937k
    fn into_inner(self) -> usize {
201
937k
        self.0
202
937k
    }
203
}
204
205
/// An address to a global instance that lives in a specific [`Store`](crate::Store).
206
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
207
pub struct GlobalAddr(usize);
208
209
impl core::fmt::Display for GlobalAddr {
210
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211
0
        write!(f, "global address {}", self.0)
212
0
    }
213
}
214
215
impl Addr for GlobalAddr {
216
681
    fn new(inner: usize) -> Self {
217
681
        Self(inner)
218
681
    }
219
220
    /// Returns the inner integer represented by this [`GlobalAddr`].
221
463
    fn into_inner(self) -> usize {
222
463
        self.0
223
463
    }
224
}
225
226
/// An address to an element instance that lives in a specific [`Store`](crate::Store).
227
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
228
pub struct ElemAddr(usize);
229
230
impl core::fmt::Display for ElemAddr {
231
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
232
0
        write!(f, "element segment address {}", self.0)
233
0
    }
234
}
235
236
impl Addr for ElemAddr {
237
815
    fn new(inner: usize) -> Self {
238
815
        Self(inner)
239
815
    }
240
241
882
    fn into_inner(self) -> usize {
242
882
        self.0
243
882
    }
244
}
245
246
/// An address to a data instance that lives in a specific [`Store`](crate::Store).
247
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
248
pub struct DataAddr(usize);
249
250
impl core::fmt::Display for DataAddr {
251
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
252
0
        write!(f, "data segment address {}", self.0)
253
0
    }
254
}
255
256
impl Addr for DataAddr {
257
449
    fn new(inner: usize) -> Self {
258
449
        Self(inner)
259
449
    }
260
261
554
    fn into_inner(self) -> usize {
262
554
        self.0
263
554
    }
264
}
265
266
/// An address to a module instance that lives in a specific [`Store`](crate::Store).
267
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
268
pub struct ModuleAddr(usize);
269
270
impl core::fmt::Display for ModuleAddr {
271
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
272
0
        write!(f, "module address {}", self.0)
273
0
    }
274
}
275
276
impl Addr for ModuleAddr {
277
1.96k
    fn new(inner: usize) -> Self {
278
1.96k
        Self(inner)
279
1.96k
    }
280
281
1.45M
    fn into_inner(self) -> usize {
282
1.45M
        self.0
283
1.45M
    }
284
}