1use {
2 crate::{
3 code::{Code, UncompiledCode},
4 decode::{Decode, DecodeError, Decoder},
5 error::Error,
6 exec,
7 instance::Instance,
8 into_func::IntoFunc,
9 stack::StackGuard,
10 store::{Handle, InternedFuncType, Store, StoreId, UnguardedHandle},
11 val::{Val, ValType},
12 },
13 std::{error, fmt, mem, sync::Arc},
14};
15
16#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20pub struct Func(pub(crate) Handle<FuncEntity>);
21
22impl Func {
23 pub fn wrap<Ts, U>(store: &mut Store, f: impl IntoFunc<Ts, U>) -> Self {
25 let (type_, trampoline) = f.into_func();
26 let type_ = store.get_or_intern_type(&type_);
27 Self(store.insert_func(FuncEntity::Host(HostFuncEntity::new(type_, trampoline))))
28 }
29
30 pub fn type_(self, store: &Store) -> &FuncType {
32 store.resolve_type(self.0.as_ref(store).type_())
33 }
34
35 pub fn call(self, store: &mut Store, args: &[Val], results: &mut [Val]) -> Result<(), Error> {
45 let type_ = self.type_(store);
46 if args.len() != type_.params().len() {
47 return Err(FuncError::ParamCountMismatch)?;
48 }
49 if results.len() != type_.results().len() {
50 return Err(FuncError::ResultCountMismatch)?;
51 }
52 for (arg, param_type) in args.iter().zip(type_.params().iter().copied()) {
53 if arg.type_() != param_type {
54 return Err(FuncError::ParamTypeMismatch)?;
55 }
56 }
57 exec::exec(store, self, args, results)
58 }
59
60 pub(crate) fn new_wasm(
62 store: &mut Store,
63 type_: InternedFuncType,
64 instance: Instance,
65 code: UncompiledCode,
66 ) -> Self {
67 Self(store.insert_func(FuncEntity::Wasm(WasmFuncEntity::new(type_, instance, code))))
68 }
69
70 pub(crate) unsafe fn from_unguarded(func: UnguardedFunc, store_id: StoreId) -> Self {
76 Self(Handle::from_unguarded(func, store_id))
77 }
78
79 pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedFunc {
85 self.0.to_unguarded(store_id)
86 }
87
88 pub(crate) fn compile(self, store: &mut Store) {
90 let FuncEntity::Wasm(func) = self.0.as_mut(store) else {
91 return;
92 };
93 let instance = func.instance().clone();
94 let code = match mem::replace(func.code_mut(), Code::Compiling) {
95 Code::Uncompiled(code) => {
96 let engine = store.engine().clone();
97 engine.compile(store, self, &instance, &code)
98 }
99 Code::Compiling => panic!("function is already being compiled"),
100 Code::Compiled(state) => state,
101 };
102 let FuncEntity::Wasm(func) = self.0.as_mut(store) else {
103 unreachable!();
104 };
105 *func.code_mut() = Code::Compiled(code);
106 }
107}
108
109pub(crate) type UnguardedFunc = UnguardedHandle<FuncEntity>;
111
112#[derive(Clone, Debug, Eq, Hash, PartialEq)]
114pub struct FuncType {
115 params_results: Arc<[ValType]>,
116 param_count: usize,
117}
118
119impl FuncType {
120 pub fn new(
122 params: impl IntoIterator<Item = ValType>,
123 results: impl IntoIterator<Item = ValType>,
124 ) -> Self {
125 let mut params_results = params.into_iter().collect::<Vec<_>>();
126 let param_count = params_results.len();
127 params_results.extend(results);
128 Self {
129 params_results: params_results.into(),
130 param_count,
131 }
132 }
133
134 pub fn params(&self) -> &[ValType] {
136 &self.params_results[..self.param_count]
137 }
138
139 pub fn results(&self) -> &[ValType] {
141 &self.params_results[self.param_count..]
142 }
143
144 pub(crate) fn from_val_type(type_: Option<ValType>) -> FuncType {
147 thread_local! {
148 static TYPES: [FuncType; 7] = [
149 FuncType::new(vec![], vec![]),
150 FuncType::new(vec![], vec![ValType::I32]),
151 FuncType::new(vec![], vec![ValType::I64]),
152 FuncType::new(vec![], vec![ValType::F32]),
153 FuncType::new(vec![], vec![ValType::F64]),
154 FuncType::new(vec![], vec![ValType::FuncRef]),
155 FuncType::new(vec![], vec![ValType::ExternRef]),
156 ];
157 }
158
159 TYPES.with(|types| match type_ {
160 None => types[0].clone(),
161 Some(ValType::I32) => types[1].clone(),
162 Some(ValType::I64) => types[2].clone(),
163 Some(ValType::F32) => types[3].clone(),
164 Some(ValType::F64) => types[4].clone(),
165 Some(ValType::FuncRef) => types[5].clone(),
166 Some(ValType::ExternRef) => types[6].clone(),
167 })
168 }
169
170 pub(crate) fn call_frame_size(&self) -> usize {
173 self.params().len().max(self.results().len()) + 4
174 }
175}
176
177impl Decode for FuncType {
178 fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
179 if decoder.read_byte()? != 0x60 {
180 return Err(DecodeError::new("malformed function type"))?;
181 }
182 let mut param_result_types: Vec<_> = decoder.decode_iter()?.collect::<Result<_, _>>()?;
183 let param_count = param_result_types.len();
184 let result_types = decoder.decode_iter()?;
185 param_result_types.reserve(result_types.size_hint().0);
186 for result_type in result_types {
187 param_result_types.push(result_type?);
188 }
189 Ok(Self {
190 params_results: param_result_types.into(),
191 param_count,
192 })
193 }
194}
195
196#[derive(Clone, Copy, Debug)]
198pub enum FuncError {
199 ParamCountMismatch,
200 ParamTypeMismatch,
201 ResultCountMismatch,
202}
203
204impl fmt::Display for FuncError {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 match self {
207 Self::ParamCountMismatch => write!(f, "function parameter count mismatch"),
208 Self::ParamTypeMismatch => write!(f, "function parameter type mismatch"),
209 Self::ResultCountMismatch => write!(f, "function result count mismatch"),
210 }
211 }
212}
213
214impl error::Error for FuncError {}
215
216#[derive(Debug)]
218pub enum FuncEntity {
219 Wasm(WasmFuncEntity),
220 Host(HostFuncEntity),
221}
222
223impl FuncEntity {
224 pub(crate) fn type_(&self) -> InternedFuncType {
226 match self {
227 Self::Wasm(func) => func.type_(),
228 Self::Host(func) => func.type_(),
229 }
230 }
231}
232
233#[derive(Debug)]
234pub(crate) struct WasmFuncEntity {
235 type_: InternedFuncType,
236 instance: Instance,
237 code: Code,
238}
239
240impl WasmFuncEntity {
241 fn new(type_: InternedFuncType, instance: Instance, code: UncompiledCode) -> WasmFuncEntity {
243 WasmFuncEntity {
244 type_,
245 instance,
246 code: Code::Uncompiled(code),
247 }
248 }
249
250 pub(crate) fn type_(&self) -> InternedFuncType {
252 self.type_
253 }
254
255 pub(crate) fn instance(&self) -> &Instance {
257 &self.instance
258 }
259
260 pub(crate) fn code(&self) -> &Code {
262 &self.code
263 }
264
265 pub(crate) fn code_mut(&mut self) -> &mut Code {
267 &mut self.code
268 }
269}
270
271#[derive(Debug)]
272pub struct HostFuncEntity {
273 type_: InternedFuncType,
274 trampoline: HostFuncTrampoline,
275}
276
277impl HostFuncEntity {
278 pub(crate) fn new(type_: InternedFuncType, trampoline: HostFuncTrampoline) -> Self {
280 Self { type_, trampoline }
281 }
282
283 pub(crate) fn type_(&self) -> InternedFuncType {
285 self.type_
286 }
287
288 pub(crate) fn trampoline(&self) -> &HostFuncTrampoline {
290 &self.trampoline
291 }
292}
293
294#[derive(Clone)]
295pub struct HostFuncTrampoline {
296 inner: Arc<dyn Fn(&mut Store, StackGuard) -> Result<StackGuard, Error> + Send + Sync + 'static>,
297}
298
299impl HostFuncTrampoline {
300 pub fn new(
301 inner: impl Fn(&mut Store, StackGuard) -> Result<StackGuard, Error> + Send + Sync + 'static,
302 ) -> Self {
303 Self {
304 inner: Arc::new(inner),
305 }
306 }
307
308 pub(crate) fn call(&self, store: &mut Store, stack: StackGuard) -> Result<StackGuard, Error> {
309 (self.inner)(store, stack)
310 }
311}
312
313impl fmt::Debug for HostFuncTrampoline {
314 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
315 f.debug_struct("HostFuncTrampoline").finish()
316 }
317}