1use std::marker::*;
2use std::mem::*;
3use std::sync::atomic::*;
4use std::sync::*;
5use std::usize;
6
7use bytemuck::*;
8use wasm_runtime_layer::*;
9#[allow(unused_imports)]
10use wasmtime_environ::component::StringEncoding;
11
12#[allow(unused_imports)]
13use crate::abi::{Generator, *};
14use crate::types::{FuncType, ValueType};
15use crate::values::Value;
16use crate::{AsContext, AsContextMut, StoreContextMut, *};
17
18#[derive(Clone, Debug)]
20pub(crate) enum FuncImpl {
21 GuestFunc(Option<crate::Instance>, Arc<GuestFunc>),
23 HostFunc(Arc<AtomicUsize>),
25}
26
27#[derive(Debug)]
29pub(crate) struct GuestFunc {
30 pub callee: wasm_runtime_layer::Func,
32 pub component: Arc<ComponentInner>,
34 pub encoding: StringEncoding,
36 pub function: Function,
38 pub memory: Option<Memory>,
40 pub realloc: Option<wasm_runtime_layer::Func>,
42 pub post_return: Option<wasm_runtime_layer::Func>,
44 pub state_table: Arc<StateTable>,
46 pub types: Arc<[crate::types::ValueType]>,
48 pub instance_id: u64,
50 pub interface_id: Option<InterfaceIdentifier>,
52}
53
54#[derive(Clone, Debug)]
56pub struct Func {
57 pub(crate) store_id: u64,
59 pub(crate) ty: FuncType,
61 pub(crate) backing: FuncImpl,
63}
64
65impl Func {
66 pub fn new<C: AsContextMut>(
68 mut ctx: C,
69 ty: FuncType,
70 f: impl 'static
71 + Send
72 + Sync
73 + Fn(StoreContextMut<C::UserState, C::Engine>, &[Value], &mut [Value]) -> Result<()>,
74 ) -> Self {
75 let mut ctx_mut = ctx.as_context_mut();
76 let data = ctx_mut.inner.data_mut();
77 let idx = data.host_functions.push(f);
78
79 Self {
80 store_id: data.id,
81 ty,
82 backing: FuncImpl::HostFunc(idx),
83 }
84 }
85
86 pub fn call<C: AsContextMut>(
92 &self,
93 mut ctx: C,
94 arguments: &[Value],
95 results: &mut [Value],
96 ) -> Result<()> {
97 if ctx.as_context().inner.data().id != self.store_id {
98 panic!("Attempted to call function with incorrect store.");
99 }
100
101 self.ty.match_params(arguments)?;
102
103 if self.ty.results().len() != results.len() {
104 bail!("Incorrect result length.");
105 }
106
107 match &self.backing {
108 FuncImpl::GuestFunc(i, x) => {
109 let GuestFunc {
110 callee,
111 component,
112 encoding,
113 function,
114 memory,
115 realloc,
116 state_table,
117 post_return,
118 types,
119 instance_id,
120 interface_id,
121 } = &**x;
122
123 ensure!(
124 !state_table.dropped.load(Ordering::Acquire),
125 "Instance had been dropped."
126 );
127
128 let mut bindgen = FuncBindgen {
129 ctx,
130 flat_results: Vec::default(),
131 arguments,
132 results,
133 callee_interface: None,
134 callee_wasm: Some(callee),
135 component,
136 encoding,
137 memory,
138 realloc,
139 resource_tables: &state_table.resource_tables,
140 post_return,
141 types,
142 handles_to_drop: Vec::new(),
143 required_dropped: Vec::new(),
144 instance_id: *instance_id,
145 store_id: self.store_id,
146 };
147
148 Ok(Generator::new(
149 &component.resolve,
150 AbiVariant::GuestExport,
151 LiftLower::LowerArgsLiftResults,
152 &mut bindgen,
153 )
154 .call(function)
155 .map_err(|error| FuncError {
156 name: function.name.clone(),
157 interface: interface_id.clone(),
158 instance: i.as_ref().expect("No instance available.").clone(),
159 error,
160 })?)
161 }
162 FuncImpl::HostFunc(idx) => {
163 let callee = ctx.as_context().inner.data().host_functions.get(idx);
164 (callee)(ctx.as_context_mut(), arguments, results)?;
165 self.ty.match_results(results)
166 }
167 }
168 }
169
170 pub fn ty(&self) -> FuncType {
172 self.ty.clone()
173 }
174
175 pub fn typed<P: ComponentList, R: ComponentList>(&self) -> Result<TypedFunc<P, R>> {
177 let mut params_results = vec![ValueType::Bool; P::LEN + R::LEN];
178 P::into_tys(&mut params_results[..P::LEN]);
179 R::into_tys(&mut params_results[P::LEN..]);
180 ensure!(
181 ¶ms_results[..P::LEN] == self.ty.params(),
182 "Parameters did not match function signature. Expected {:?} but got {:?}",
183 self.ty.params(),
184 ¶ms_results[..P::LEN]
185 );
186 ensure!(
187 ¶ms_results[P::LEN..] == self.ty.results(),
188 "Results did not match function signature. Expected {:?} but got {:?}",
189 self.ty.results(),
190 ¶ms_results[P::LEN..]
191 );
192 Ok(TypedFunc {
193 inner: self.clone(),
194 data: PhantomData,
195 })
196 }
197
198 pub(crate) fn instantiate(&self, inst: crate::Instance) -> Self {
200 if let FuncImpl::GuestFunc(None, y) = &self.backing {
201 Self {
202 store_id: self.store_id,
203 backing: FuncImpl::GuestFunc(Some(inst), y.clone()),
204 ty: self.ty.clone(),
205 }
206 } else {
207 panic!("Function was not an uninitialized guest function.");
208 }
209 }
210
211 pub(crate) fn call_from_guest<C: AsContextMut>(
213 &self,
214 ctx: C,
215 options: &GuestInvokeOptions,
216 arguments: &[wasm_runtime_layer::Value],
217 results: &mut [wasm_runtime_layer::Value],
218 ) -> Result<()> {
219 ensure!(
220 self.store_id == options.store_id,
221 "Function stores did not match."
222 );
223
224 let args = arguments
225 .iter()
226 .map(TryFrom::try_from)
227 .collect::<Result<Vec<_>>>()?;
228 let mut res = vec![Value::Bool(false); results.len()];
229
230 let mut bindgen = FuncBindgen {
231 ctx,
232 flat_results: Vec::default(),
233 arguments: &args,
234 results: &mut res,
235 callee_interface: Some(self),
236 callee_wasm: None,
237 component: &options.component,
238 encoding: &options.encoding,
239 memory: &options.memory,
240 realloc: &options.realloc,
241 resource_tables: &options.state_table.resource_tables,
242 post_return: &options.post_return,
243 types: &options.types,
244 handles_to_drop: Vec::new(),
245 required_dropped: Vec::new(),
246 instance_id: options.instance_id,
247 store_id: self.store_id,
248 };
249
250 Generator::new(
251 &options.component.resolve,
252 AbiVariant::GuestImport,
253 LiftLower::LiftArgsLowerResults,
254 &mut bindgen,
255 )
256 .call(&options.function)?;
257
258 for (idx, val) in res.into_iter().enumerate() {
259 results[idx] = (&val).try_into()?;
260 }
261
262 Ok(())
263 }
264}
265
266pub(crate) struct GuestInvokeOptions {
268 pub component: Arc<ComponentInner>,
270 pub encoding: StringEncoding,
272 pub function: Function,
274 pub memory: Option<Memory>,
276 pub realloc: Option<wasm_runtime_layer::Func>,
278 pub post_return: Option<wasm_runtime_layer::Func>,
280 pub state_table: Arc<StateTable>,
282 pub types: Arc<[crate::types::ValueType]>,
284 pub instance_id: u64,
286 pub store_id: u64,
288}
289
290struct FuncBindgen<'a, C: AsContextMut> {
292 pub callee_interface: Option<&'a Func>,
294 pub callee_wasm: Option<&'a wasm_runtime_layer::Func>,
296 pub component: &'a ComponentInner,
298 pub ctx: C,
300 pub encoding: &'a StringEncoding,
302 pub flat_results: Vec<wasm_runtime_layer::Value>,
304 pub memory: &'a Option<Memory>,
306 pub realloc: &'a Option<wasm_runtime_layer::Func>,
308 pub post_return: &'a Option<wasm_runtime_layer::Func>,
310 pub arguments: &'a [Value],
312 pub results: &'a mut [Value],
314 pub resource_tables: &'a Mutex<Vec<HandleTable>>,
316 pub types: &'a [crate::types::ValueType],
318 pub handles_to_drop: Vec<(u32, i32)>,
320 pub required_dropped: Vec<(bool, u32, i32, Arc<AtomicBool>)>,
322 pub instance_id: u64,
324 pub store_id: u64,
326}
327
328impl<'a, C: AsContextMut> FuncBindgen<'a, C> {
329 fn load<B: Blittable>(&self, offset: usize) -> Result<B> {
331 Ok(B::from_bytes(<B::Array as ByteArray>::load(
332 &self.ctx,
333 self.memory.as_ref().expect("No memory."),
334 offset,
335 )?))
336 }
337
338 fn store<B: Blittable>(&mut self, offset: usize, value: B) -> Result<()> {
340 value.to_bytes().store(
341 &mut self.ctx,
342 self.memory.as_ref().expect("No memory."),
343 offset,
344 )
345 }
346
347 fn load_array<B: Blittable>(&self, offset: usize, len: usize) -> Result<Arc<[B]>> {
349 let mut raw_memory = B::zeroed_array(len);
350 self.memory.as_ref().expect("No memory").read(
351 self.ctx.as_context().inner,
352 offset,
353 B::to_le_slice_mut(
354 Arc::get_mut(&mut raw_memory).expect("Could not get exclusive reference."),
355 ),
356 )?;
357 Ok(raw_memory)
358 }
359
360 fn store_array<B: Blittable>(&mut self, offset: usize, value: &[B]) -> Result<()> {
362 self.memory.as_ref().expect("No memory.").write(
363 self.ctx.as_context_mut().inner,
364 offset,
365 B::to_le_slice(value),
366 )
367 }
368}
369
370impl<'a, C: AsContextMut> Bindgen for FuncBindgen<'a, C> {
371 type Operand = Value;
372
373 fn emit(
374 &mut self,
375 _resolve: &Resolve,
376 inst: &Instruction<'_>,
377 operands: &mut Vec<Self::Operand>,
378 results: &mut Vec<Self::Operand>,
379 ) -> Result<()> {
380 match inst {
381 Instruction::GetArg { nth } => results.push(
382 self.arguments
383 .get(*nth)
384 .cloned()
385 .ok_or_else(|| Error::msg("Invalid argument count."))?,
386 ),
387 Instruction::I32Const { val } => results.push(Value::S32(*val)),
388 Instruction::Bitcasts { casts } => {
389 for (cast, op) in casts.iter().zip(operands) {
390 match cast {
391 Bitcast::I32ToF32 => require_matches!(
392 op,
393 Value::S32(x),
394 results.push(Value::F32(f32::from_bits(*x as u32)))
395 ),
396 Bitcast::F32ToI32 => require_matches!(
397 op,
398 Value::F32(x),
399 results.push(Value::S32(x.to_bits() as i32))
400 ),
401 Bitcast::I64ToF64 => require_matches!(
402 op,
403 Value::S64(x),
404 results.push(Value::F64(f64::from_bits(*x as u64)))
405 ),
406 Bitcast::F64ToI64 => require_matches!(
407 op,
408 Value::F64(x),
409 results.push(Value::S64(x.to_bits() as i64))
410 ),
411 Bitcast::I32ToI64 => {
412 require_matches!(op, Value::S32(x), results.push(Value::S64(*x as i64)))
413 }
414 Bitcast::I64ToI32 => {
415 require_matches!(op, Value::S64(x), results.push(Value::S32(*x as i32)))
416 }
417 Bitcast::I64ToF32 => {
418 require_matches!(op, Value::S64(x), results.push(Value::F32(*x as f32)))
419 }
420 Bitcast::F32ToI64 => {
421 require_matches!(op, Value::F32(x), results.push(Value::S64(*x as i64)))
422 }
423 Bitcast::None => results.push(op.clone()),
424 }
425 }
426 }
427 Instruction::ConstZero { tys } => {
428 for t in tys.iter() {
429 match t {
430 WasmType::I32 => results.push(Value::S32(0)),
431 WasmType::I64 => results.push(Value::S64(0)),
432 WasmType::F32 => results.push(Value::F32(0.0)),
433 WasmType::F64 => results.push(Value::F64(0.0)),
434 }
435 }
436 }
437 Instruction::I32Load { offset } => require_matches!(
438 operands.pop(),
439 Some(Value::S32(x)),
440 results.push(Value::S32(self.load((x as usize) + (*offset as usize))?))
441 ),
442 Instruction::I32Load8U { offset } => require_matches!(
443 operands.pop(),
444 Some(Value::S32(x)),
445 results.push(Value::S32(
446 self.load::<u8>((x as usize) + (*offset as usize))? as i32
447 ))
448 ),
449 Instruction::I32Load8S { offset } => require_matches!(
450 operands.pop(),
451 Some(Value::S32(x)),
452 results.push(Value::S32(
453 self.load::<i8>((x as usize) + (*offset as usize))? as i32
454 ))
455 ),
456 Instruction::I32Load16U { offset } => require_matches!(
457 operands.pop(),
458 Some(Value::S32(x)),
459 results.push(Value::S32(
460 self.load::<u16>((x as usize) + (*offset as usize))? as i32
461 ))
462 ),
463 Instruction::I32Load16S { offset } => require_matches!(
464 operands.pop(),
465 Some(Value::S32(x)),
466 results.push(Value::S32(
467 self.load::<i16>((x as usize) + (*offset as usize))? as i32
468 ))
469 ),
470 Instruction::I64Load { offset } => require_matches!(
471 operands.pop(),
472 Some(Value::S32(x)),
473 results.push(Value::S64(self.load((x as usize) + (*offset as usize))?))
474 ),
475 Instruction::F32Load { offset } => require_matches!(
476 operands.pop(),
477 Some(Value::S32(x)),
478 results.push(Value::F32(self.load((x as usize) + (*offset as usize))?))
479 ),
480 Instruction::F64Load { offset } => require_matches!(
481 operands.pop(),
482 Some(Value::S32(x)),
483 results.push(Value::F64(self.load((x as usize) + (*offset as usize))?))
484 ),
485 Instruction::I32Store { offset } => require_matches!(
486 operands.pop(),
487 Some(Value::S32(address)),
488 require_matches!(
489 operands.pop(),
490 Some(Value::S32(x)),
491 self.store((address as usize) + (*offset as usize), x)?
492 )
493 ),
494 Instruction::I32Store8 { offset } => require_matches!(
495 operands.pop(),
496 Some(Value::S32(address)),
497 require_matches!(
498 operands.pop(),
499 Some(Value::S32(x)),
500 self.store((address as usize) + (*offset as usize), x as u8)?
501 )
502 ),
503 Instruction::I32Store16 { offset } => require_matches!(
504 operands.pop(),
505 Some(Value::S32(address)),
506 require_matches!(
507 operands.pop(),
508 Some(Value::S32(x)),
509 self.store((address as usize) + (*offset as usize), x as u16)?
510 )
511 ),
512 Instruction::I64Store { offset } => require_matches!(
513 operands.pop(),
514 Some(Value::S32(address)),
515 require_matches!(
516 operands.pop(),
517 Some(Value::S64(x)),
518 self.store((address as usize) + (*offset as usize), x)?
519 )
520 ),
521 Instruction::F32Store { offset } => require_matches!(
522 operands.pop(),
523 Some(Value::S32(address)),
524 require_matches!(
525 operands.pop(),
526 Some(Value::F32(x)),
527 self.store((address as usize) + (*offset as usize), x)?
528 )
529 ),
530 Instruction::F64Store { offset } => require_matches!(
531 operands.pop(),
532 Some(Value::S32(address)),
533 require_matches!(
534 operands.pop(),
535 Some(Value::F64(x)),
536 self.store((address as usize) + (*offset as usize), x)?
537 )
538 ),
539 Instruction::I32FromChar => require_matches!(
540 operands.pop(),
541 Some(Value::Char(x)),
542 results.push(Value::S32(x as i32))
543 ),
544 Instruction::I64FromU64 => require_matches!(
545 operands.pop(),
546 Some(Value::U64(x)),
547 results.push(Value::S64(x as i64))
548 ),
549 Instruction::I64FromS64 => require_matches!(
550 operands.pop(),
551 Some(Value::S64(x)),
552 results.push(Value::S64(x))
553 ),
554 Instruction::I32FromU32 => require_matches!(
555 operands.pop(),
556 Some(Value::U32(x)),
557 results.push(Value::S32(x as i32))
558 ),
559 Instruction::I32FromS32 => require_matches!(
560 operands.pop(),
561 Some(Value::S32(x)),
562 results.push(Value::S32(x))
563 ),
564 Instruction::I32FromU16 => require_matches!(
565 operands.pop(),
566 Some(Value::U16(x)),
567 results.push(Value::S32(x as i32))
568 ),
569 Instruction::I32FromS16 => require_matches!(
570 operands.pop(),
571 Some(Value::S16(x)),
572 results.push(Value::S32(x as i32))
573 ),
574 Instruction::I32FromU8 => require_matches!(
575 operands.pop(),
576 Some(Value::U8(x)),
577 results.push(Value::S32(x as i32))
578 ),
579 Instruction::I32FromS8 => require_matches!(
580 operands.pop(),
581 Some(Value::S8(x)),
582 results.push(Value::S32(x as i32))
583 ),
584 Instruction::F32FromFloat32 => require_matches!(
585 operands.pop(),
586 Some(Value::F32(x)),
587 results.push(Value::F32(x))
588 ),
589 Instruction::F64FromFloat64 => require_matches!(
590 operands.pop(),
591 Some(Value::F64(x)),
592 results.push(Value::F64(x))
593 ),
594 Instruction::S8FromI32 => require_matches!(
595 operands.pop(),
596 Some(Value::S32(x)),
597 results.push(Value::S8(x as i8))
598 ),
599 Instruction::U8FromI32 => require_matches!(
600 operands.pop(),
601 Some(Value::S32(x)),
602 results.push(Value::U8(x as u8))
603 ),
604 Instruction::S16FromI32 => require_matches!(
605 operands.pop(),
606 Some(Value::S32(x)),
607 results.push(Value::S16(x as i16))
608 ),
609 Instruction::U16FromI32 => require_matches!(
610 operands.pop(),
611 Some(Value::S32(x)),
612 results.push(Value::U16(x as u16))
613 ),
614 Instruction::S32FromI32 => require_matches!(
615 operands.pop(),
616 Some(Value::S32(x)),
617 results.push(Value::S32(x))
618 ),
619 Instruction::U32FromI32 => require_matches!(
620 operands.pop(),
621 Some(Value::S32(x)),
622 results.push(Value::U32(x as u32))
623 ),
624 Instruction::S64FromI64 => require_matches!(
625 operands.pop(),
626 Some(Value::S64(x)),
627 results.push(Value::S64(x))
628 ),
629 Instruction::U64FromI64 => require_matches!(
630 operands.pop(),
631 Some(Value::S64(x)),
632 results.push(Value::U64(x as u64))
633 ),
634 Instruction::CharFromI32 => require_matches!(
635 operands.pop(),
636 Some(Value::S32(x)),
637 results.push(Value::Char(char::from_u32(x as u32).ok_or_else(|| {
638 Error::msg("Could not convert integer to char.")
639 })?))
640 ),
641 Instruction::Float32FromF32 => require_matches!(
642 operands.pop(),
643 Some(Value::F32(x)),
644 results.push(Value::F32(x))
645 ),
646 Instruction::Float64FromF64 => require_matches!(
647 operands.pop(),
648 Some(Value::F64(x)),
649 results.push(Value::F64(x))
650 ),
651 Instruction::BoolFromI32 => require_matches!(
652 operands.pop(),
653 Some(Value::S32(x)),
654 results.push(Value::Bool(x > 0))
655 ),
656 Instruction::I32FromBool => require_matches!(
657 operands.pop(),
658 Some(Value::Bool(x)),
659 results.push(Value::S32(x as i32))
660 ),
661 Instruction::StringLower { realloc: _ } => {
662 let encoded = require_matches!(
663 operands.pop(),
664 Some(Value::String(x)),
665 match self.encoding {
666 StringEncoding::Utf8 => Vec::from_iter(x.bytes()),
667 StringEncoding::Utf16 | StringEncoding::CompactUtf16 =>
668 x.encode_utf16().flat_map(|a| a.to_le_bytes()).collect(),
669 }
670 );
671
672 let realloc = self.realloc.as_ref().expect("No realloc.");
673 let args = [
674 wasm_runtime_layer::Value::I32(0),
675 wasm_runtime_layer::Value::I32(0),
676 wasm_runtime_layer::Value::I32(1),
677 wasm_runtime_layer::Value::I32(encoded.len() as i32),
678 ];
679 let mut res = [wasm_runtime_layer::Value::I32(0)];
680 realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
681 let ptr = require_matches!(&res[0], wasm_runtime_layer::Value::I32(x), *x);
682
683 let memory = self.memory.as_ref().expect("No memory.");
684 memory.write(&mut self.ctx.as_context_mut().inner, ptr as usize, &encoded)?;
685
686 results.push(Value::S32(ptr));
687 results.push(Value::S32(encoded.len() as i32));
688 }
689 Instruction::ListCanonLower {
690 element,
691 realloc: _,
692 } => {
693 let list = require_matches!(operands.pop(), Some(Value::List(x)), x);
694 let align = self.component.size_align.align(element);
695 let size = self.component.size_align.size(element);
696
697 let realloc = self.realloc.as_ref().expect("No realloc.");
698 let args = [
699 wasm_runtime_layer::Value::I32(0),
700 wasm_runtime_layer::Value::I32(0),
701 wasm_runtime_layer::Value::I32(align as i32),
702 wasm_runtime_layer::Value::I32((list.len() * size) as i32),
703 ];
704 let mut res = [wasm_runtime_layer::Value::I32(0)];
705 realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
706 let ptr = require_matches!(res[0], wasm_runtime_layer::Value::I32(x), x);
707
708 match element {
709 Type::U8 => self.store_array(ptr as usize, list.typed::<u8>()?)?,
710 Type::U16 => self.store_array(ptr as usize, list.typed::<u16>()?)?,
711 Type::U32 => self.store_array(ptr as usize, list.typed::<u32>()?)?,
712 Type::U64 => self.store_array(ptr as usize, list.typed::<u64>()?)?,
713 Type::S8 => self.store_array(ptr as usize, list.typed::<i8>()?)?,
714 Type::S16 => self.store_array(ptr as usize, list.typed::<i16>()?)?,
715 Type::S32 => self.store_array(ptr as usize, list.typed::<i32>()?)?,
716 Type::S64 => self.store_array(ptr as usize, list.typed::<i64>()?)?,
717 Type::Float32 => self.store_array(ptr as usize, list.typed::<f32>()?)?,
718 Type::Float64 => self.store_array(ptr as usize, list.typed::<f64>()?)?,
719 _ => unreachable!(),
720 }
721
722 results.push(Value::S32(ptr));
723 results.push(Value::S32(list.len() as i32));
724 }
725 Instruction::ListLower {
726 element,
727 realloc: _,
728 len,
729 } => {
730 let list = require_matches!(operands.pop(), Some(Value::List(x)), x);
731 let align = self.component.size_align.align(element);
732 let size = self.component.size_align.size(element);
733
734 let realloc = self.realloc.as_ref().expect("No realloc.");
735 let args = [
736 wasm_runtime_layer::Value::I32(0),
737 wasm_runtime_layer::Value::I32(0),
738 wasm_runtime_layer::Value::I32(align as i32),
739 wasm_runtime_layer::Value::I32((list.len() * size) as i32),
740 ];
741 let mut res = [wasm_runtime_layer::Value::I32(0)];
742 realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
743 let ptr = require_matches!(res[0], wasm_runtime_layer::Value::I32(x), x);
744
745 len.set(list.len() as i32);
746
747 results.push(Value::S32(ptr));
748 results.push(Value::S32(list.len() as i32));
749
750 for item in &list {
751 results.push(item.clone());
752 }
753
754 results.push(Value::S32(ptr));
755 }
756 Instruction::StringLift => {
757 let memory = self.memory.as_ref().expect("No memory.");
758 let len = require_matches!(operands.pop(), Some(Value::S32(len)), len) as usize;
759 let mut result = vec![0; len];
760 require_matches!(
761 operands.pop(),
762 Some(Value::S32(ptr)),
763 memory.read(&self.ctx.as_context().inner, ptr as usize, &mut result)?
764 );
765
766 match self.encoding {
767 StringEncoding::Utf8 => {
768 results.push(Value::String(String::from_utf8(result)?.into()))
769 }
770 StringEncoding::Utf16 | StringEncoding::CompactUtf16 => {
771 ensure!(result.len() & 0b1 == 0, "Invalid string length");
772 results.push(Value::String(
773 String::from_utf16(
774 &result
775 .chunks_exact(2)
776 .map(|e| {
777 u16::from_be_bytes(
778 e.try_into().expect("All chunks must have size 2."),
779 )
780 })
781 .collect::<Vec<_>>(),
782 )?
783 .into(),
784 ));
785 }
786 }
787 }
788 Instruction::ListCanonLift { element, ty: _ } => {
789 let len = require_matches!(operands.pop(), Some(Value::S32(x)), x);
790 let ptr = require_matches!(operands.pop(), Some(Value::S32(x)), x);
791
792 results.push(Value::List(match element {
793 Type::U8 => self.load_array::<u8>(ptr as usize, len as usize)?.into(),
794 Type::U16 => self.load_array::<u16>(ptr as usize, len as usize)?.into(),
795 Type::U32 => self.load_array::<u32>(ptr as usize, len as usize)?.into(),
796 Type::U64 => self.load_array::<u64>(ptr as usize, len as usize)?.into(),
797 Type::S8 => self.load_array::<i8>(ptr as usize, len as usize)?.into(),
798 Type::S16 => self.load_array::<i16>(ptr as usize, len as usize)?.into(),
799 Type::S32 => self.load_array::<i32>(ptr as usize, len as usize)?.into(),
800 Type::S64 => self.load_array::<i64>(ptr as usize, len as usize)?.into(),
801 Type::Float32 => self.load_array::<f32>(ptr as usize, len as usize)?.into(),
802 Type::Float64 => self.load_array::<f64>(ptr as usize, len as usize)?.into(),
803 _ => unreachable!(),
804 }));
805 }
806 Instruction::ListLift {
807 element: _,
808 ty,
809 len: _,
810 } => {
811 let ty = self.types[ty.index()].clone();
812 results.push(Value::List(List::new(
813 require_matches!(ty, crate::types::ValueType::List(x), x),
814 operands.drain(..),
815 )?));
816 }
817 Instruction::ReadI32 { value } => {
818 value.set(require_matches!(operands.pop(), Some(Value::S32(x)), x))
819 }
820 Instruction::RecordLower { record: _, ty } => {
821 let official_ty =
822 require_matches!(&self.types[ty.index()], ValueType::Record(x), x);
823 let record = require_matches!(operands.pop(), Some(Value::Record(x)), x);
824 ensure!(&record.ty() == official_ty, "Record types did not match.");
825
826 for _i in 0..record.fields().len() {
827 results.push(Value::Bool(false));
828 }
829
830 for (index, value) in official_ty
831 .fields
832 .iter()
833 .map(|x| x.0)
834 .zip(record.fields().map(|x| x.1))
835 {
836 results[index] = value;
837 }
838 }
839 Instruction::RecordLift { record: _, ty } => {
840 let official_ty =
841 require_matches!(&self.types[ty.index()], ValueType::Record(x), x);
842 ensure!(
843 operands.len() == official_ty.fields().len(),
844 "Record types did not match."
845 );
846
847 results.push(Value::Record(crate::values::Record::from_sorted(
848 official_ty.clone(),
849 official_ty.fields.iter().map(|(i, name, _)| {
850 (name.clone(), replace(&mut operands[*i], Value::Bool(false)))
851 }),
852 )));
853 operands.clear();
854 }
855 Instruction::HandleLower { handle, ty } => match &self.types[ty.index()] {
856 ValueType::Own(_ty) => {
857 let def = match handle {
858 Handle::Own(x) => x,
859 Handle::Borrow(x) => x,
860 };
861 let val = require_matches!(operands.pop(), Some(Value::Own(x)), x);
862 let rep = val.lower(&mut self.ctx)?;
863
864 let mut tables = self
865 .resource_tables
866 .try_lock()
867 .expect("Could not acquire table access.");
868 results.push(Value::S32(
869 tables[self.component.resource_map[def.index()].as_u32() as usize].add(
870 HandleElement {
871 rep,
872 own: true,
873 lend_count: 0,
874 },
875 ),
876 ));
877 }
878 ValueType::Borrow(_ty) => {
879 let def = match handle {
880 Handle::Own(x) => x,
881 Handle::Borrow(x) => x,
882 };
883 let val = require_matches!(operands.pop(), Some(Value::Borrow(x)), x);
884 let rep = val.lower(&mut self.ctx)?;
885
886 if val.ty().is_owned_by_instance(self.instance_id) {
887 results.push(Value::S32(rep));
888 } else {
889 let mut tables = self
890 .resource_tables
891 .try_lock()
892 .expect("Could not acquire table access.");
893 let res = self.component.resource_map[def.index()].as_u32();
894 let idx = tables[res as usize].add(HandleElement {
895 rep,
896 own: false,
897 lend_count: 0,
898 });
899 results.push(Value::S32(idx));
900 self.handles_to_drop.push((res, idx));
901 }
902 }
903 _ => unreachable!(),
904 },
905 Instruction::HandleLift { handle, ty } => match &self.types[ty.index()] {
906 ValueType::Own(ty) => {
907 let def = match handle {
908 Handle::Own(x) => x,
909 Handle::Borrow(x) => x,
910 };
911 let val = require_matches!(operands.pop(), Some(Value::S32(x)), x);
912
913 let mut tables = self
914 .resource_tables
915 .try_lock()
916 .expect("Could not acquire table access.");
917 let table =
918 &mut tables[self.component.resource_map[def.index()].as_u32() as usize];
919 let elem = table.remove(val)?;
920 ensure!(
921 elem.lend_count == 0,
922 "Attempted to transfer ownership while handle was lent."
923 );
924 ensure!(
925 elem.own,
926 "Attempted to transfer ownership of non-owned handle."
927 );
928
929 results.push(Value::Own(ResourceOwn::new_guest(
930 elem.rep,
931 ty.clone(),
932 self.store_id,
933 table.destructor().cloned(),
934 )));
935 }
936 ValueType::Borrow(ty) => {
937 let def = match handle {
938 Handle::Own(x) => x,
939 Handle::Borrow(x) => x,
940 };
941 let val = require_matches!(operands.pop(), Some(Value::S32(x)), x);
942
943 let mut tables = self
944 .resource_tables
945 .try_lock()
946 .expect("Could not acquire table access.");
947 let res = self.component.resource_map[def.index()].as_u32();
948 let table = &mut tables[res as usize];
949 let mut elem = *table.get(val)?;
950
951 if elem.own {
952 elem.lend_count += 1;
953 table.set(val, elem);
954 }
955
956 let borrow = ResourceBorrow::new(elem.rep, self.store_id, ty.clone());
957 self.required_dropped
958 .push((elem.own, res, val, borrow.dead_ref()));
959 results.push(Value::Borrow(borrow));
960 }
961 _ => unreachable!(),
962 },
963 Instruction::TupleLower { tuple: _, ty: _ } => {
964 let tuple = require_matches!(operands.pop(), Some(Value::Tuple(x)), x);
965 results.extend(tuple.iter().cloned());
966 }
967 Instruction::TupleLift { tuple: _, ty } => {
968 results.push(Value::Tuple(crate::values::Tuple::new_unchecked(
969 require_matches!(&self.types[ty.index()], ValueType::Tuple(x), x.clone()),
970 operands.drain(..),
971 )));
972 }
973 Instruction::FlagsLower { flags: _, ty: _ } => {
974 let flags = require_matches!(operands.pop(), Some(Value::Flags(x)), x);
975 if flags.ty().names().len() > 0 {
976 results.extend(flags.as_u32_list().iter().map(|x| Value::S32(*x as i32)));
977 }
978 }
979 Instruction::FlagsLift { flags: _, ty } => {
980 let flags = require_matches!(&self.types[ty.index()], ValueType::Flags(x), x);
981
982 let list = match operands.len() {
983 0 => FlagsList::Single(0),
984 1 => FlagsList::Single(require_matches!(
985 operands.pop(),
986 Some(Value::S32(x)),
987 x as u32
988 )),
989 _ => FlagsList::Multiple(Arc::new(
990 operands
991 .drain(..)
992 .map(|x| Ok(require_matches!(x, Value::S32(y), y) as u32))
993 .collect::<Result<_>>()?,
994 )),
995 };
996
997 results.push(Value::Flags(crate::values::Flags::new_unchecked(
998 flags.clone(),
999 list,
1000 )));
1001 }
1002 Instruction::ExtractVariantDiscriminant { discriminant_value } => {
1003 let (discriminant, val) = match operands
1004 .pop()
1005 .expect("No operand on stack for which to extract discriminant.")
1006 {
1007 Value::Variant(x) => (x.discriminant(), x.value()),
1008 Value::Enum(x) => (x.discriminant(), None),
1009 Value::Option(x) => {
1010 (x.is_some().then_some(1).unwrap_or_default(), (*x).clone())
1011 }
1012 Value::Result(x) => (
1013 x.is_err().then_some(1).unwrap_or_default(),
1014 match &*x {
1015 std::result::Result::Ok(y) => y,
1016 std::result::Result::Err(y) => y,
1017 }
1018 .clone(),
1019 ),
1020 _ => bail!("Invalid type for which to extract variant."),
1021 };
1022
1023 if let Some(value) = val {
1024 results.push(value);
1025 discriminant_value.set((discriminant as i32, true));
1026 } else {
1027 discriminant_value.set((discriminant as i32, false));
1028 }
1029 }
1030 Instruction::ExtractReadVariantDiscriminant { value, .. } => {
1031 value.set(require_matches!(operands.pop(), Some(Value::S32(x)), x))
1032 }
1033 Instruction::VariantLift {
1034 ty, discriminant, ..
1035 } => {
1036 let variant_ty =
1037 require_matches!(&self.types[ty.index()], ValueType::Variant(x), x);
1038 results.push(Value::Variant(crate::values::Variant::new(
1039 variant_ty.clone(),
1040 *discriminant as usize,
1041 operands.pop(),
1042 )?));
1043 }
1044 Instruction::EnumLower { enum_: _, ty: _ } => {
1045 let en = require_matches!(operands.pop(), Some(Value::Enum(x)), x);
1046 results.push(Value::S32(en.discriminant() as i32));
1047 }
1048 Instruction::EnumLift {
1049 enum_: _,
1050 ty,
1051 discriminant,
1052 } => {
1053 let enum_ty = require_matches!(&self.types[ty.index()], ValueType::Enum(x), x);
1054 results.push(Value::Enum(crate::values::Enum::new(
1055 enum_ty.clone(),
1056 *discriminant as usize,
1057 )?));
1058 }
1059 Instruction::OptionLift {
1060 ty, discriminant, ..
1061 } => {
1062 let option_ty = require_matches!(&self.types[ty.index()], ValueType::Option(x), x);
1063 results.push(Value::Option(OptionValue::new(
1064 option_ty.clone(),
1065 if *discriminant == 0 {
1066 None
1067 } else {
1068 Some(require_matches!(operands.pop(), Some(x), x))
1069 },
1070 )?));
1071 }
1072 Instruction::ResultLift {
1073 discriminant, ty, ..
1074 } => {
1075 let result_ty = require_matches!(&self.types[ty.index()], ValueType::Result(x), x);
1076 results.push(Value::Result(ResultValue::new(
1077 result_ty.clone(),
1078 if *discriminant == 0 {
1079 std::result::Result::Ok(operands.pop())
1080 } else {
1081 std::result::Result::Err(operands.pop())
1082 },
1083 )?));
1084 }
1085 Instruction::CallWasm { name: _, sig } => {
1086 let args = operands
1087 .iter()
1088 .map(TryFrom::try_from)
1089 .collect::<Result<Vec<_>>>()?;
1090 self.flat_results = vec![wasm_runtime_layer::Value::I32(0); sig.results.len()];
1091 self.callee_wasm.expect("No available WASM callee.").call(
1092 &mut self.ctx.as_context_mut().inner,
1093 &args,
1094 &mut self.flat_results,
1095 )?;
1096 results.extend(
1097 self.flat_results
1098 .iter()
1099 .map(TryFrom::try_from)
1100 .collect::<Result<Vec<_>>>()?,
1101 );
1102 }
1103 Instruction::CallInterface { func } => {
1104 for _i in 0..func.results.len() {
1105 results.push(Value::Bool(false));
1106 }
1107
1108 self.callee_interface
1109 .expect("No available interface callee.")
1110 .call(self.ctx.as_context_mut(), operands, &mut results[..])?;
1111 }
1112 Instruction::Return { amt: _, func: _ } => {
1113 if let Some(post) = &self.post_return {
1114 post.call(
1115 &mut self.ctx.as_context_mut().inner,
1116 &self.flat_results,
1117 &mut [],
1118 )?;
1119 }
1120
1121 let mut tables = self
1122 .resource_tables
1123 .try_lock()
1124 .expect("Could not lock resource table.");
1125 for (res, idx) in &self.handles_to_drop {
1126 tables[*res as usize]
1127 .remove(*idx)
1128 .expect("Could not find handle to drop.");
1129 }
1130
1131 for (own, res, idx, ptr) in &self.required_dropped {
1132 ensure!(
1133 Arc::strong_count(ptr) == 1,
1134 "Borrow was not dropped at the end of method."
1135 );
1136
1137 if *own {
1138 let table = &mut tables[*res as usize];
1139 let mut elem = *table.get(*idx)?;
1140
1141 elem.lend_count -= 1;
1142 table.set(*idx, elem);
1143 }
1144 }
1145
1146 for (i, val) in operands.drain(..).enumerate() {
1147 *self
1148 .results
1149 .get_mut(i)
1150 .ok_or_else(|| Error::msg("Unexpected number of output arguments."))? = val;
1151 }
1152 }
1153 Instruction::Malloc {
1154 realloc: _,
1155 size,
1156 align,
1157 } => {
1158 let realloc = self.realloc.as_ref().expect("No realloc.");
1159 let args = [
1160 wasm_runtime_layer::Value::I32(0),
1161 wasm_runtime_layer::Value::I32(0),
1162 wasm_runtime_layer::Value::I32(*align as i32),
1163 wasm_runtime_layer::Value::I32(*size as i32),
1164 ];
1165 let mut res = [wasm_runtime_layer::Value::I32(0)];
1166 realloc.call(&mut self.ctx.as_context_mut().inner, &args, &mut res)?;
1167 require_matches!(
1168 &res[0],
1169 wasm_runtime_layer::Value::I32(x),
1170 results.push(Value::S32(*x))
1171 );
1172 }
1173 }
1174
1175 Ok(())
1176 }
1177
1178 fn sizes(&self) -> &SizeAlign {
1179 &self.component.size_align
1180 }
1181
1182 fn is_list_canonical(&self, element: &Type) -> bool {
1183 const LITTLE_ENDIAN: bool = cfg!(target_endian = "little");
1185
1186 match element {
1187 Type::Bool => false,
1188 Type::U8 => true,
1189 Type::U16 => LITTLE_ENDIAN,
1190 Type::U32 => LITTLE_ENDIAN,
1191 Type::U64 => LITTLE_ENDIAN,
1192 Type::S8 => true,
1193 Type::S16 => LITTLE_ENDIAN,
1194 Type::S32 => LITTLE_ENDIAN,
1195 Type::S64 => LITTLE_ENDIAN,
1196 Type::Float32 => LITTLE_ENDIAN,
1197 Type::Float64 => LITTLE_ENDIAN,
1198 Type::Char => false,
1199 Type::String => false,
1200 Type::Id(_) => false,
1201 }
1202 }
1203}
1204
1205#[derive(Clone, Debug)]
1207pub struct TypedFunc<P: ComponentList, R: ComponentList> {
1208 inner: Func,
1210 data: PhantomData<fn(P) -> R>,
1212}
1213
1214impl<P: ComponentList, R: ComponentList> TypedFunc<P, R> {
1215 pub fn new<C: AsContextMut>(
1217 ctx: C,
1218 f: impl 'static + Send + Sync + Fn(StoreContextMut<C::UserState, C::Engine>, P) -> Result<R>,
1219 ) -> Self {
1220 let mut params_results = vec![ValueType::Bool; P::LEN + R::LEN];
1221 P::into_tys(&mut params_results[..P::LEN]);
1222 R::into_tys(&mut params_results[P::LEN..]);
1223
1224 Self {
1225 inner: Func::new(
1226 ctx,
1227 FuncType::new(
1228 params_results[..P::LEN].iter().cloned(),
1229 params_results[P::LEN..].iter().cloned(),
1230 ),
1231 move |ctx, args, res| {
1232 let p = P::from_values(args)?;
1233 let r = f(ctx, p)?;
1234 r.into_values(res)
1235 },
1236 ),
1237 data: PhantomData,
1238 }
1239 }
1240
1241 pub fn call(&self, ctx: impl AsContextMut, params: P) -> Result<R> {
1246 let mut params_results = vec![Value::Bool(false); P::LEN + R::LEN];
1247 params.into_values(&mut params_results[0..P::LEN])?;
1248 let (params, results) = params_results.split_at_mut(P::LEN);
1249 self.inner.call(ctx, params, results)?;
1250 R::from_values(results)
1251 }
1252
1253 pub fn func(&self) -> Func {
1255 self.inner.clone()
1256 }
1257
1258 pub fn ty(&self) -> FuncType {
1260 self.inner.ty.clone()
1261 }
1262}
1263
1264pub struct FuncError {
1266 name: String,
1268 interface: Option<InterfaceIdentifier>,
1270 instance: crate::Instance,
1272 error: Error,
1274}
1275
1276impl FuncError {
1277 pub fn name(&self) -> &str {
1279 &self.name
1280 }
1281
1282 pub fn instance(&self) -> &crate::Instance {
1284 &self.instance
1285 }
1286}
1287
1288impl std::fmt::Debug for FuncError {
1289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1290 if let Some(inter) = &self.interface {
1291 f.write_fmt(format_args!("in {}.{}: {:?}", inter, self.name, self.error))
1292 } else {
1293 f.write_fmt(format_args!("in {}: {:?}", self.name, self.error))
1294 }
1295 }
1296}
1297
1298impl std::fmt::Display for FuncError {
1299 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1300 if let Some(inter) = &self.interface {
1301 f.write_fmt(format_args!("in {}.{}: {}", inter, self.name, self.error))
1302 } else {
1303 f.write_fmt(format_args!("in {}: {}", self.name, self.error))
1304 }
1305 }
1306}
1307
1308impl std::error::Error for FuncError {
1309 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1310 Some(self.error.as_ref())
1311 }
1312}
1313
1314trait Blittable: Sized {
1316 type Array: ByteArray;
1318
1319 fn from_bytes(array: Self::Array) -> Self;
1321 fn to_bytes(self) -> Self::Array;
1323
1324 fn zeroed_array(len: usize) -> Arc<[Self]>;
1326
1327 fn to_le_slice(data: &[Self]) -> &[u8];
1329 fn to_le_slice_mut(data: &mut [Self]) -> &mut [u8];
1331}
1332
1333macro_rules! impl_blittable {
1335 ($($type_impl: ident)*) => {
1336 $(
1337 impl Blittable for $type_impl {
1338 type Array = [u8; std::mem::size_of::<$type_impl>()];
1339
1340 fn from_bytes(array: Self::Array) -> Self {
1341 Self::from_le_bytes(array)
1342 }
1343
1344 fn to_bytes(self) -> Self::Array {
1345 Self::to_le_bytes(self)
1346 }
1347
1348 fn zeroed_array(len: usize) -> Arc<[Self]> {
1349 Arc::from(zeroed_slice_box::<Self>(len))
1350 }
1351
1352 fn to_le_slice(data: &[Self]) -> &[u8] {
1353 assert!(cfg!(target_endian = "little"), "Attempted to bitcast to little-endian bytes on a big endian platform.");
1354 cast_slice(data)
1355 }
1356
1357 fn to_le_slice_mut(data: &mut [Self]) -> &mut [u8] {
1358 assert!(cfg!(target_endian = "little"), "Attempted to bitcast to little-endian bytes on a big endian platform.");
1359 cast_slice_mut(data)
1360 }
1361 }
1362 )*
1363 };
1364}
1365
1366impl_blittable!(u8 u16 u32 u64 i8 i16 i32 i64 f32 f64);
1367
1368trait ByteArray: Sized {
1370 fn load(ctx: impl AsContext, memory: &Memory, offset: usize) -> Result<Self>;
1372
1373 fn store(self, ctx: impl AsContextMut, memory: &Memory, offset: usize) -> Result<()>;
1375}
1376
1377impl<const N: usize> ByteArray for [u8; N] {
1378 fn load(ctx: impl AsContext, memory: &Memory, offset: usize) -> Result<Self> {
1379 let mut res = [0; N];
1380 memory.read(ctx.as_context().inner, offset, &mut res)?;
1381 Ok(res)
1382 }
1383
1384 fn store(self, mut ctx: impl AsContextMut, memory: &Memory, offset: usize) -> Result<()> {
1385 memory.write(ctx.as_context_mut().inner, offset, &self)?;
1386 Ok(())
1387 }
1388}
1389
1390type FunctionBacking<T, E> =
1392 dyn 'static + Send + Sync + Fn(StoreContextMut<T, E>, &[Value], &mut [Value]) -> Result<()>;
1393
1394type FunctionBackingKeyPair<T, E> = (Arc<AtomicUsize>, Arc<FunctionBacking<T, E>>);
1396
1397pub(crate) struct FuncVec<T, E: backend::WasmEngine> {
1399 functions: Vec<FunctionBackingKeyPair<T, E>>,
1401}
1402
1403impl<T, E: backend::WasmEngine> FuncVec<T, E> {
1404 pub fn push(
1406 &mut self,
1407 f: impl 'static + Send + Sync + Fn(StoreContextMut<T, E>, &[Value], &mut [Value]) -> Result<()>,
1408 ) -> Arc<AtomicUsize> {
1409 if self.functions.capacity() == self.functions.len() {
1410 self.clear_dead_functions();
1411 }
1412 let idx = Arc::new(AtomicUsize::new(self.functions.len()));
1413 self.functions.push((idx.clone(), Arc::new(f)));
1414 idx
1415 }
1416
1417 pub fn get(&self, value: &AtomicUsize) -> Arc<FunctionBacking<T, E>> {
1419 self.functions[value.load(Ordering::Acquire)].1.clone()
1420 }
1421
1422 fn clear_dead_functions(&mut self) {
1424 let new_len = 2 * self.functions.len();
1425 let old = replace(&mut self.functions, Vec::with_capacity(new_len));
1426 for (idx, val) in old {
1427 if Arc::strong_count(&idx) > 1 {
1428 idx.store(self.functions.len(), Ordering::Release);
1429 self.functions.push((idx, val));
1430 }
1431 }
1432 }
1433}
1434
1435impl<T, E: backend::WasmEngine> Default for FuncVec<T, E> {
1436 fn default() -> Self {
1437 Self {
1438 functions: Vec::new(),
1439 }
1440 }
1441}