1use {
2 crate::{
3 decode::{Decode, DecodeError, Decoder},
4 extern_ref::{ExternRef, UnguardedExternRef},
5 func_ref::{FuncRef, UnguardedFuncRef},
6 ref_::{Ref, RefType, UnguardedRef},
7 stack::StackSlot,
8 store::StoreId,
9 },
10 std::fmt,
11};
12
13#[derive(Clone, Copy, Debug, PartialEq)]
15pub enum Val {
16 I32(i32),
17 I64(i64),
18 F32(f32),
19 F64(f64),
20 FuncRef(FuncRef),
21 ExternRef(ExternRef),
22}
23
24impl Val {
25 pub fn default(type_: ValType) -> Self {
27 match type_ {
28 ValType::I32 => 0i32.into(),
29 ValType::I64 => 0i64.into(),
30 ValType::F32 => 0f32.into(),
31 ValType::F64 => 0f64.into(),
32 ValType::FuncRef => FuncRef::null().into(),
33 ValType::ExternRef => ExternRef::null().into(),
34 }
35 }
36
37 pub fn type_(self) -> ValType {
39 match self {
40 Val::I32(_) => ValType::I32,
41 Val::I64(_) => ValType::I64,
42 Val::F32(_) => ValType::F32,
43 Val::F64(_) => ValType::F64,
44 Val::FuncRef(_) => ValType::FuncRef,
45 Val::ExternRef(_) => ValType::ExternRef,
46 }
47 }
48
49 pub fn is_i32(self) -> bool {
51 self.to_i32().is_some()
52 }
53
54 pub fn is_i64(self) -> bool {
56 self.to_i64().is_some()
57 }
58
59 pub fn is_f32(self) -> bool {
61 self.to_f32().is_some()
62 }
63
64 pub fn is_f64(self) -> bool {
66 self.to_f64().is_some()
67 }
68
69 pub fn is_ref(self) -> bool {
71 self.to_ref().is_some()
72 }
73
74 pub fn is_func_ref(self) -> bool {
76 self.to_func_ref().is_some()
77 }
78
79 pub fn is_extern_ref(self) -> bool {
81 self.to_extern_ref().is_some()
82 }
83
84 pub fn to_i32(self) -> Option<i32> {
86 match self {
87 Val::I32(val) => Some(val),
88 _ => None,
89 }
90 }
91
92 pub fn to_i64(self) -> Option<i64> {
94 match self {
95 Val::I64(val) => Some(val),
96 _ => None,
97 }
98 }
99
100 pub fn to_f32(self) -> Option<f32> {
102 match self {
103 Val::F32(val) => Some(val),
104 _ => None,
105 }
106 }
107
108 pub fn to_f64(self) -> Option<f64> {
110 match self {
111 Val::F64(val) => Some(val),
112 _ => None,
113 }
114 }
115
116 pub fn to_ref(self) -> Option<Ref> {
118 match self {
119 Val::FuncRef(val) => Some(val.into()),
120 Val::ExternRef(val) => Some(val.into()),
121 _ => None,
122 }
123 }
124
125 pub fn to_func_ref(self) -> Option<FuncRef> {
127 match self {
128 Val::FuncRef(val) => Some(val),
129 _ => None,
130 }
131 }
132
133 pub fn to_extern_ref(self) -> Option<ExternRef> {
135 match self {
136 Val::ExternRef(val) => Some(val),
137 _ => None,
138 }
139 }
140
141 pub(crate) unsafe fn from_unguarded(val: UnguardedVal, store_id: StoreId) -> Self {
147 match val {
148 UnguardedVal::I32(val) => val.into(),
149 UnguardedVal::I64(val) => val.into(),
150 UnguardedVal::F32(val) => val.into(),
151 UnguardedVal::F64(val) => val.into(),
152 UnguardedVal::FuncRef(val) => FuncRef::from_unguarded(val, store_id).into(),
153 UnguardedVal::ExternRef(val) => ExternRef::from_unguarded(val, store_id).into(),
154 }
155 }
156
157 pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedVal {
163 match self {
164 Val::I32(val) => val.into(),
165 Val::I64(val) => val.into(),
166 Val::F32(val) => val.into(),
167 Val::F64(val) => val.into(),
168 Val::FuncRef(val) => val.to_unguarded(store_id).into(),
169 Val::ExternRef(val) => val.to_unguarded(store_id).into(),
170 }
171 }
172}
173
174impl From<i32> for Val {
175 fn from(val: i32) -> Self {
176 Val::I32(val)
177 }
178}
179
180impl From<i64> for Val {
181 fn from(val: i64) -> Self {
182 Val::I64(val)
183 }
184}
185
186impl From<f32> for Val {
187 fn from(val: f32) -> Self {
188 Val::F32(val)
189 }
190}
191
192impl From<f64> for Val {
193 fn from(val: f64) -> Self {
194 Val::F64(val)
195 }
196}
197
198impl From<FuncRef> for Val {
199 fn from(val: FuncRef) -> Self {
200 Val::FuncRef(val)
201 }
202}
203
204impl From<ExternRef> for Val {
205 fn from(val: ExternRef) -> Self {
206 Val::ExternRef(val)
207 }
208}
209
210impl From<Ref> for Val {
211 fn from(val: Ref) -> Self {
212 match val {
213 Ref::FuncRef(val) => val.into(),
214 Ref::ExternRef(val) => val.into(),
215 }
216 }
217}
218
219#[derive(Clone, Copy, Debug, PartialEq)]
221pub(crate) enum UnguardedVal {
222 I32(i32),
223 I64(i64),
224 F32(f32),
225 F64(f64),
226 FuncRef(UnguardedFuncRef),
227 ExternRef(UnguardedExternRef),
228}
229
230impl UnguardedVal {
231 pub(crate) unsafe fn read_from_stack(ptr: *const StackSlot, type_: ValType) -> Self {
233 let val = match type_ {
234 ValType::I32 => (*ptr.cast::<i32>()).into(),
235 ValType::I64 => (*ptr.cast::<i64>()).into(),
236 ValType::F32 => (*ptr.cast::<f32>()).into(),
237 ValType::F64 => (*ptr.cast::<f64>()).into(),
238 ValType::FuncRef => (*ptr.cast::<UnguardedFuncRef>()).into(),
239 ValType::ExternRef => (*ptr.cast::<UnguardedExternRef>()).into(),
240 };
241 val
242 }
243
244 pub(crate) unsafe fn write_to_stack(self, ptr: *mut StackSlot) {
246 match self {
247 UnguardedVal::I32(val) => *ptr.cast() = val,
248 UnguardedVal::I64(val) => *ptr.cast() = val,
249 UnguardedVal::F32(val) => *ptr.cast() = val,
250 UnguardedVal::F64(val) => *ptr.cast() = val,
251 UnguardedVal::FuncRef(val) => *ptr.cast() = val,
252 UnguardedVal::ExternRef(val) => *ptr.cast() = val,
253 }
254 }
255}
256
257impl From<i32> for UnguardedVal {
258 fn from(val: i32) -> Self {
259 UnguardedVal::I32(val)
260 }
261}
262
263impl From<i64> for UnguardedVal {
264 fn from(val: i64) -> Self {
265 UnguardedVal::I64(val)
266 }
267}
268
269impl From<f32> for UnguardedVal {
270 fn from(val: f32) -> Self {
271 UnguardedVal::F32(val)
272 }
273}
274
275impl From<f64> for UnguardedVal {
276 fn from(val: f64) -> Self {
277 UnguardedVal::F64(val)
278 }
279}
280
281impl From<UnguardedRef> for UnguardedVal {
282 fn from(val: UnguardedRef) -> Self {
283 match val {
284 UnguardedRef::FuncRef(val) => val.into(),
285 UnguardedRef::ExternRef(val) => val.into(),
286 }
287 }
288}
289
290impl From<UnguardedFuncRef> for UnguardedVal {
291 fn from(val: UnguardedFuncRef) -> Self {
292 UnguardedVal::FuncRef(val)
293 }
294}
295
296impl From<UnguardedExternRef> for UnguardedVal {
297 fn from(val: UnguardedExternRef) -> Self {
298 UnguardedVal::ExternRef(val)
299 }
300}
301
302#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
304pub enum ValType {
305 I32,
306 I64,
307 F32,
308 F64,
309 FuncRef,
310 ExternRef,
311}
312
313impl ValType {
314 pub fn is_num(self) -> bool {
316 match self {
317 Self::I32 | Self::I64 | Self::F32 | Self::F64 => true,
318 _ => false,
319 }
320 }
321
322 pub fn is_ref(self) -> bool {
324 self.to_ref().is_some()
325 }
326
327 pub fn to_ref(self) -> Option<RefType> {
329 match self {
330 Self::FuncRef => Some(RefType::FuncRef),
331 Self::ExternRef => Some(RefType::ExternRef),
332 _ => None,
333 }
334 }
335
336 pub(crate) fn reg_idx(self) -> usize {
338 match self {
339 ValType::I32 | ValType::I64 | ValType::FuncRef | ValType::ExternRef => 0,
340 ValType::F32 | ValType::F64 => 1,
341 }
342 }
343}
344
345impl Decode for ValType {
346 fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
347 match decoder.read_byte()? {
348 0x6F => Ok(Self::ExternRef),
349 0x70 => Ok(Self::FuncRef),
350 0x7C => Ok(Self::F64),
351 0x7D => Ok(Self::F32),
352 0x7E => Ok(Self::I64),
353 0x7F => Ok(Self::I32),
354 _ => Err(DecodeError::new("malformed value type")),
355 }
356 }
357}
358
359impl fmt::Display for ValType {
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 match self {
362 Self::I32 => write!(f, "i32"),
363 Self::I64 => write!(f, "i64"),
364 Self::F32 => write!(f, "f32"),
365 Self::F64 => write!(f, "f64"),
366 Self::FuncRef => write!(f, "funcref"),
367 Self::ExternRef => write!(f, "externref"),
368 }
369 }
370}
371
372impl From<RefType> for ValType {
373 fn from(val: RefType) -> Self {
374 match val {
375 RefType::FuncRef => Self::FuncRef,
376 RefType::ExternRef => Self::ExternRef,
377 }
378 }
379}