1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::sys::externals::Function;
use crate::sys::store::{Store, StoreObject};
use crate::sys::RuntimeError;
use wasmer_types::Value;
pub use wasmer_types::{
ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability,
TableType, Type as ValType,
};
use wasmer_vm::VMFuncRef;
pub type Val = Value<Function>;
impl StoreObject for Val {
fn comes_from_same_store(&self, store: &Store) -> bool {
match self {
Self::FuncRef(None) => true,
Self::FuncRef(Some(f)) => Store::same(store, f.store()),
Self::ExternRef(_) => true,
Self::I32(_) | Self::I64(_) | Self::F32(_) | Self::F64(_) | Self::V128(_) => true,
}
}
}
impl From<Function> for Val {
fn from(val: Function) -> Self {
Self::FuncRef(Some(val))
}
}
pub trait ValFuncRef {
fn into_vm_funcref(&self, store: &Store) -> Result<VMFuncRef, RuntimeError>;
fn from_vm_funcref(item: VMFuncRef, store: &Store) -> Self;
fn into_table_reference(&self, store: &Store) -> Result<wasmer_vm::TableElement, RuntimeError>;
fn from_table_reference(item: wasmer_vm::TableElement, store: &Store) -> Self;
}
impl ValFuncRef for Val {
fn into_vm_funcref(&self, store: &Store) -> Result<VMFuncRef, RuntimeError> {
if !self.comes_from_same_store(store) {
return Err(RuntimeError::new("cross-`Store` values are not supported"));
}
Ok(match self {
Self::FuncRef(None) => VMFuncRef::null(),
Self::FuncRef(Some(f)) => f.vm_funcref(),
_ => return Err(RuntimeError::new("val is not func ref")),
})
}
fn from_vm_funcref(func_ref: VMFuncRef, store: &Store) -> Self {
if func_ref.is_null() {
return Self::FuncRef(None);
}
let item: &wasmer_vm::VMCallerCheckedAnyfunc = unsafe {
let anyfunc: *const wasmer_vm::VMCallerCheckedAnyfunc = *func_ref;
&*anyfunc
};
let signature = store
.engine()
.lookup_signature(item.type_index)
.expect("Signature not found in store");
let export = wasmer_engine::ExportFunction {
metadata: None,
vm_function: wasmer_vm::VMFunction {
address: item.func_ptr,
signature,
kind: wasmer_vm::VMFunctionKind::Static,
vmctx: item.vmctx,
call_trampoline: None,
instance_ref: None,
},
};
let f = Function::from_vm_export(store, export);
Self::FuncRef(Some(f))
}
fn into_table_reference(&self, store: &Store) -> Result<wasmer_vm::TableElement, RuntimeError> {
if !self.comes_from_same_store(store) {
return Err(RuntimeError::new("cross-`Store` values are not supported"));
}
Ok(match self {
Self::ExternRef(extern_ref) => {
wasmer_vm::TableElement::ExternRef(extern_ref.clone().into())
}
Self::FuncRef(None) => wasmer_vm::TableElement::FuncRef(VMFuncRef::null()),
Self::FuncRef(Some(f)) => wasmer_vm::TableElement::FuncRef(f.vm_funcref()),
_ => return Err(RuntimeError::new("val is not reference")),
})
}
fn from_table_reference(item: wasmer_vm::TableElement, store: &Store) -> Self {
match item {
wasmer_vm::TableElement::FuncRef(f) => Self::from_vm_funcref(f, store),
wasmer_vm::TableElement::ExternRef(extern_ref) => Self::ExternRef(extern_ref.into()),
}
}
}