16f6f79efSAndrew Brown //! This module gives users to instantiate values that Cranelift understands. These values are used,
26f6f79efSAndrew Brown //! for example, during interpretation and for wrapping immediates.
390ac295eSAlex Crichton use crate::ir::immediates::{Ieee16, Ieee32, Ieee64, Ieee128, Offset32};
490ac295eSAlex Crichton use crate::ir::{ConstantData, Type, types};
57ac3fda7Sbeetrees use core::cmp::Ordering;
66f6f79efSAndrew Brown use core::fmt::{self, Display, Formatter};
76f6f79efSAndrew Brown 
86f6f79efSAndrew Brown /// Represent a data value. Where [Value] is an SSA reference, [DataValue] is the type + value
96f6f79efSAndrew Brown /// that would be referred to by a [Value].
106f6f79efSAndrew Brown ///
116f6f79efSAndrew Brown /// [Value]: crate::ir::Value
12099102d9SAlex Crichton #[expect(missing_docs, reason = "self-describing variants")]
139856664fSJamey Sharp #[derive(Clone, Debug, PartialOrd)]
146f6f79efSAndrew Brown pub enum DataValue {
156f6f79efSAndrew Brown     I8(i8),
166f6f79efSAndrew Brown     I16(i16),
176f6f79efSAndrew Brown     I32(i32),
186f6f79efSAndrew Brown     I64(i64),
19084383f6SAfonso Bordado     I128(i128),
207ac3fda7Sbeetrees     F16(Ieee16),
213778fa02SAndrew Brown     F32(Ieee32),
223778fa02SAndrew Brown     F64(Ieee64),
237ac3fda7Sbeetrees     F128(Ieee128),
246f6f79efSAndrew Brown     V128([u8; 16]),
253ef89b77SDamian Heaton     V64([u8; 8]),
26d48b3856Sbeetrees     V32([u8; 4]),
27d48b3856Sbeetrees     V16([u8; 2]),
286f6f79efSAndrew Brown }
296f6f79efSAndrew Brown 
309856664fSJamey Sharp impl PartialEq for DataValue {
eq(&self, other: &Self) -> bool319856664fSJamey Sharp     fn eq(&self, other: &Self) -> bool {
329856664fSJamey Sharp         use DataValue::*;
339856664fSJamey Sharp         match (self, other) {
349856664fSJamey Sharp             (I8(l), I8(r)) => l == r,
359856664fSJamey Sharp             (I8(_), _) => false,
369856664fSJamey Sharp             (I16(l), I16(r)) => l == r,
379856664fSJamey Sharp             (I16(_), _) => false,
389856664fSJamey Sharp             (I32(l), I32(r)) => l == r,
399856664fSJamey Sharp             (I32(_), _) => false,
409856664fSJamey Sharp             (I64(l), I64(r)) => l == r,
419856664fSJamey Sharp             (I64(_), _) => false,
429856664fSJamey Sharp             (I128(l), I128(r)) => l == r,
439856664fSJamey Sharp             (I128(_), _) => false,
447ac3fda7Sbeetrees             (F16(l), F16(r)) => l.partial_cmp(&r) == Some(Ordering::Equal),
457ac3fda7Sbeetrees             (F16(_), _) => false,
469856664fSJamey Sharp             (F32(l), F32(r)) => l.as_f32() == r.as_f32(),
479856664fSJamey Sharp             (F32(_), _) => false,
489856664fSJamey Sharp             (F64(l), F64(r)) => l.as_f64() == r.as_f64(),
499856664fSJamey Sharp             (F64(_), _) => false,
507ac3fda7Sbeetrees             (F128(l), F128(r)) => l.partial_cmp(&r) == Some(Ordering::Equal),
517ac3fda7Sbeetrees             (F128(_), _) => false,
529856664fSJamey Sharp             (V128(l), V128(r)) => l == r,
539856664fSJamey Sharp             (V128(_), _) => false,
549856664fSJamey Sharp             (V64(l), V64(r)) => l == r,
559856664fSJamey Sharp             (V64(_), _) => false,
56d48b3856Sbeetrees             (V32(l), V32(r)) => l == r,
57d48b3856Sbeetrees             (V32(_), _) => false,
58d48b3856Sbeetrees             (V16(l), V16(r)) => l == r,
59d48b3856Sbeetrees             (V16(_), _) => false,
609856664fSJamey Sharp         }
619856664fSJamey Sharp     }
629856664fSJamey Sharp }
639856664fSJamey Sharp 
646f6f79efSAndrew Brown impl DataValue {
65a2fb019bSAfonso Bordado     /// Try to cast an immediate integer (a wrapped `i64` on most Cranelift instructions) to the
666d500998SAndrew Brown     /// given Cranelift [Type].
from_integer(imm: i128, ty: Type) -> Result<DataValue, DataValueCastFailure>67084383f6SAfonso Bordado     pub fn from_integer(imm: i128, ty: Type) -> Result<DataValue, DataValueCastFailure> {
686f6f79efSAndrew Brown         match ty {
696d500998SAndrew Brown             types::I8 => Ok(DataValue::I8(imm as i8)),
706d500998SAndrew Brown             types::I16 => Ok(DataValue::I16(imm as i16)),
716d500998SAndrew Brown             types::I32 => Ok(DataValue::I32(imm as i32)),
72084383f6SAfonso Bordado             types::I64 => Ok(DataValue::I64(imm as i64)),
73084383f6SAfonso Bordado             types::I128 => Ok(DataValue::I128(imm)),
746d500998SAndrew Brown             _ => Err(DataValueCastFailure::FromInteger(imm, ty)),
756f6f79efSAndrew Brown         }
766f6f79efSAndrew Brown     }
776f6f79efSAndrew Brown 
786f6f79efSAndrew Brown     /// Return the Cranelift IR [Type] for this [DataValue].
ty(&self) -> Type796f6f79efSAndrew Brown     pub fn ty(&self) -> Type {
806f6f79efSAndrew Brown         match self {
81387db16dST0b1-iOS             DataValue::I8(_) => types::I8,
82387db16dST0b1-iOS             DataValue::I16(_) => types::I16,
83387db16dST0b1-iOS             DataValue::I32(_) => types::I32,
84387db16dST0b1-iOS             DataValue::I64(_) => types::I64,
85387db16dST0b1-iOS             DataValue::I128(_) => types::I128,
867ac3fda7Sbeetrees             DataValue::F16(_) => types::F16,
876f6f79efSAndrew Brown             DataValue::F32(_) => types::F32,
886f6f79efSAndrew Brown             DataValue::F64(_) => types::F64,
897ac3fda7Sbeetrees             DataValue::F128(_) => types::F128,
906f6f79efSAndrew Brown             DataValue::V128(_) => types::I8X16, // A default type.
913ef89b77SDamian Heaton             DataValue::V64(_) => types::I8X8,   // A default type.
92d48b3856Sbeetrees             DataValue::V32(_) => types::I8X4,   // A default type.
93d48b3856Sbeetrees             DataValue::V16(_) => types::I8X2,   // A default type.
946f6f79efSAndrew Brown         }
956f6f79efSAndrew Brown     }
966f6f79efSAndrew Brown 
976f6f79efSAndrew Brown     /// Return true if the value is a vector (i.e. `DataValue::V128`).
is_vector(&self) -> bool986f6f79efSAndrew Brown     pub fn is_vector(&self) -> bool {
996f6f79efSAndrew Brown         match self {
100d48b3856Sbeetrees             DataValue::V128(_) | DataValue::V64(_) | DataValue::V32(_) | DataValue::V16(_) => true,
1016f6f79efSAndrew Brown             _ => false,
1026f6f79efSAndrew Brown         }
1036f6f79efSAndrew Brown     }
1046d500998SAndrew Brown 
swap_bytes(self) -> Self105db8fe010SJan-Justin van Tonder     fn swap_bytes(self) -> Self {
106db8fe010SJan-Justin van Tonder         match self {
107db8fe010SJan-Justin van Tonder             DataValue::I8(i) => DataValue::I8(i.swap_bytes()),
108db8fe010SJan-Justin van Tonder             DataValue::I16(i) => DataValue::I16(i.swap_bytes()),
109db8fe010SJan-Justin van Tonder             DataValue::I32(i) => DataValue::I32(i.swap_bytes()),
110db8fe010SJan-Justin van Tonder             DataValue::I64(i) => DataValue::I64(i.swap_bytes()),
111db8fe010SJan-Justin van Tonder             DataValue::I128(i) => DataValue::I128(i.swap_bytes()),
1127ac3fda7Sbeetrees             DataValue::F16(f) => DataValue::F16(Ieee16::with_bits(f.bits().swap_bytes())),
113db8fe010SJan-Justin van Tonder             DataValue::F32(f) => DataValue::F32(Ieee32::with_bits(f.bits().swap_bytes())),
114db8fe010SJan-Justin van Tonder             DataValue::F64(f) => DataValue::F64(Ieee64::with_bits(f.bits().swap_bytes())),
1157ac3fda7Sbeetrees             DataValue::F128(f) => DataValue::F128(Ieee128::with_bits(f.bits().swap_bytes())),
116db8fe010SJan-Justin van Tonder             DataValue::V128(mut v) => {
117db8fe010SJan-Justin van Tonder                 v.reverse();
118db8fe010SJan-Justin van Tonder                 DataValue::V128(v)
119db8fe010SJan-Justin van Tonder             }
120db8fe010SJan-Justin van Tonder             DataValue::V64(mut v) => {
121db8fe010SJan-Justin van Tonder                 v.reverse();
122db8fe010SJan-Justin van Tonder                 DataValue::V64(v)
123db8fe010SJan-Justin van Tonder             }
124d48b3856Sbeetrees             DataValue::V32(mut v) => {
125d48b3856Sbeetrees                 v.reverse();
126d48b3856Sbeetrees                 DataValue::V32(v)
127d48b3856Sbeetrees             }
128d48b3856Sbeetrees             DataValue::V16(mut v) => {
129d48b3856Sbeetrees                 v.reverse();
130d48b3856Sbeetrees                 DataValue::V16(v)
131d48b3856Sbeetrees             }
132db8fe010SJan-Justin van Tonder         }
133db8fe010SJan-Justin van Tonder     }
134db8fe010SJan-Justin van Tonder 
135db8fe010SJan-Justin van Tonder     /// Converts `self` to big endian from target's endianness.
to_be(self) -> Self136db8fe010SJan-Justin van Tonder     pub fn to_be(self) -> Self {
137db8fe010SJan-Justin van Tonder         if cfg!(target_endian = "big") {
138db8fe010SJan-Justin van Tonder             self
139db8fe010SJan-Justin van Tonder         } else {
140db8fe010SJan-Justin van Tonder             self.swap_bytes()
141db8fe010SJan-Justin van Tonder         }
142db8fe010SJan-Justin van Tonder     }
143db8fe010SJan-Justin van Tonder 
144db8fe010SJan-Justin van Tonder     /// Converts `self` to little endian from target's endianness.
to_le(self) -> Self145db8fe010SJan-Justin van Tonder     pub fn to_le(self) -> Self {
146db8fe010SJan-Justin van Tonder         if cfg!(target_endian = "little") {
147db8fe010SJan-Justin van Tonder             self
148db8fe010SJan-Justin van Tonder         } else {
149db8fe010SJan-Justin van Tonder             self.swap_bytes()
150db8fe010SJan-Justin van Tonder         }
151db8fe010SJan-Justin van Tonder     }
152db8fe010SJan-Justin van Tonder 
153db8fe010SJan-Justin van Tonder     /// Write a [DataValue] to a slice in native-endian byte order.
1542776074dSAfonso Bordado     ///
1552776074dSAfonso Bordado     /// # Panics:
1562776074dSAfonso Bordado     ///
1572776074dSAfonso Bordado     /// Panics if the slice does not have enough space to accommodate the [DataValue]
write_to_slice_ne(&self, dst: &mut [u8])158db8fe010SJan-Justin van Tonder     pub fn write_to_slice_ne(&self, dst: &mut [u8]) {
1596d500998SAndrew Brown         match self {
1601b8154e0SUlrich Weigand             DataValue::I8(i) => dst[..1].copy_from_slice(&i.to_ne_bytes()[..]),
1611b8154e0SUlrich Weigand             DataValue::I16(i) => dst[..2].copy_from_slice(&i.to_ne_bytes()[..]),
1621b8154e0SUlrich Weigand             DataValue::I32(i) => dst[..4].copy_from_slice(&i.to_ne_bytes()[..]),
1631b8154e0SUlrich Weigand             DataValue::I64(i) => dst[..8].copy_from_slice(&i.to_ne_bytes()[..]),
1648115e725SAfonso Bordado             DataValue::I128(i) => dst[..16].copy_from_slice(&i.to_ne_bytes()[..]),
1657ac3fda7Sbeetrees             DataValue::F16(f) => dst[..2].copy_from_slice(&f.bits().to_ne_bytes()[..]),
1661b8154e0SUlrich Weigand             DataValue::F32(f) => dst[..4].copy_from_slice(&f.bits().to_ne_bytes()[..]),
1671b8154e0SUlrich Weigand             DataValue::F64(f) => dst[..8].copy_from_slice(&f.bits().to_ne_bytes()[..]),
1687ac3fda7Sbeetrees             DataValue::F128(f) => dst[..16].copy_from_slice(&f.bits().to_ne_bytes()[..]),
16967870d15SUlrich Weigand             DataValue::V128(v) => dst[..16].copy_from_slice(&v[..]),
17067870d15SUlrich Weigand             DataValue::V64(v) => dst[..8].copy_from_slice(&v[..]),
171d48b3856Sbeetrees             DataValue::V32(v) => dst[..4].copy_from_slice(&v[..]),
172d48b3856Sbeetrees             DataValue::V16(v) => dst[..2].copy_from_slice(&v[..]),
1732776074dSAfonso Bordado         };
1742776074dSAfonso Bordado     }
1752776074dSAfonso Bordado 
176db8fe010SJan-Justin van Tonder     /// Write a [DataValue] to a slice in big-endian byte order.
1772776074dSAfonso Bordado     ///
1782776074dSAfonso Bordado     /// # Panics:
1792776074dSAfonso Bordado     ///
1802776074dSAfonso Bordado     /// Panics if the slice does not have enough space to accommodate the [DataValue]
write_to_slice_be(&self, dst: &mut [u8])181db8fe010SJan-Justin van Tonder     pub fn write_to_slice_be(&self, dst: &mut [u8]) {
182db8fe010SJan-Justin van Tonder         self.clone().to_be().write_to_slice_ne(dst);
183db8fe010SJan-Justin van Tonder     }
184db8fe010SJan-Justin van Tonder 
185db8fe010SJan-Justin van Tonder     /// Write a [DataValue] to a slice in little-endian byte order.
186db8fe010SJan-Justin van Tonder     ///
187db8fe010SJan-Justin van Tonder     /// # Panics:
188db8fe010SJan-Justin van Tonder     ///
189db8fe010SJan-Justin van Tonder     /// Panics if the slice does not have enough space to accommodate the [DataValue]
write_to_slice_le(&self, dst: &mut [u8])190db8fe010SJan-Justin van Tonder     pub fn write_to_slice_le(&self, dst: &mut [u8]) {
191db8fe010SJan-Justin van Tonder         self.clone().to_le().write_to_slice_ne(dst);
192db8fe010SJan-Justin van Tonder     }
193db8fe010SJan-Justin van Tonder 
194db8fe010SJan-Justin van Tonder     /// Read a [DataValue] from a slice using a given [Type] with native-endian byte order.
195db8fe010SJan-Justin van Tonder     ///
196db8fe010SJan-Justin van Tonder     /// # Panics:
197db8fe010SJan-Justin van Tonder     ///
198db8fe010SJan-Justin van Tonder     /// Panics if the slice does not have enough space to accommodate the [DataValue]
read_from_slice_ne(src: &[u8], ty: Type) -> Self199db8fe010SJan-Justin van Tonder     pub fn read_from_slice_ne(src: &[u8], ty: Type) -> Self {
2002776074dSAfonso Bordado         match ty {
2011b8154e0SUlrich Weigand             types::I8 => DataValue::I8(i8::from_ne_bytes(src[..1].try_into().unwrap())),
2021b8154e0SUlrich Weigand             types::I16 => DataValue::I16(i16::from_ne_bytes(src[..2].try_into().unwrap())),
2031b8154e0SUlrich Weigand             types::I32 => DataValue::I32(i32::from_ne_bytes(src[..4].try_into().unwrap())),
2041b8154e0SUlrich Weigand             types::I64 => DataValue::I64(i64::from_ne_bytes(src[..8].try_into().unwrap())),
2058115e725SAfonso Bordado             types::I128 => DataValue::I128(i128::from_ne_bytes(src[..16].try_into().unwrap())),
2067ac3fda7Sbeetrees             types::F16 => DataValue::F16(Ieee16::with_bits(u16::from_ne_bytes(
2077ac3fda7Sbeetrees                 src[..2].try_into().unwrap(),
2087ac3fda7Sbeetrees             ))),
2091b8154e0SUlrich Weigand             types::F32 => DataValue::F32(Ieee32::with_bits(u32::from_ne_bytes(
2102776074dSAfonso Bordado                 src[..4].try_into().unwrap(),
2112776074dSAfonso Bordado             ))),
2121b8154e0SUlrich Weigand             types::F64 => DataValue::F64(Ieee64::with_bits(u64::from_ne_bytes(
2132776074dSAfonso Bordado                 src[..8].try_into().unwrap(),
2142776074dSAfonso Bordado             ))),
2157ac3fda7Sbeetrees             types::F128 => DataValue::F128(Ieee128::with_bits(u128::from_ne_bytes(
2167ac3fda7Sbeetrees                 src[..16].try_into().unwrap(),
2177ac3fda7Sbeetrees             ))),
218d48b3856Sbeetrees             _ if ty.is_vector() => match ty.bytes() {
219d48b3856Sbeetrees                 16 => DataValue::V128(src[..16].try_into().unwrap()),
220d48b3856Sbeetrees                 8 => DataValue::V64(src[..8].try_into().unwrap()),
221d48b3856Sbeetrees                 4 => DataValue::V32(src[..4].try_into().unwrap()),
222d48b3856Sbeetrees                 2 => DataValue::V16(src[..2].try_into().unwrap()),
223d48b3856Sbeetrees                 _ => unimplemented!(),
224d48b3856Sbeetrees             },
2256d500998SAndrew Brown             _ => unimplemented!(),
2266d500998SAndrew Brown         }
2276d500998SAndrew Brown     }
2286d500998SAndrew Brown 
229db8fe010SJan-Justin van Tonder     /// Read a [DataValue] from a slice using a given [Type] in big-endian byte order.
230db8fe010SJan-Justin van Tonder     ///
231db8fe010SJan-Justin van Tonder     /// # Panics:
232db8fe010SJan-Justin van Tonder     ///
233db8fe010SJan-Justin van Tonder     /// Panics if the slice does not have enough space to accommodate the [DataValue]
read_from_slice_be(src: &[u8], ty: Type) -> Self234db8fe010SJan-Justin van Tonder     pub fn read_from_slice_be(src: &[u8], ty: Type) -> Self {
235db8fe010SJan-Justin van Tonder         DataValue::read_from_slice_ne(src, ty).to_be()
2362776074dSAfonso Bordado     }
2372776074dSAfonso Bordado 
238db8fe010SJan-Justin van Tonder     /// Read a [DataValue] from a slice using a given [Type] in little-endian byte order.
239db8fe010SJan-Justin van Tonder     ///
240db8fe010SJan-Justin van Tonder     /// # Panics:
241db8fe010SJan-Justin van Tonder     ///
242db8fe010SJan-Justin van Tonder     /// Panics if the slice does not have enough space to accommodate the [DataValue]
read_from_slice_le(src: &[u8], ty: Type) -> Self243db8fe010SJan-Justin van Tonder     pub fn read_from_slice_le(src: &[u8], ty: Type) -> Self {
244db8fe010SJan-Justin van Tonder         DataValue::read_from_slice_ne(src, ty).to_le()
245db8fe010SJan-Justin van Tonder     }
246db8fe010SJan-Justin van Tonder 
247db8fe010SJan-Justin van Tonder     /// Write a [DataValue] to a memory location in native-endian byte order.
write_value_to(&self, p: *mut u128)248db8fe010SJan-Justin van Tonder     pub unsafe fn write_value_to(&self, p: *mut u128) {
249db8fe010SJan-Justin van Tonder         let size = self.ty().bytes() as usize;
250*0889323aSSSD         self.write_to_slice_ne(unsafe { core::slice::from_raw_parts_mut(p as *mut u8, size) });
251db8fe010SJan-Justin van Tonder     }
252db8fe010SJan-Justin van Tonder 
253db8fe010SJan-Justin van Tonder     /// Read a [DataValue] from a memory location using a given [Type] in native-endian byte order.
read_value_from(p: *const u128, ty: Type) -> Self2546d500998SAndrew Brown     pub unsafe fn read_value_from(p: *const u128, ty: Type) -> Self {
255db8fe010SJan-Justin van Tonder         DataValue::read_from_slice_ne(
256*0889323aSSSD             unsafe { core::slice::from_raw_parts(p as *const u8, ty.bytes() as usize) },
2572776074dSAfonso Bordado             ty,
2582776074dSAfonso Bordado         )
2596d500998SAndrew Brown     }
2607e45cff4SAfonso Bordado 
2617e45cff4SAfonso Bordado     /// Performs a bitwise comparison over the contents of [DataValue].
2627e45cff4SAfonso Bordado     ///
2637e45cff4SAfonso Bordado     /// Returns true if all bits are equal.
2647e45cff4SAfonso Bordado     ///
2657e45cff4SAfonso Bordado     /// This behaviour is different from PartialEq for NaN floats.
bitwise_eq(&self, other: &DataValue) -> bool2667e45cff4SAfonso Bordado     pub fn bitwise_eq(&self, other: &DataValue) -> bool {
2677e45cff4SAfonso Bordado         match (self, other) {
2687e45cff4SAfonso Bordado             // We need to bit compare the floats to ensure that we produce the correct values
2697e45cff4SAfonso Bordado             // on NaN's. The test suite expects to assert the precise bit pattern on NaN's or
2707e45cff4SAfonso Bordado             // works around it in the tests themselves.
2717ac3fda7Sbeetrees             (DataValue::F16(a), DataValue::F16(b)) => a.bits() == b.bits(),
2727e45cff4SAfonso Bordado             (DataValue::F32(a), DataValue::F32(b)) => a.bits() == b.bits(),
2737e45cff4SAfonso Bordado             (DataValue::F64(a), DataValue::F64(b)) => a.bits() == b.bits(),
2747ac3fda7Sbeetrees             (DataValue::F128(a), DataValue::F128(b)) => a.bits() == b.bits(),
2757e45cff4SAfonso Bordado 
2767e45cff4SAfonso Bordado             // We don't need to worry about F32x4 / F64x2 Since we compare V128 which is already the
2777e45cff4SAfonso Bordado             // raw bytes anyway
2787e45cff4SAfonso Bordado             (a, b) => a == b,
2797e45cff4SAfonso Bordado         }
2807e45cff4SAfonso Bordado     }
2816f6f79efSAndrew Brown }
2826f6f79efSAndrew Brown 
2836f6f79efSAndrew Brown /// Record failures to cast [DataValue].
28403fdbadfSbjorn3 #[derive(Debug, PartialEq)]
285099102d9SAlex Crichton #[expect(missing_docs, reason = "self-describing variants")]
2866f6f79efSAndrew Brown pub enum DataValueCastFailure {
2876f6f79efSAndrew Brown     TryInto(Type, Type),
288084383f6SAfonso Bordado     FromInteger(i128, Type),
2896f6f79efSAndrew Brown }
2906f6f79efSAndrew Brown 
29182f3ad4fSbjorn3 // This is manually implementing Error and Display instead of using thiserror to reduce the amount
29282f3ad4fSbjorn3 // of dependencies used by Cranelift.
293*0889323aSSSD impl core::error::Error for DataValueCastFailure {}
29403fdbadfSbjorn3 
29503fdbadfSbjorn3 impl Display for DataValueCastFailure {
fmt(&self, f: &mut Formatter) -> fmt::Result29603fdbadfSbjorn3     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
29703fdbadfSbjorn3         match self {
29803fdbadfSbjorn3             DataValueCastFailure::TryInto(from, to) => {
299a0442ea0SHamir Mahal                 write!(f, "unable to cast data value of type {from} to type {to}")
30003fdbadfSbjorn3             }
30103fdbadfSbjorn3             DataValueCastFailure::FromInteger(val, to) => {
302a0442ea0SHamir Mahal                 write!(f, "unable to cast i64({val}) to a data value of type {to}")
30303fdbadfSbjorn3             }
30403fdbadfSbjorn3         }
30503fdbadfSbjorn3     }
30603fdbadfSbjorn3 }
30703fdbadfSbjorn3 
3086f6f79efSAndrew Brown /// Helper for creating conversion implementations for [DataValue].
3096f6f79efSAndrew Brown macro_rules! build_conversion_impl {
3106f6f79efSAndrew Brown     ( $rust_ty:ty, $data_value_ty:ident, $cranelift_ty:ident ) => {
3116f6f79efSAndrew Brown         impl From<$rust_ty> for DataValue {
3126f6f79efSAndrew Brown             fn from(data: $rust_ty) -> Self {
3136f6f79efSAndrew Brown                 DataValue::$data_value_ty(data)
3146f6f79efSAndrew Brown             }
3156f6f79efSAndrew Brown         }
3166f6f79efSAndrew Brown 
3176f6f79efSAndrew Brown         impl TryInto<$rust_ty> for DataValue {
3186f6f79efSAndrew Brown             type Error = DataValueCastFailure;
3196f6f79efSAndrew Brown             fn try_into(self) -> Result<$rust_ty, Self::Error> {
3206f6f79efSAndrew Brown                 if let DataValue::$data_value_ty(v) = self {
3216f6f79efSAndrew Brown                     Ok(v)
3226f6f79efSAndrew Brown                 } else {
3236f6f79efSAndrew Brown                     Err(DataValueCastFailure::TryInto(
3246f6f79efSAndrew Brown                         self.ty(),
3256f6f79efSAndrew Brown                         types::$cranelift_ty,
3266f6f79efSAndrew Brown                     ))
3276f6f79efSAndrew Brown                 }
3286f6f79efSAndrew Brown             }
3296f6f79efSAndrew Brown         }
3306f6f79efSAndrew Brown     };
3316f6f79efSAndrew Brown }
3326f6f79efSAndrew Brown build_conversion_impl!(i8, I8, I8);
3336f6f79efSAndrew Brown build_conversion_impl!(i16, I16, I16);
3346f6f79efSAndrew Brown build_conversion_impl!(i32, I32, I32);
3356f6f79efSAndrew Brown build_conversion_impl!(i64, I64, I64);
336084383f6SAfonso Bordado build_conversion_impl!(i128, I128, I128);
3377ac3fda7Sbeetrees build_conversion_impl!(Ieee16, F16, F16);
3383778fa02SAndrew Brown build_conversion_impl!(Ieee32, F32, F32);
3393778fa02SAndrew Brown build_conversion_impl!(Ieee64, F64, F64);
3407ac3fda7Sbeetrees build_conversion_impl!(Ieee128, F128, F128);
3416f6f79efSAndrew Brown build_conversion_impl!([u8; 16], V128, I8X16);
3423ef89b77SDamian Heaton build_conversion_impl!([u8; 8], V64, I8X8);
343d48b3856Sbeetrees build_conversion_impl!([u8; 4], V32, I8X4);
344d48b3856Sbeetrees build_conversion_impl!([u8; 2], V16, I8X2);
3453a2025fdSAndrew Brown impl From<Offset32> for DataValue {
from(o: Offset32) -> Self3463a2025fdSAndrew Brown     fn from(o: Offset32) -> Self {
3473a2025fdSAndrew Brown         DataValue::from(Into::<i32>::into(o))
3483a2025fdSAndrew Brown     }
3493a2025fdSAndrew Brown }
3506f6f79efSAndrew Brown 
3516f6f79efSAndrew Brown impl Display for DataValue {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result3526f6f79efSAndrew Brown     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3536f6f79efSAndrew Brown         match self {
354a0442ea0SHamir Mahal             DataValue::I8(dv) => write!(f, "{dv}"),
355a0442ea0SHamir Mahal             DataValue::I16(dv) => write!(f, "{dv}"),
356a0442ea0SHamir Mahal             DataValue::I32(dv) => write!(f, "{dv}"),
357a0442ea0SHamir Mahal             DataValue::I64(dv) => write!(f, "{dv}"),
358a0442ea0SHamir Mahal             DataValue::I128(dv) => write!(f, "{dv}"),
3593778fa02SAndrew Brown             // The Ieee* wrappers here print the expected syntax.
360a0442ea0SHamir Mahal             DataValue::F16(dv) => write!(f, "{dv}"),
361a0442ea0SHamir Mahal             DataValue::F32(dv) => write!(f, "{dv}"),
362a0442ea0SHamir Mahal             DataValue::F64(dv) => write!(f, "{dv}"),
363a0442ea0SHamir Mahal             DataValue::F128(dv) => write!(f, "{dv}"),
3646f6f79efSAndrew Brown             // Again, for syntax consistency, use ConstantData, which in this case displays as hex.
3656f6f79efSAndrew Brown             DataValue::V128(dv) => write!(f, "{}", ConstantData::from(&dv[..])),
3663ef89b77SDamian Heaton             DataValue::V64(dv) => write!(f, "{}", ConstantData::from(&dv[..])),
367d48b3856Sbeetrees             DataValue::V32(dv) => write!(f, "{}", ConstantData::from(&dv[..])),
368d48b3856Sbeetrees             DataValue::V16(dv) => write!(f, "{}", ConstantData::from(&dv[..])),
3696f6f79efSAndrew Brown         }
3706f6f79efSAndrew Brown     }
3716f6f79efSAndrew Brown }
3726f6f79efSAndrew Brown 
3736f6f79efSAndrew Brown /// Helper structure for printing bracket-enclosed vectors of [DataValue]s.
3746f6f79efSAndrew Brown /// - for empty vectors, display `[]`
3756f6f79efSAndrew Brown /// - for single item vectors, display `42`, e.g.
3766f6f79efSAndrew Brown /// - for multiple item vectors, display `[42, 43, 44]`, e.g.
3776f6f79efSAndrew Brown pub struct DisplayDataValues<'a>(pub &'a [DataValue]);
3786f6f79efSAndrew Brown 
3796f6f79efSAndrew Brown impl<'a> Display for DisplayDataValues<'a> {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result3806f6f79efSAndrew Brown     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3816f6f79efSAndrew Brown         if self.0.len() == 1 {
3826f6f79efSAndrew Brown             write!(f, "{}", self.0[0])
3836f6f79efSAndrew Brown         } else {
3846f6f79efSAndrew Brown             write!(f, "[")?;
3856f6f79efSAndrew Brown             write_data_value_list(f, &self.0)?;
3866f6f79efSAndrew Brown             write!(f, "]")
3876f6f79efSAndrew Brown         }
3886f6f79efSAndrew Brown     }
3896f6f79efSAndrew Brown }
3906f6f79efSAndrew Brown 
3916f6f79efSAndrew Brown /// Helper function for displaying `Vec<DataValue>`.
write_data_value_list(f: &mut Formatter<'_>, list: &[DataValue]) -> fmt::Result3926f6f79efSAndrew Brown pub fn write_data_value_list(f: &mut Formatter<'_>, list: &[DataValue]) -> fmt::Result {
3936f6f79efSAndrew Brown     match list.len() {
3946f6f79efSAndrew Brown         0 => Ok(()),
3956f6f79efSAndrew Brown         1 => write!(f, "{}", list[0]),
3966f6f79efSAndrew Brown         _ => {
3976f6f79efSAndrew Brown             write!(f, "{}", list[0])?;
3986f6f79efSAndrew Brown             for dv in list.iter().skip(1) {
399a0442ea0SHamir Mahal                 write!(f, ", {dv}")?;
4006f6f79efSAndrew Brown             }
4016f6f79efSAndrew Brown             Ok(())
4026f6f79efSAndrew Brown         }
4036f6f79efSAndrew Brown     }
4046f6f79efSAndrew Brown }
4056f6f79efSAndrew Brown 
4066f6f79efSAndrew Brown #[cfg(test)]
4076f6f79efSAndrew Brown mod test {
4086f6f79efSAndrew Brown     use super::*;
4096f6f79efSAndrew Brown 
4106f6f79efSAndrew Brown     #[test]
type_conversions()4116f6f79efSAndrew Brown     fn type_conversions() {
4126f6f79efSAndrew Brown         assert_eq!(DataValue::V128([0; 16]).ty(), types::I8X16);
4136f6f79efSAndrew Brown         assert_eq!(
4146f6f79efSAndrew Brown             TryInto::<[u8; 16]>::try_into(DataValue::V128([0; 16])).unwrap(),
4156f6f79efSAndrew Brown             [0; 16]
4166f6f79efSAndrew Brown         );
4176f6f79efSAndrew Brown         assert_eq!(
4186f6f79efSAndrew Brown             TryInto::<i32>::try_into(DataValue::V128([0; 16])).unwrap_err(),
4196f6f79efSAndrew Brown             DataValueCastFailure::TryInto(types::I8X16, types::I32)
4206f6f79efSAndrew Brown         );
4216f6f79efSAndrew Brown     }
4226f6f79efSAndrew Brown }
423