1 use crate::r#ref::ref_to_val; 2 use crate::{ 3 from_valtype, into_valtype, wasm_ref_t, wasm_valkind_t, wasmtime_valkind_t, CStoreContextMut, 4 WASM_I32, 5 }; 6 use std::mem::{self, ManuallyDrop, MaybeUninit}; 7 use std::ptr; 8 use wasmtime::{AsContextMut, Func, HeapType, Ref, Val, ValType}; 9 10 #[repr(C)] 11 pub struct wasm_val_t { 12 pub kind: wasm_valkind_t, 13 pub of: wasm_val_union, 14 } 15 16 #[repr(C)] 17 #[derive(Copy, Clone)] 18 pub union wasm_val_union { 19 pub i32: i32, 20 pub i64: i64, 21 pub u32: u32, 22 pub u64: u64, 23 pub f32: f32, 24 pub f64: f64, 25 pub ref_: *mut wasm_ref_t, 26 } 27 28 impl Drop for wasm_val_t { 29 fn drop(&mut self) { 30 match into_valtype(self.kind) { 31 ValType::Ref(_) => unsafe { 32 if !self.of.ref_.is_null() { 33 drop(Box::from_raw(self.of.ref_)); 34 } 35 }, 36 _ => {} 37 } 38 } 39 } 40 41 impl Clone for wasm_val_t { 42 fn clone(&self) -> Self { 43 let mut ret = wasm_val_t { 44 kind: self.kind, 45 of: self.of, 46 }; 47 unsafe { 48 match into_valtype(self.kind) { 49 ValType::Ref(_) if !self.of.ref_.is_null() => { 50 ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone())); 51 } 52 _ => {} 53 } 54 } 55 return ret; 56 } 57 } 58 59 impl Default for wasm_val_t { 60 fn default() -> Self { 61 wasm_val_t { 62 kind: WASM_I32, 63 of: wasm_val_union { i32: 0 }, 64 } 65 } 66 } 67 68 impl wasm_val_t { 69 pub fn from_val(val: Val) -> wasm_val_t { 70 match val { 71 Val::I32(i) => wasm_val_t { 72 kind: from_valtype(&ValType::I32), 73 of: wasm_val_union { i32: i }, 74 }, 75 Val::I64(i) => wasm_val_t { 76 kind: from_valtype(&ValType::I64), 77 of: wasm_val_union { i64: i }, 78 }, 79 Val::F32(f) => wasm_val_t { 80 kind: from_valtype(&ValType::F32), 81 of: wasm_val_union { u32: f }, 82 }, 83 Val::F64(f) => wasm_val_t { 84 kind: from_valtype(&ValType::F64), 85 of: wasm_val_union { u64: f }, 86 }, 87 Val::ExternRef(_) => crate::abort("externref"), 88 Val::FuncRef(f) => wasm_val_t { 89 kind: from_valtype(&ValType::FUNCREF), 90 of: wasm_val_union { 91 ref_: f.map_or(ptr::null_mut(), |f| { 92 Box::into_raw(Box::new(wasm_ref_t { 93 r: Ref::Func(Some(f)), 94 })) 95 }), 96 }, 97 }, 98 _ => unimplemented!("wasm_val_t::from_val {:?}", val), 99 } 100 } 101 102 pub fn val(&self) -> Val { 103 match into_valtype(self.kind) { 104 ValType::I32 => Val::from(unsafe { self.of.i32 }), 105 ValType::I64 => Val::from(unsafe { self.of.i64 }), 106 ValType::F32 => Val::from(unsafe { self.of.f32 }), 107 ValType::F64 => Val::from(unsafe { self.of.f64 }), 108 ValType::Ref(r) => match (r.is_nullable(), r.heap_type()) { 109 (true, HeapType::Extern) => unsafe { 110 if self.of.ref_.is_null() { 111 Val::ExternRef(None) 112 } else { 113 ref_to_val(&*self.of.ref_) 114 } 115 }, 116 (true, HeapType::Func) => unsafe { 117 if self.of.ref_.is_null() { 118 Val::FuncRef(None) 119 } else { 120 ref_to_val(&*self.of.ref_) 121 } 122 }, 123 _ => unimplemented!("wasm_val_t: non-funcref and non-externref reference types"), 124 }, 125 ValType::V128 => unimplemented!("wasm_val_t: v128"), 126 } 127 } 128 } 129 130 #[no_mangle] 131 pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source: &wasm_val_t) { 132 crate::initialize(out, source.clone()); 133 } 134 135 #[no_mangle] 136 pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) { 137 ptr::drop_in_place(val); 138 } 139 140 #[repr(C)] 141 pub struct wasmtime_val_t { 142 pub kind: wasmtime_valkind_t, 143 pub of: wasmtime_val_union, 144 } 145 146 #[repr(C)] 147 pub union wasmtime_val_union { 148 pub i32: i32, 149 pub i64: i64, 150 pub f32: u32, 151 pub f64: u64, 152 pub funcref: wasmtime_func_t, 153 pub v128: [u8; 16], 154 } 155 156 #[repr(C)] 157 #[derive(Clone, Copy)] 158 pub struct wasmtime_func_t { 159 pub store_id: u64, 160 pub index: usize, 161 } 162 163 impl wasmtime_val_t { 164 pub fn from_val(cx: impl AsContextMut, val: Val) -> wasmtime_val_t { 165 // TODO: Needed for when we re-add externref support. 166 let _ = cx; 167 168 match val { 169 Val::I32(i) => wasmtime_val_t { 170 kind: crate::WASMTIME_I32, 171 of: wasmtime_val_union { i32: i }, 172 }, 173 Val::I64(i) => wasmtime_val_t { 174 kind: crate::WASMTIME_I64, 175 of: wasmtime_val_union { i64: i }, 176 }, 177 Val::F32(i) => wasmtime_val_t { 178 kind: crate::WASMTIME_F32, 179 of: wasmtime_val_union { f32: i }, 180 }, 181 Val::F64(i) => wasmtime_val_t { 182 kind: crate::WASMTIME_F64, 183 of: wasmtime_val_union { f64: i }, 184 }, 185 Val::ExternRef(_) => crate::abort("externref"), 186 Val::FuncRef(func) => wasmtime_val_t { 187 kind: crate::WASMTIME_FUNCREF, 188 of: wasmtime_val_union { 189 funcref: match func { 190 None => wasmtime_func_t { 191 store_id: 0, 192 index: 0, 193 }, 194 Some(func) => unsafe { mem::transmute::<Func, wasmtime_func_t>(func) }, 195 }, 196 }, 197 }, 198 Val::V128(val) => wasmtime_val_t { 199 kind: crate::WASMTIME_V128, 200 of: wasmtime_val_union { 201 v128: val.as_u128().to_le_bytes(), 202 }, 203 }, 204 } 205 } 206 207 pub unsafe fn to_val(&self, cx: impl AsContextMut) -> Val { 208 // TODO: needed for when we re-add externref support. 209 let _ = cx; 210 211 match self.kind { 212 crate::WASMTIME_I32 => Val::I32(self.of.i32), 213 crate::WASMTIME_I64 => Val::I64(self.of.i64), 214 crate::WASMTIME_F32 => Val::F32(self.of.f32), 215 crate::WASMTIME_F64 => Val::F64(self.of.f64), 216 crate::WASMTIME_V128 => Val::V128(u128::from_le_bytes(self.of.v128).into()), 217 crate::WASMTIME_FUNCREF => { 218 let store = self.of.funcref.store_id; 219 let index = self.of.funcref.index; 220 Val::FuncRef(if store == 0 && index == 0 { 221 None 222 } else { 223 Some(mem::transmute::<wasmtime_func_t, Func>(self.of.funcref)) 224 }) 225 } 226 other => panic!("unknown wasmtime_valkind_t: {}", other), 227 } 228 } 229 } 230 231 impl Drop for wasmtime_val_t { 232 fn drop(&mut self) { 233 // TODO: this drop impl is needed for when we re-add externref support. 234 } 235 } 236 237 #[no_mangle] 238 pub unsafe extern "C" fn wasmtime_val_delete( 239 cx: CStoreContextMut<'_>, 240 val: &mut ManuallyDrop<wasmtime_val_t>, 241 ) { 242 // TODO: needed for when we re-add externref support. 243 let _ = cx; 244 245 ManuallyDrop::drop(val) 246 } 247 248 #[no_mangle] 249 pub unsafe extern "C" fn wasmtime_val_copy( 250 mut cx: CStoreContextMut<'_>, 251 dst: &mut MaybeUninit<wasmtime_val_t>, 252 src: &wasmtime_val_t, 253 ) { 254 let val = src.to_val(&mut cx); 255 crate::initialize(dst, wasmtime_val_t::from_val(cx, val)) 256 } 257