Coverage Report

Created: 2026-07-03 16:00

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.10k
    fn default() -> Self {
39
3.10k
        Self {
40
3.10k
            inner: Vec::default(),
41
3.10k
            _phantom: PhantomData,
42
3.10k
        }
43
3.10k
    }
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
2.88M
    pub unsafe fn get(&self, addr: A) -> &Inst {
53
        // TODO use unwrap_unchecked instead
54
2.88M
        self.inner
55
2.88M
            .get(addr.into_inner())
56
2.88M
            .expect("addrs to always be valid")
57
2.88M
    }
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
5.34k
    pub unsafe fn get_mut(&mut self, addr: A) -> &mut Inst {
65
        // TODO use unwrap_unchecked instead
66
5.34k
        self.inner
67
5.34k
            .get_mut(addr.into_inner())
68
5.34k
            .expect("addrs to always be valid")
69
5.34k
    }
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
12.3k
    pub fn insert(&mut self, instance: Inst) -> A {
75
12.3k
        let new_addr = self.inner.len();
76
12.3k
        self.inner.push(instance);
77
12.3k
        A::new(new_addr)
78
12.3k
    }
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
6
    pub unsafe fn get_two_mut(
89
6
        &mut self,
90
6
        addr_one: A,
91
6
        addr_two: A,
92
6
    ) -> Option<(&mut Inst, &mut Inst)> {
93
6
        let addr_one = addr_one.into_inner();
94
6
        let addr_two = addr_two.into_inner();
95
96
6
        match addr_one.cmp(&addr_two) {
97
            Ordering::Greater => {
98
1
                let (left, right) = self.inner.split_at_mut(addr_one);
99
1
                let one = right.get_mut(0).expect(
100
1
                    "this to be exactly the same as addr_one and addresses to always be valid",
101
                );
102
1
                let two = left
103
1
                    .get_mut(addr_two)
104
1
                    .expect("addresses to always be valid");
105
106
1
                Some((one, two))
107
            }
108
            Ordering::Less => {
109
5
                let (left, right) = self.inner.split_at_mut(addr_two);
110
5
                let one = left
111
5
                    .get_mut(addr_one)
112
5
                    .expect("addresses to always be valid");
113
5
                let two = right.get_mut(0).expect(
114
5
                    "this to be exactly the same as addr_two and addresses to always be valid",
115
                );
116
117
5
                Some((one, two))
118
            }
119
0
            Ordering::Equal => None,
120
        }
121
6
    }
122
}
123
124
/// An address to a function instance that lives in a specific [`Store`](crate::Store).
125
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
126
pub struct FuncAddr(usize);
127
128
impl core::fmt::Display for FuncAddr {
129
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
130
0
        write!(f, "function address {}", self.0)
131
0
    }
132
}
133
134
impl Addr for FuncAddr {
135
7.50k
    fn new(inner: usize) -> Self {
136
7.50k
        Self(inner)
137
7.50k
    }
138
139
403k
    fn into_inner(self) -> usize {
140
403k
        self.0
141
403k
    }
142
}
143
144
/// An address to a table instance that lives in a specific [`Store`](crate::Store).
145
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
146
pub struct TableAddr(usize);
147
148
impl core::fmt::Display for TableAddr {
149
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150
0
        write!(f, "table address {}", self.0)
151
0
    }
152
}
153
154
impl Addr for TableAddr {
155
503
    fn new(inner: usize) -> Self {
156
503
        Self(inner)
157
503
    }
158
159
101k
    fn into_inner(self) -> usize {
160
101k
        self.0
161
101k
    }
162
}
163
164
/// An address to a memory instance that lives in a specific [`Store`](crate::Store).
165
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
166
pub struct MemAddr(usize);
167
168
impl core::fmt::Display for MemAddr {
169
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170
0
        write!(f, "memory address {}", self.0)
171
0
    }
172
}
173
174
impl Addr for MemAddr {
175
501
    fn new(inner: usize) -> Self {
176
501
        Self(inner)
177
501
    }
178
179
932k
    fn into_inner(self) -> usize {
180
932k
        self.0
181
932k
    }
182
}
183
184
/// An address to a global instance that lives in a specific [`Store`](crate::Store).
185
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
186
pub struct GlobalAddr(usize);
187
188
impl core::fmt::Display for GlobalAddr {
189
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
190
0
        write!(f, "global address {}", self.0)
191
0
    }
192
}
193
194
impl Addr for GlobalAddr {
195
678
    fn new(inner: usize) -> Self {
196
678
        Self(inner)
197
678
    }
198
199
    /// Returns the inner integer represented by this [`GlobalAddr`].
200
463
    fn into_inner(self) -> usize {
201
463
        self.0
202
463
    }
203
}
204
205
/// An address to an element instance that lives in a specific [`Store`](crate::Store).
206
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
207
pub struct ElemAddr(usize);
208
209
impl core::fmt::Display for ElemAddr {
210
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211
0
        write!(f, "element segment address {}", self.0)
212
0
    }
213
}
214
215
impl Addr for ElemAddr {
216
815
    fn new(inner: usize) -> Self {
217
815
        Self(inner)
218
815
    }
219
220
882
    fn into_inner(self) -> usize {
221
882
        self.0
222
882
    }
223
}
224
225
/// An address to a data instance that lives in a specific [`Store`](crate::Store).
226
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
227
pub struct DataAddr(usize);
228
229
impl core::fmt::Display for DataAddr {
230
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
231
0
        write!(f, "data segment address {}", self.0)
232
0
    }
233
}
234
235
impl Addr for DataAddr {
236
404
    fn new(inner: usize) -> Self {
237
404
        Self(inner)
238
404
    }
239
240
474
    fn into_inner(self) -> usize {
241
474
        self.0
242
474
    }
243
}
244
245
/// An address to a module instance that lives in a specific [`Store`](crate::Store).
246
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
247
pub struct ModuleAddr(usize);
248
249
impl core::fmt::Display for ModuleAddr {
250
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251
0
        write!(f, "module address {}", self.0)
252
0
    }
253
}
254
255
impl Addr for ModuleAddr {
256
1.91k
    fn new(inner: usize) -> Self {
257
1.91k
        Self(inner)
258
1.91k
    }
259
260
1.44M
    fn into_inner(self) -> usize {
261
1.44M
        self.0
262
1.44M
    }
263
}