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")]
64pub(crate) fn encode_slots(v: &Value, ty: PortType, out: &mut [u64]) -> Option<()> {
65 if ty == PortType::Dyn {
66 (out[0], out[1]) = match v {
67 Value::None => empty_pair(),
68 v => (v as *const Value as usize as u64, 1),
69 };
70 return Some(());
71 }
72 match v {
73 Value::U64(x) => out[0] = *x,
74 Value::I64(x) => out[0] = *x as u64,
75 Value::F64(x) => out[0] = x.to_bits(),
76 Value::Bool(b) => out[0] = *b as u64,
77 _ => {
78 let (p, l) = borrow_pair(v)?;
79 out[0] = p;
80 out[1] = l;
81 }
82 }
83 Some(())
84}
85
86pub(crate) unsafe fn decode_pair(ty: PortType, ptr: u64, len: u64) -> Value {
96 use crate::ast::SliceArc;
97 let (p, n) = (ptr as usize, len as usize);
98 unsafe {
100 match ty {
101 PortType::Str => Value::Str(std::sync::Arc::from(std::str::from_utf8_unchecked(
102 std::slice::from_raw_parts(p as *const u8, n),
103 ))),
104 PortType::Bytes => Value::Bytes(std::sync::Arc::from(std::slice::from_raw_parts(
105 p as *const u8,
106 n,
107 ))),
108 PortType::Json | PortType::Ext | PortType::Handle | PortType::Dyn => {
109 if n == 0 {
110 Value::None
111 } else {
112 (*(p as *const Value)).clone()
113 }
114 }
115 PortType::VecF32 => Value::VecF32(SliceArc::from_vec(
116 std::slice::from_raw_parts(p as *const f32, n).to_vec(),
117 )),
118 PortType::VecF64 => Value::VecF64(SliceArc::from_vec(
119 std::slice::from_raw_parts(p as *const f64, n).to_vec(),
120 )),
121 PortType::VecF16 => Value::VecF16(SliceArc::from_vec(
122 std::slice::from_raw_parts(p as *const half::f16, n).to_vec(),
123 )),
124 PortType::VecI8 => Value::VecI8(SliceArc::from_vec(
125 std::slice::from_raw_parts(p as *const i8, n).to_vec(),
126 )),
127 PortType::VecI16 => Value::VecI16(SliceArc::from_vec(
128 std::slice::from_raw_parts(p as *const i16, n).to_vec(),
129 )),
130 PortType::VecI32 => Value::VecI32(SliceArc::from_vec(
131 std::slice::from_raw_parts(p as *const i32, n).to_vec(),
132 )),
133 PortType::VecI64 => Value::VecI64(SliceArc::from_vec(
134 std::slice::from_raw_parts(p as *const i64, n).to_vec(),
135 )),
136 other => panic!("{other:?} is not a Ref2-colored port type"),
137 }
138 }
139}
140
141pub(crate) fn carrier_port(ty: PortType) -> PortType {
147 match ty {
148 PortType::I8 | PortType::I16 | PortType::I32 => PortType::I64,
149 PortType::U32 | PortType::U16 | PortType::U8 | PortType::F32 | PortType::F16 => {
150 PortType::U64
151 }
152 other => other,
153 }
154}
155
156pub(crate) fn decode_slot(slots: &[u64], ty: PortType) -> Value {
166 use crate::ast::{Bits128, RegLanes, SlotColor};
167 match ty.slot_color() {
168 SlotColor::Imm1 => match ty {
169 PortType::F64 => Value::F64(f64::from_bits(slots[0])),
170 PortType::Bool => Value::Bool(slots[0] != 0),
171 PortType::I64 | PortType::I8 | PortType::I16 | PortType::I32 => {
174 Value::I64(slots[0] as i64)
175 }
176 PortType::U64
180 | PortType::U32
181 | PortType::U16
182 | PortType::U8
183 | PortType::F32
184 | PortType::F16 => Value::U64(slots[0]),
185 other => unreachable!("{other:?} is colored Imm1 but has no one-slot carrier"),
186 },
187 SlotColor::Imm2 => {
190 let limbs = Bits128([slots[0], slots[1]]);
191 match ty {
192 PortType::U128 => Value::U128(limbs),
193 PortType::I128 => Value::I128(limbs),
194 PortType::Reg128 => Value::Reg128(limbs, RegLanes::Raw),
195 PortType::RegI8x16 => Value::Reg128(limbs, RegLanes::I8x16),
196 PortType::RegI16x8 => Value::Reg128(limbs, RegLanes::I16x8),
197 PortType::RegI32x4 => Value::Reg128(limbs, RegLanes::I32x4),
198 PortType::RegI64x2 => Value::Reg128(limbs, RegLanes::I64x2),
199 PortType::RegF16x8 => Value::Reg128(limbs, RegLanes::F16x8),
200 PortType::RegF32x4 => Value::Reg128(limbs, RegLanes::F32x4),
201 PortType::RegF64x2 => Value::Reg128(limbs, RegLanes::F64x2),
202 other => unreachable!("{other:?} is colored Imm2 but is not a 128-bit value"),
203 }
204 }
205 SlotColor::Ref2 => unsafe { decode_pair(ty, slots[0], slots[1]) },
208 }
209}
210
211pub fn decode_output(buffer: &[u64], slot: usize, ty: PortType) -> Value {
214 decode_slot(&buffer[slot..], ty)
215}
216
217pub unsafe fn arg_ref<'a>(ty: PortType, slots: &'a [u64]) -> crate::ast::ValueRef<'a> {
225 use crate::ast::ValueRef;
226 let (p, n) = (
227 slots.first().copied().unwrap_or(0) as usize,
228 slots.get(1).copied().unwrap_or(0) as usize,
229 );
230 unsafe {
232 match ty {
233 PortType::U64 => ValueRef::U64(slots[0]),
234 PortType::I64 | PortType::I8 | PortType::I16 | PortType::I32 => {
235 ValueRef::I64(slots[0] as i64)
236 }
237 PortType::F64 => ValueRef::F64(f64::from_bits(slots[0])),
238 PortType::Bool => ValueRef::Bool(slots[0] != 0),
239 PortType::Str => ValueRef::Str(std::str::from_utf8_unchecked(
240 std::slice::from_raw_parts(p as *const u8, n),
241 )),
242 PortType::Bytes => ValueRef::Bytes(std::slice::from_raw_parts(p as *const u8, n)),
243 PortType::Json | PortType::Ext | PortType::Handle | PortType::Dyn => {
244 if n == 0 {
245 ValueRef::None
246 } else {
247 ValueRef::from(&*(p as *const Value))
248 }
249 }
250 _ => ValueRef::U64(slots[0]),
251 }
252 }
253}