Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ jobs:
-p wasmtime-c-api --no-default-features
-p wasmtime-c-api --no-default-features --features wat
-p wasmtime-c-api --no-default-features --features wasi
-p wasmtime-c-api --no-default-features --features gc
- name: wasmtime-wasi-http
checks: |
Expand Down
2 changes: 2 additions & 0 deletions crates/c-api-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@ pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {

#[doc = #as_ref_docs]
#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
eprintln!("`{}` is not implemented", stringify!(#as_ref));
std::process::abort();
}

#[doc = #as_ref_const_docs]
#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
eprintln!("`{}` is not implemented", stringify!(#as_ref_const));
std::process::abort();
Expand Down
2 changes: 1 addition & 1 deletion crates/c-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ doctest = false

[dependencies]
env_logger = { workspace = true, optional = true }
wasmtime = { workspace = true, features = ['runtime', 'gc', 'std'] }
wasmtime = { workspace = true, features = ['runtime', 'std'] }
wasmtime-c-api-macros = { workspace = true }
log = { workspace = true }
tracing = { workspace = true }
Expand Down
6 changes: 6 additions & 0 deletions crates/c-api/include/wasmtime/config.hh
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,15 @@ class Config {
wasmtime_config_wasm_tail_call_set(ptr.get(), enable);
}

#ifdef WASMTIME_FEATURE_GC
/// \brief Configures whether the WebAssembly reference types proposal is
/// enabled
///
/// https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.wasm_reference_types
void wasm_reference_types(bool enable) {
wasmtime_config_wasm_reference_types_set(ptr.get(), enable);
}
#endif // WASMTIME_FEATURE_GC

/// \brief Configures whether the WebAssembly simd proposal is enabled
///
Expand Down Expand Up @@ -361,11 +363,13 @@ class Config {
wasmtime_config_wasm_memory64_set(ptr.get(), enable);
}

#ifdef WASMTIME_FEATURE_GC
/// \brief Configures whether the WebAssembly Garbage Collection proposal will
/// be enabled
///
/// https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.wasm_gc
void wasm_gc(bool enable) { wasmtime_config_wasm_gc_set(ptr.get(), enable); }
#endif // WASMTIME_FEATURE_GC

/// \brief Configures whether the WebAssembly function references proposal
/// will be enabled
Expand All @@ -383,13 +387,15 @@ class Config {
wasmtime_config_wasm_wide_arithmetic_set(ptr.get(), enable);
}

#ifdef WASMTIME_FEATURE_GC
/// \brief Configures whether the WebAssembly exceptions proposal will be
/// enabled
///
/// https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.wasm_exceptions
void wasm_exceptions(bool enable) {
wasmtime_config_wasm_exceptions_set(ptr.get(), enable);
}
#endif // WASMTIME_FEATURE_GC

/// \brief Configures whether the WebAssembly custom-page-sizes proposal will
/// be enabled
Expand Down
3 changes: 3 additions & 0 deletions crates/c-api/include/wasmtime/func.hh
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ NATIVE_WASM_TYPE(double, F64, f64)

#undef NATIVE_WASM_TYPE

#ifdef WASMTIME_FEATURE_GC
/// Type information for `externref`, represented on the host as an optional
/// `ExternRef`.
template <> struct WasmType<std::optional<ExternRef>> {
Expand All @@ -102,6 +103,7 @@ template <> struct WasmType<std::optional<ExternRef>> {
p->externref = 0;
}
}

static std::optional<ExternRef> load(Store::Context cx,
wasmtime_val_raw_t *p) {
if (p->externref == 0) {
Expand All @@ -112,6 +114,7 @@ template <> struct WasmType<std::optional<ExternRef>> {
return ExternRef(val);
}
};
#endif // WASMTIME_FEATURE_GC

/// Type information for the `V128` host value used as a wasm value.
template <> struct WasmType<V128> {
Expand Down
2 changes: 2 additions & 0 deletions crates/c-api/include/wasmtime/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ WASM_API_EXTERN void wasmtime_context_set_data(wasmtime_context_t *context,
*
* The `context` argument must not be NULL.
*/
#ifdef WASMTIME_FEATURE_GC
WASM_API_EXTERN wasmtime_error_t *
wasmtime_context_gc(wasmtime_context_t *context);
#endif

/**
* \brief Set fuel to this context's store for wasm to consume while executing.
Expand Down
4 changes: 4 additions & 0 deletions crates/c-api/include/wasmtime/store.hh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public:
/// Creates a context referencing the provided `Caller`.
Context(Caller *caller);

#ifdef WASMTIME_FEATURE_GC
/// Runs a garbage collection pass in the referenced store to collect loose
/// `externref` values, if any are available.
Result<std::monostate> gc() {
Expand All @@ -103,6 +104,7 @@ public:
}
return std::monostate();
}
#endif

/// Injects fuel to be consumed within this store.
///
Expand Down Expand Up @@ -253,9 +255,11 @@ public:
/// Explicit function to acquire a `Context` from this store.
Context context() { return this; }

#ifdef WASMTIME_FEATURE_GC
/// Runs a garbage collection pass in the referenced store to collect loose
/// GC-managed objects, if any are available.
Result<std::monostate> gc() { return context().gc(); }
#endif

private:
template <typename F>
Expand Down
6 changes: 6 additions & 0 deletions crates/c-api/include/wasmtime/val.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
extern "C" {
#endif

#ifdef WASMTIME_FEATURE_GC
struct wasmtime_eqref;
/// Convenience alias for #wasmtime_eqref
typedef struct wasmtime_eqref wasmtime_eqref_t;
Expand Down Expand Up @@ -201,6 +202,7 @@ WASM_API_EXTERN bool wasmtime_anyref_i31_get_s(wasmtime_context_t *context,
* `wasmtime_externref_set_null`. Null can be tested for with the
* `wasmtime_externref_is_null` function.
*/

typedef struct wasmtime_externref {
/// Internal metadata tracking within the store, embedders should not
/// configure or modify these fields.
Expand Down Expand Up @@ -393,6 +395,8 @@ typedef uint8_t wasmtime_valkind_t;
/// exnref
#define WASMTIME_EXNREF 8

#endif // WASMTIME_FEATURE_GC

/// \brief A 128-bit value representing the WebAssembly `v128` type. Bytes are
/// stored in little-endian order.
typedef uint8_t wasmtime_v128[16];
Expand All @@ -416,6 +420,7 @@ typedef union wasmtime_valunion {
float32_t f32;
/// Field used if #wasmtime_val_t::kind is #WASMTIME_F64
float64_t f64;
#ifdef WASMTIME_FEATURE_GC
/// Field used if #wasmtime_val_t::kind is #WASMTIME_ANYREF
wasmtime_anyref_t anyref;
/// Field used if #wasmtime_val_t::kind is #WASMTIME_EXTERNREF
Expand All @@ -427,6 +432,7 @@ typedef union wasmtime_valunion {
/// Use `wasmtime_funcref_is_null` to test whether this is a null function
/// reference.
wasmtime_func_t funcref;
#endif // WASMTIME_FEATURE_GC
/// Field used if #wasmtime_val_t::kind is #WASMTIME_V128
wasmtime_v128 v128;
} wasmtime_valunion_t;
Expand Down
4 changes: 4 additions & 0 deletions crates/c-api/include/wasmtime/val.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class EqRef;
class StructRef;
class ArrayRef;

#ifdef WASMTIME_FEATURE_GC
/**
* \brief Representation of a WebAssembly `externref` value.
*
Expand Down Expand Up @@ -103,9 +104,11 @@ public:
return wasmtime_externref_to_raw(cx.capi(), &val);
}
};
#endif // WASMTIME_FEATURE_GC

class EqRef;

#ifdef WASMTIME_FEATURE_GC
/**
* \brief Representation of a WebAssembly `anyref` value.
*/
Expand Down Expand Up @@ -204,6 +207,7 @@ public:
/// \brief Downcast to arrayref. Returns null arrayref if not an arrayref.
inline std::optional<ArrayRef> as_array(Store::Context cx) const;
};
#endif // WASMTIME_FEATURE_GC

/// \brief Container for the `v128` WebAssembly type.
struct V128 {
Expand Down
4 changes: 4 additions & 0 deletions crates/c-api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,13 @@ pub extern "C" fn wasmtime_config_wasm_tail_call_set(c: &mut wasm_config_t, enab
}

#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern "C" fn wasmtime_config_wasm_reference_types_set(c: &mut wasm_config_t, enable: bool) {
c.config.wasm_reference_types(enable);
}

#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern "C" fn wasmtime_config_wasm_function_references_set(
c: &mut wasm_config_t,
enable: bool,
Expand All @@ -103,6 +105,7 @@ pub extern "C" fn wasmtime_config_wasm_function_references_set(
}

#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern "C" fn wasmtime_config_wasm_gc_set(c: &mut wasm_config_t, enable: bool) {
c.config.wasm_gc(enable);
}
Expand Down Expand Up @@ -476,6 +479,7 @@ pub extern "C" fn wasmtime_config_wasm_wide_arithmetic_set(c: &mut wasm_config_t
}

#[unsafe(no_mangle)]
#[cfg(feature = "gc")]
pub extern "C" fn wasmtime_config_wasm_exceptions_set(c: &mut wasm_config_t, enable: bool) {
c.config.wasm_exceptions(enable);
}
Expand Down
1 change: 1 addition & 0 deletions crates/c-api/src/exn.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg(feature = "gc")]
use crate::{
WasmtimeStoreContextMut, handle_result, wasm_trap_t, wasmtime_error_t, wasmtime_val_t,
};
Expand Down
32 changes: 23 additions & 9 deletions crates/c-api/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ use std::panic::{self, AssertUnwindSafe};
use std::ptr;
use std::str;
use wasmtime::{
AsContext, AsContextMut, Error, Extern, Func, Result, RootScope, StoreContext, StoreContextMut,
Trap, Val, ValRaw,
AsContext, AsContextMut, Error, Extern, Func, Result, StoreContext, StoreContextMut, Trap, Val,
ValRaw,
};
#[cfg(feature = "gc")]
use wasmtime::{RootScope, ThrownException};

#[derive(Clone)]
#[repr(transparent)]
Expand Down Expand Up @@ -351,13 +353,15 @@ pub unsafe extern "C" fn wasmtime_func_call(
nresults: usize,
trap_ret: &mut *mut wasm_trap_t,
) -> Option<Box<wasmtime_error_t>> {
let mut scope = RootScope::new(&mut store);
let mut params = mem::take(&mut scope.as_context_mut().data_mut().wasm_val_storage);
#[cfg(feature = "gc")]
let mut store = RootScope::new(&mut store);
let mut params = mem::take(&mut store.as_context_mut().data_mut().wasm_val_storage);

let (wt_params, wt_results) = translate_args(
&mut params,
crate::slice_from_raw_parts(args, nargs)
.iter()
.map(|i| i.to_val(&mut scope)),
.map(|i| i.to_val(&mut store)),
nresults,
);

Expand All @@ -366,16 +370,16 @@ pub unsafe extern "C" fn wasmtime_func_call(
// can. As a result we catch panics here and transform them to traps to
// allow the caller to have any insulation possible against Rust panics.
let result = panic::catch_unwind(AssertUnwindSafe(|| {
func.call(&mut scope, wt_params, wt_results)
func.call(&mut store, wt_params, wt_results)
}));
match result {
Ok(Ok(())) => {
let results = crate::slice_from_raw_parts_mut(results, nresults);
for (slot, val) in results.iter_mut().zip(wt_results.iter()) {
crate::initialize(slot, wasmtime_val_t::from_val(&mut scope, *val));
crate::initialize(slot, wasmtime_val_t::from_val(&mut store, *val));
}
params.truncate(0);
scope.as_context_mut().data_mut().wasm_val_storage = params;
store.as_context_mut().data_mut().wasm_val_storage = params;
None
}
Ok(Err(trap)) => store_err(trap, trap_ret),
Expand All @@ -402,8 +406,18 @@ pub unsafe extern "C" fn wasmtime_func_call_unchecked(
}
}

#[cfg(feature = "gc")]
fn is_trap_like_impl(err: &Error) -> bool {
err.is::<Trap>() || err.is::<ThrownException>()
}

#[cfg(not(feature = "gc"))]
fn is_trap_like_impl(err: &Error) -> bool {
err.is::<Trap>()
}

fn store_err(err: Error, trap_ret: &mut *mut wasm_trap_t) -> Option<Box<wasmtime_error_t>> {
if err.is::<Trap>() || err.is::<wasmtime::ThrownException>() {
if is_trap_like_impl(&err) {
*trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(err)));
None
} else {
Expand Down
30 changes: 20 additions & 10 deletions crates/c-api/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use crate::{
wasm_store_t, wasm_val_t, wasmtime_error_t, wasmtime_val_t,
};
use std::mem::MaybeUninit;
use wasmtime::{Extern, Global, RootScope};
#[cfg(feature = "gc")]
use wasmtime::RootScope;
use wasmtime::{Extern, Global};

#[derive(Clone)]
#[repr(transparent)]
Expand Down Expand Up @@ -84,9 +86,11 @@ pub unsafe extern "C" fn wasmtime_global_new(
val: &wasmtime_val_t,
ret: &mut Global,
) -> Option<Box<wasmtime_error_t>> {
let mut scope = RootScope::new(&mut store);
let val = val.to_val(&mut scope);
let global = Global::new(scope, gt.ty().ty.clone(), val);
#[cfg(feature = "gc")]
let mut store = RootScope::new(&mut store);

let val = val.to_val(&mut store);
let global = Global::new(&mut store, gt.ty().ty.clone(), val);
handle_result(global, |global| {
*ret = global;
})
Expand All @@ -106,9 +110,13 @@ pub extern "C" fn wasmtime_global_get(
global: &Global,
val: &mut MaybeUninit<wasmtime_val_t>,
) {
let mut scope = RootScope::new(store);
let gval = global.get(&mut scope);
crate::initialize(val, wasmtime_val_t::from_val(&mut scope, gval))
let mut store = store;

#[cfg(feature = "gc")]
let mut store = RootScope::new(&mut store);

let gval = global.get(&mut store);
crate::initialize(val, wasmtime_val_t::from_val(&mut store, gval))
}

#[unsafe(no_mangle)]
Expand All @@ -117,7 +125,9 @@ pub unsafe extern "C" fn wasmtime_global_set(
global: &Global,
val: &wasmtime_val_t,
) -> Option<Box<wasmtime_error_t>> {
let mut scope = RootScope::new(&mut store);
let val = val.to_val(&mut scope);
handle_result(global.set(scope, val), |()| {})
#[cfg(feature = "gc")]
let mut store = RootScope::new(&mut store);

let val = val.to_val(&mut store);
handle_result(global.set(&mut store, val), |()| {})
}
Loading
Loading