Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
244 lines
6.6 KiB
Rust
244 lines
6.6 KiB
Rust
use std::os::raw::c_void;
|
|
use wasmtime::{ExternRef, Func, Val};
|
|
|
|
/// `*mut wasm_ref_t` is a reference type (`externref` or `funcref`), as seen by
|
|
/// the C API. Because we do not have a uniform representation for `funcref`s
|
|
/// and `externref`s, a `*mut wasm_ref_t` is morally a
|
|
/// `Option<Box<Either<ExternRef, Func>>>`.
|
|
///
|
|
/// A null `*mut wasm_ref_t` is either a null `funcref` or a null `externref`
|
|
/// depending on context (e.g. the table's element type that it is going into or
|
|
/// coming out of).
|
|
///
|
|
/// Note: this is not `#[repr(C)]` because it is an opaque type in the header,
|
|
/// and only ever referenced as `*mut wasm_ref_t`. This also lets us use a
|
|
/// regular, non-`repr(C)` `enum` to define `WasmRefInner`.
|
|
#[derive(Clone)]
|
|
pub struct wasm_ref_t {
|
|
pub(crate) r: WasmRefInner,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) enum WasmRefInner {
|
|
ExternRef(ExternRef),
|
|
FuncRef(Func),
|
|
}
|
|
|
|
wasmtime_c_api_macros::declare_own!(wasm_ref_t);
|
|
|
|
pub(crate) fn ref_to_val(r: &wasm_ref_t) -> Val {
|
|
match &r.r {
|
|
WasmRefInner::ExternRef(x) => Val::ExternRef(Some(x.clone())),
|
|
WasmRefInner::FuncRef(f) => Val::FuncRef(Some(f.clone())),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn val_into_ref(val: Val) -> Option<Box<wasm_ref_t>> {
|
|
match val {
|
|
Val::ExternRef(Some(x)) => Some(Box::new(wasm_ref_t {
|
|
r: WasmRefInner::ExternRef(x),
|
|
})),
|
|
Val::FuncRef(Some(f)) => Some(Box::new(wasm_ref_t {
|
|
r: WasmRefInner::FuncRef(f),
|
|
})),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_copy(r: Option<&wasm_ref_t>) -> Option<Box<wasm_ref_t>> {
|
|
r.map(|r| Box::new(r.clone()))
|
|
}
|
|
|
|
fn abort(name: &str) -> ! {
|
|
eprintln!("`{}` is not implemented", name);
|
|
std::process::abort();
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_same(a: Option<&wasm_ref_t>, b: Option<&wasm_ref_t>) -> bool {
|
|
match (a.map(|a| &a.r), b.map(|b| &b.r)) {
|
|
(Some(WasmRefInner::ExternRef(a)), Some(WasmRefInner::ExternRef(b))) => a.ptr_eq(b),
|
|
(None, None) => true,
|
|
// Note: we don't support equality for `Func`, so we always return
|
|
// `false` for `funcref`s.
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_get_host_info(_ref: Option<&wasm_ref_t>) -> *mut c_void {
|
|
std::ptr::null_mut()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_set_host_info(_ref: Option<&wasm_ref_t>, _info: *mut c_void) {
|
|
abort("wasm_ref_set_host_info")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
|
|
_ref: Option<&wasm_ref_t>,
|
|
_info: *mut c_void,
|
|
_finalizer: Option<extern "C" fn(*mut c_void)>,
|
|
) {
|
|
abort("wasm_ref_set_host_info_with_finalizer")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_extern(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_extern_t> {
|
|
abort("wasm_ref_as_extern")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_extern_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_extern_t> {
|
|
abort("wasm_ref_as_extern_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_foreign(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_foreign_t> {
|
|
abort("wasm_ref_as_foreign")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_foreign_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_foreign_t> {
|
|
abort("wasm_ref_as_foreign_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_func(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
|
|
abort("wasm_ref_as_func")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_func_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> {
|
|
abort("wasm_ref_as_func_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_global(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_global_t> {
|
|
abort("wasm_ref_as_global")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_global_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_global_t> {
|
|
abort("wasm_ref_as_global_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_instance(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_instance_t> {
|
|
abort("wasm_ref_as_instance")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_instance_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_instance_t> {
|
|
abort("wasm_ref_as_instance_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_memory(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_memory_t> {
|
|
abort("wasm_ref_as_memory")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_memory_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_memory_t> {
|
|
abort("wasm_ref_as_memory_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_module(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_module_t> {
|
|
abort("wasm_ref_as_module")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_module_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_module_t> {
|
|
abort("wasm_ref_as_module_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_table(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_table_t> {
|
|
abort("wasm_ref_as_table")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_table_const(
|
|
_ref: Option<&wasm_ref_t>,
|
|
) -> Option<&crate::wasm_table_t> {
|
|
abort("wasm_ref_as_table_const")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_trap(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
|
|
abort("wasm_ref_as_trap")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_ref_as_trap_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> {
|
|
abort("wasm_ref_as_trap_const")
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[repr(C)]
|
|
pub struct wasm_foreign_t {}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_new(_store: &crate::wasm_store_t) -> Box<wasm_foreign_t> {
|
|
abort("wasm_foreign_new")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_delete(_foreign: Box<wasm_foreign_t>) {}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_copy(r: &wasm_foreign_t) -> Box<wasm_foreign_t> {
|
|
Box::new(r.clone())
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_same(_a: &wasm_foreign_t, _b: &wasm_foreign_t) -> bool {
|
|
abort("wasm_foreign_same")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_get_host_info(_foreign: &wasm_foreign_t) -> *mut c_void {
|
|
std::ptr::null_mut()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_set_host_info(_foreign: &wasm_foreign_t, _info: *mut c_void) {
|
|
abort("wasm_foreign_set_host_info")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_set_host_info_with_finalizer(
|
|
_foreign: &wasm_foreign_t,
|
|
_info: *mut c_void,
|
|
_finalizer: Option<extern "C" fn(*mut c_void)>,
|
|
) {
|
|
abort("wasm_foreign_set_host_info_with_finalizer")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_as_ref(_: &wasm_foreign_t) -> &wasm_ref_t {
|
|
abort("wasm_foreign_as_ref")
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn wasm_foreign_as_ref_const(_: &wasm_foreign_t) -> Option<&wasm_ref_t> {
|
|
abort("wasm_foreign_as_ref_const")
|
|
}
|