Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wasmtime-specific C APIs for tables #1654

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions crates/c-api/include/wasmtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,32 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_validate(
const wasm_byte_vec_t *binary
);


// Similar to `wasm_table_*`, except these explicitly operate on funcref tables
// and work with `wasm_func_t` values instead of `wasm_ref_t`.
WASM_API_EXTERN own wasmtime_error_t *wasmtime_funcref_table_new(
wasm_store_t *store,
const wasm_tabletype_t *element_ty,
wasm_func_t *init,
own wasm_table_t **table
);
WASM_API_EXTERN bool wasmtime_funcref_table_get(
const wasm_table_t *table,
wasm_table_size_t index,
own wasm_func_t **func
);
WASM_API_EXTERN own wasmtime_error_t *wasmtime_funcref_table_set(
wasm_table_t *table,
wasm_table_size_t index,
const wasm_func_t *value
);
WASM_API_EXTERN wasmtime_error_t *wasmtime_funcref_table_grow(
wasm_table_t *table,
wasm_table_size_t delta,
const wasm_func_t *init,
wasm_table_size_t *prev_size
);

#undef own

#ifdef __cplusplus
Expand Down
18 changes: 12 additions & 6 deletions crates/c-api/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl wasm_func_t {
}
}

fn func(&self) -> &HostRef<Func> {
pub(crate) fn func(&self) -> &HostRef<Func> {
match &self.ext.which {
ExternHost::Func(f) => f,
_ => unsafe { std::hint::unreachable_unchecked() },
Expand All @@ -75,6 +75,16 @@ impl wasm_func_t {
}
}

impl From<HostRef<Func>> for wasm_func_t {
fn from(func: HostRef<Func>) -> wasm_func_t {
wasm_func_t {
ext: wasm_extern_t {
which: ExternHost::Func(func),
},
}
}
}

fn create_function(
store: &wasm_store_t,
ty: &wasm_functype_t,
Expand All @@ -97,11 +107,7 @@ fn create_function(
}
Ok(())
});
Box::new(wasm_func_t {
ext: wasm_extern_t {
which: ExternHost::Func(HostRef::new(func)),
},
})
Box::new(HostRef::new(func).into())
}

#[no_mangle]
Expand Down
97 changes: 85 additions & 12 deletions crates/c-api/src/table.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::wasm_ref_t;
use crate::{handle_result, wasm_func_t, wasm_ref_t, wasmtime_error_t};
use crate::{wasm_extern_t, wasm_store_t, wasm_tabletype_t, ExternHost};
use std::ptr;
use wasmtime::{AnyRef, HostRef, Table, Val};
Expand Down Expand Up @@ -34,15 +34,14 @@ impl wasm_table_t {
}

#[no_mangle]
pub unsafe extern "C" fn wasm_table_new(
pub extern "C" fn wasm_table_new(
store: &wasm_store_t,
tt: &wasm_tabletype_t,
init: *mut wasm_ref_t,
init: Option<Box<wasm_ref_t>>,
) -> Option<Box<wasm_table_t>> {
let init: Val = if !init.is_null() {
Box::from_raw(init).r.into()
} else {
Val::AnyRef(AnyRef::Null)
let init: Val = match init {
Some(init) => init.r.into(),
None => Val::AnyRef(AnyRef::Null),
};
let table = Table::new(&store.store.borrow(), tt.ty().ty.clone(), init).ok()?;
Some(Box::new(wasm_table_t {
Expand All @@ -52,23 +51,66 @@ pub unsafe extern "C" fn wasm_table_new(
}))
}

#[no_mangle]
pub extern "C" fn wasmtime_funcref_table_new(
store: &wasm_store_t,
tt: &wasm_tabletype_t,
init: Option<&wasm_func_t>,
out: &mut *mut wasm_table_t,
) -> Option<Box<wasmtime_error_t>> {
let init: Val = match init {
Some(val) => Val::FuncRef(val.func().borrow().clone()),
None => Val::AnyRef(AnyRef::Null),
};
handle_result(
Table::new(&store.store.borrow(), tt.ty().ty.clone(), init),
|table| {
*out = Box::into_raw(Box::new(wasm_table_t {
ext: wasm_extern_t {
which: ExternHost::Table(HostRef::new(table)),
},
}));
println!("ret at {:?}", *out);
},
)
}

#[no_mangle]
pub extern "C" fn wasm_table_type(t: &wasm_table_t) -> Box<wasm_tabletype_t> {
let ty = t.table().borrow().ty();
Box::new(wasm_tabletype_t::new(ty))
}

#[no_mangle]
pub unsafe extern "C" fn wasm_table_get(
t: &wasm_table_t,
index: wasm_table_size_t,
) -> *mut wasm_ref_t {
pub extern "C" fn wasm_table_get(t: &wasm_table_t, index: wasm_table_size_t) -> *mut wasm_ref_t {
match t.table().borrow().get(index) {
Some(val) => into_funcref(val),
None => into_funcref(Val::AnyRef(AnyRef::Null)),
}
}

#[no_mangle]
pub extern "C" fn wasmtime_funcref_table_get(
t: &wasm_table_t,
index: wasm_table_size_t,
ptr: &mut *mut wasm_func_t,
) -> bool {
println!("get {:p} at {}", t, index);
match t.table().borrow().get(index) {
Some(val) => {
*ptr = match val {
// TODO: what do do about creating new `HostRef` handles here?
Val::FuncRef(f) => Box::into_raw(Box::new(HostRef::new(f).into())),
Val::AnyRef(AnyRef::Null) => ptr::null_mut(),
_ => return false,
};
}

_ => return false,
}
true
}

#[no_mangle]
pub unsafe extern "C" fn wasm_table_set(
t: &wasm_table_t,
Expand All @@ -79,7 +121,20 @@ pub unsafe extern "C" fn wasm_table_set(
t.table().borrow().set(index, val).is_ok()
}

unsafe fn into_funcref(val: Val) -> *mut wasm_ref_t {
#[no_mangle]
pub extern "C" fn wasmtime_funcref_table_set(
t: &wasm_table_t,
index: wasm_table_size_t,
val: Option<&wasm_func_t>,
) -> Option<Box<wasmtime_error_t>> {
let val = match val {
Some(val) => Val::FuncRef(val.func().borrow().clone()),
None => Val::AnyRef(AnyRef::Null),
};
handle_result(t.table().borrow().set(index, val), |()| {})
}

fn into_funcref(val: Val) -> *mut wasm_ref_t {
if let Val::AnyRef(AnyRef::Null) = val {
return ptr::null_mut();
}
Expand Down Expand Up @@ -114,6 +169,24 @@ pub unsafe extern "C" fn wasm_table_grow(
t.table().borrow().grow(delta, init).is_ok()
}

#[no_mangle]
pub extern "C" fn wasmtime_funcref_table_grow(
t: &wasm_table_t,
delta: wasm_table_size_t,
init: Option<&wasm_func_t>,
prev_size: Option<&mut wasm_table_size_t>,
) -> Option<Box<wasmtime_error_t>> {
let val = match init {
Some(val) => Val::FuncRef(val.func().borrow().clone()),
None => Val::AnyRef(AnyRef::Null),
};
handle_result(t.table().borrow().grow(delta, val), |prev| {
if let Some(ptr) = prev_size {
*ptr = prev;
}
})
}

#[no_mangle]
pub extern "C" fn wasm_table_as_extern(t: &wasm_table_t) -> &wasm_extern_t {
&t.ext
Expand Down