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