Files
wasmtime/crates/c-api/src/linker.rs
Alex Crichton 76b82910c9 Remove the module linking implementation in Wasmtime (#3958)
* Remove the module linking implementation in Wasmtime

This commit removes the experimental implementation of the module
linking WebAssembly proposal from Wasmtime. The module linking is no
longer intended for core WebAssembly but is instead incorporated into
the component model now at this point. This means that very large parts
of Wasmtime's implementation of module linking are no longer applicable
and would change greatly with an implementation of the component model.

The main purpose of this is to remove Wasmtime's reliance on the support
for module-linking in `wasmparser` and tooling crates. With this
reliance removed we can move over to the `component-model` branch of
`wasmparser` and use the updated support for the component model.
Additionally given the trajectory of the component model proposal the
embedding API of Wasmtime will not look like what it looks like today
for WebAssembly. For example the core wasm `Instance` will not change
and instead a `Component` is likely to be added instead.

Some more rationale for this is in #3941, but the basic idea is that I
feel that it's not going to be viable to develop support for the
component model on a non-`main` branch of Wasmtime. Additionaly I don't
think it's viable, for the same reasons as `wasm-tools`, to support the
old module linking proposal and the new component model at the same
time.

This commit takes a moment to not only delete the existing module
linking implementation but some abstractions are also simplified. For
example module serialization is a bit simpler that there's only one
module. Additionally instantiation is much simpler since the only
initializer we have to deal with are imports and nothing else.

Closes #3941

* Fix doc link

* Update comments
2022-03-23 14:57:34 -05:00

188 lines
5.4 KiB
Rust

use crate::{
bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t,
wasmtime_extern_t, wasmtime_module_t, CStoreContextMut,
};
use std::ffi::c_void;
use std::mem::MaybeUninit;
use std::str;
use wasmtime::{Func, Instance, Linker};
#[repr(C)]
pub struct wasmtime_linker_t {
linker: Linker<crate::StoreData>,
}
#[no_mangle]
pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box<wasmtime_linker_t> {
Box::new(wasmtime_linker_t {
linker: Linker::new(&engine.engine),
})
}
#[no_mangle]
pub extern "C" fn wasmtime_linker_allow_shadowing(
linker: &mut wasmtime_linker_t,
allow_shadowing: bool,
) {
linker.linker.allow_shadowing(allow_shadowing);
}
#[no_mangle]
pub extern "C" fn wasmtime_linker_delete(_linker: Box<wasmtime_linker_t>) {}
macro_rules! to_str {
($ptr:expr, $len:expr) => {
match str::from_utf8(crate::slice_from_raw_parts($ptr, $len)) {
Ok(s) => s,
Err(_) => return bad_utf8(),
}
};
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_define(
linker: &mut wasmtime_linker_t,
module: *const u8,
module_len: usize,
name: *const u8,
name_len: usize,
item: &wasmtime_extern_t,
) -> Option<Box<wasmtime_error_t>> {
let linker = &mut linker.linker;
let module = to_str!(module, module_len);
let name = to_str!(name, name_len);
let item = item.to_extern();
handle_result(linker.define(module, name, item), |_linker| ())
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_define_func(
linker: &mut wasmtime_linker_t,
module: *const u8,
module_len: usize,
name: *const u8,
name_len: usize,
ty: &wasm_functype_t,
callback: crate::wasmtime_func_callback_t,
data: *mut c_void,
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
) -> Option<Box<wasmtime_error_t>> {
let ty = ty.ty().ty.clone();
let module = to_str!(module, module_len);
let name = to_str!(name, name_len);
let cb = crate::func::c_callback_to_rust_fn(callback, data, finalizer);
handle_result(linker.linker.func_new(module, name, ty, cb), |_linker| ())
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_define_func_unchecked(
linker: &mut wasmtime_linker_t,
module: *const u8,
module_len: usize,
name: *const u8,
name_len: usize,
ty: &wasm_functype_t,
callback: crate::wasmtime_func_unchecked_callback_t,
data: *mut c_void,
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
) -> Option<Box<wasmtime_error_t>> {
let ty = ty.ty().ty.clone();
let module = to_str!(module, module_len);
let name = to_str!(name, name_len);
let cb = crate::func::c_unchecked_callback_to_rust_fn(callback, data, finalizer);
handle_result(
linker.linker.func_new_unchecked(module, name, ty, cb),
|_linker| (),
)
}
#[cfg(feature = "wasi")]
#[no_mangle]
pub extern "C" fn wasmtime_linker_define_wasi(
linker: &mut wasmtime_linker_t,
) -> Option<Box<wasmtime_error_t>> {
handle_result(
wasmtime_wasi::add_to_linker(&mut linker.linker, |cx| cx.wasi.as_mut().unwrap()),
|_linker| (),
)
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_define_instance(
linker: &mut wasmtime_linker_t,
store: CStoreContextMut<'_>,
name: *const u8,
name_len: usize,
instance: &Instance,
) -> Option<Box<wasmtime_error_t>> {
let linker = &mut linker.linker;
let name = to_str!(name, name_len);
handle_result(linker.instance(store, name, *instance), |_linker| ())
}
#[no_mangle]
pub extern "C" fn wasmtime_linker_instantiate(
linker: &wasmtime_linker_t,
store: CStoreContextMut<'_>,
module: &wasmtime_module_t,
instance_ptr: &mut Instance,
trap_ptr: &mut *mut wasm_trap_t,
) -> Option<Box<wasmtime_error_t>> {
let result = linker.linker.instantiate(store, &module.module);
super::instance::handle_instantiate(result, instance_ptr, trap_ptr)
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_module(
linker: &mut wasmtime_linker_t,
store: CStoreContextMut<'_>,
name: *const u8,
name_len: usize,
module: &wasmtime_module_t,
) -> Option<Box<wasmtime_error_t>> {
let linker = &mut linker.linker;
let name = to_str!(name, name_len);
handle_result(linker.module(store, name, &module.module), |_linker| ())
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_get_default(
linker: &wasmtime_linker_t,
store: CStoreContextMut<'_>,
name: *const u8,
name_len: usize,
func: &mut Func,
) -> Option<Box<wasmtime_error_t>> {
let linker = &linker.linker;
let name = to_str!(name, name_len);
handle_result(linker.get_default(store, name), |f| *func = f)
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_get(
linker: &wasmtime_linker_t,
store: CStoreContextMut<'_>,
module: *const u8,
module_len: usize,
name: *const u8,
name_len: usize,
item_ptr: &mut MaybeUninit<wasmtime_extern_t>,
) -> bool {
let linker = &linker.linker;
let module = match str::from_utf8(crate::slice_from_raw_parts(module, module_len)) {
Ok(s) => s,
Err(_) => return false,
};
let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) {
Ok(s) => s,
Err(_) => return false,
};
match linker.get(store, module, name) {
Some(which) => {
crate::initialize(item_ptr, which.into());
true
}
None => false,
}
}