1use crate::ast::SlotShape;
21use crate::ast::{PortType, Value};
22
23pub(crate) fn borrow_pair(v: &Value) -> Option<(u64, u64)> {
28 Some(match v {
29 Value::Str(s) => (s.as_ptr() as usize as u64, s.len() as u64),
30 Value::Bytes(b) => (b.as_ptr() as usize as u64, b.len() as u64),
31 Value::Json(_) | Value::Ext(_) | Value::Handle(_) => (v as *const Value as usize as u64, 1),
32 Value::VecF32(v) => slice_pair(v.as_slice()),
33 Value::VecF64(v) => slice_pair(v.as_slice()),
34 Value::VecF16(v) => slice_pair(v.as_slice()),
35 Value::VecI8(v) => slice_pair(v.as_slice()),
36 Value::VecI16(v) => slice_pair(v.as_slice()),
37 Value::VecI32(v) => slice_pair(v.as_slice()),
38 Value::VecI64(v) => slice_pair(v.as_slice()),
39 _ => return None,
40 })
41}
42
43#[inline]
45pub(crate) fn slice_pair<T>(s: &[T]) -> (u64, u64) {
46 (s.as_ptr() as usize as u64, s.len() as u64)
47}
48
49#[inline]
52pub(crate) fn empty_pair() -> (u64, u64) {
53 (
54 std::ptr::NonNull::<u8>::dangling().as_ptr() as usize as u64,
55 0,
56 )
57}
58
59#[cfg(feature = "jit")]
63pub(crate) fn encode_slots(v: &Value, out: &mut [u64]) -> Option<()> {
64 match v {
65 Value::U64(x) => out[0] = *x,
66 Value::I64(x) => out[0] = *x as u64,
67 Value::F64(x) => out[0] = x.to_bits(),
68 Value::Bool(b) => out[0] = *b as u64,
69 _ => {
70 let (p, l) = borrow_pair(v)?;
71 out[0] = p;
72 out[1] = l;
73 }
74 }
75 Some(())
76}
77
78pub(crate) unsafe fn decode_pair(ty: PortType, ptr: u64, len: u64) -> Value {
88 use crate::ast::SliceArc;
89 let (p, n) = (ptr as usize, len as usize);
90 unsafe {
92 match ty {
93 PortType::Str => Value::Str(std::sync::Arc::from(std::str::from_utf8_unchecked(
94 std::slice::from_raw_parts(p as *const u8, n),
95 ))),
96 PortType::Bytes => Value::Bytes(std::sync::Arc::from(std::slice::from_raw_parts(
97 p as *const u8,
98 n,
99 ))),
100 PortType::Json | PortType::Ext | PortType::Handle => {
101 if n == 0 {
102 Value::None
103 } else {
104 (*(p as *const Value)).clone()
105 }
106 }
107 PortType::VecF32 => Value::VecF32(SliceArc::from_vec(
108 std::slice::from_raw_parts(p as *const f32, n).to_vec(),
109 )),
110 PortType::VecF64 => Value::VecF64(SliceArc::from_vec(
111 std::slice::from_raw_parts(p as *const f64, n).to_vec(),
112 )),
113 PortType::VecF16 => Value::VecF16(SliceArc::from_vec(
114 std::slice::from_raw_parts(p as *const half::f16, n).to_vec(),
115 )),
116 PortType::VecI8 => Value::VecI8(SliceArc::from_vec(
117 std::slice::from_raw_parts(p as *const i8, n).to_vec(),
118 )),
119 PortType::VecI16 => Value::VecI16(SliceArc::from_vec(
120 std::slice::from_raw_parts(p as *const i16, n).to_vec(),
121 )),
122 PortType::VecI32 => Value::VecI32(SliceArc::from_vec(
123 std::slice::from_raw_parts(p as *const i32, n).to_vec(),
124 )),
125 PortType::VecI64 => Value::VecI64(SliceArc::from_vec(
126 std::slice::from_raw_parts(p as *const i64, n).to_vec(),
127 )),
128 other => panic!("{other:?} is not a Ref2-colored port type"),
129 }
130 }
131}
132
133pub(crate) fn carrier_port(ty: PortType) -> PortType {
139 match ty {
140 PortType::I8 | PortType::I16 | PortType::I32 => PortType::I64,
141 PortType::U32 | PortType::U16 | PortType::U8 | PortType::F32 | PortType::F16 => {
142 PortType::U64
143 }
144 other => other,
145 }
146}
147
148pub(crate) fn decode_slot(slots: &[u64], ty: PortType) -> Value {
161 use crate::ast::{Bits128, RegLanes, SlotColor};
162 match ty.slot_color() {
163 SlotColor::Imm1 => match ty {
164 PortType::F64 => Value::F64(f64::from_bits(slots[0])),
165 PortType::Bool => Value::Bool(slots[0] != 0),
166 PortType::I64 | PortType::I8 | PortType::I16 | PortType::I32 => {
169 Value::I64(slots[0] as i64)
170 }
171 PortType::U64
175 | PortType::U32
176 | PortType::U16
177 | PortType::U8
178 | PortType::F32
179 | PortType::F16 => Value::U64(slots[0]),
180 other => unreachable!("{other:?} is colored Imm1 but has no one-slot carrier"),
181 },
182 SlotColor::Imm2 => {
185 let limbs = Bits128([slots[0], slots[1]]);
186 match ty {
187 PortType::U128 => Value::U128(limbs),
188 PortType::I128 => Value::I128(limbs),
189 PortType::Reg128 => Value::Reg128(limbs, RegLanes::Raw),
190 PortType::RegI8x16 => Value::Reg128(limbs, RegLanes::I8x16),
191 PortType::RegI16x8 => Value::Reg128(limbs, RegLanes::I16x8),
192 PortType::RegI32x4 => Value::Reg128(limbs, RegLanes::I32x4),
193 PortType::RegI64x2 => Value::Reg128(limbs, RegLanes::I64x2),
194 PortType::RegF16x8 => Value::Reg128(limbs, RegLanes::F16x8),
195 PortType::RegF32x4 => Value::Reg128(limbs, RegLanes::F32x4),
196 PortType::RegF64x2 => Value::Reg128(limbs, RegLanes::F64x2),
197 other => unreachable!("{other:?} is colored Imm2 but is not a 128-bit value"),
198 }
199 }
200 SlotColor::Ref2 => unsafe { decode_pair(ty, slots[0], slots[1]) },
203 }
204}
205
206pub fn decode_output(buffer: &[u64], slot: usize, ty: PortType) -> Value {
209 decode_slot(&buffer[slot..], ty)
210}
211
212pub unsafe fn arg_ref<'a>(ty: PortType, slots: &'a [u64]) -> crate::ast::ValueRef<'a> {
220 use crate::ast::ValueRef;
221 let (p, n) = (
222 slots.first().copied().unwrap_or(0) as usize,
223 slots.get(1).copied().unwrap_or(0) as usize,
224 );
225 unsafe {
227 match ty {
228 PortType::U64 => ValueRef::U64(slots[0]),
229 PortType::I64 | PortType::I8 | PortType::I16 | PortType::I32 => {
230 ValueRef::I64(slots[0] as i64)
231 }
232 PortType::F64 => ValueRef::F64(f64::from_bits(slots[0])),
233 PortType::Bool => ValueRef::Bool(slots[0] != 0),
234 PortType::Str => ValueRef::Str(std::str::from_utf8_unchecked(
235 std::slice::from_raw_parts(p as *const u8, n),
236 )),
237 PortType::Bytes => ValueRef::Bytes(std::slice::from_raw_parts(p as *const u8, n)),
238 PortType::Json | PortType::Ext | PortType::Handle => {
239 if n == 0 {
240 ValueRef::None
241 } else {
242 ValueRef::from(&*(p as *const Value))
243 }
244 }
245 _ => ValueRef::U64(slots[0]),
246 }
247 }
248}