5#ifndef WASMTIME_FUNC_HH
6#define WASMTIME_FUNC_HH
10#include <wasmtime/extern_declare.hh>
39 std::optional<Extern>
get_export(std::string_view name);
53template <
typename T>
struct WasmType {
54 static const bool valid =
false;
60#define NATIVE_WASM_TYPE(native, valkind, field) \
61 template <> struct WasmType<native> { \
62 static const bool valid = true; \
63 static const ValKind kind = ValKind::valkind; \
64 static void store(Store::Context cx, wasmtime_val_raw_t *p, \
69 static native load(Store::Context cx, wasmtime_val_raw_t *p) { \
82#undef NATIVE_WASM_TYPE
84#ifdef WASMTIME_FEATURE_GC
87template <>
struct WasmType<std::optional<ExternRef>> {
88 static const bool valid =
true;
89 static const ValKind kind = ValKind::ExternRef;
91 std::optional<ExternRef> &&ref) {
99 const std::optional<ExternRef> &ref) {
107 static std::optional<ExternRef> load(Store::Context cx,
112 wasmtime_externref_t val;
113 wasmtime_externref_from_raw(cx.capi(), p->
externref, &val);
114 return ExternRef(val);
120template <>
struct WasmType<
V128> {
121 static const bool valid =
true;
122 static const ValKind kind = ValKind::V128;
137template <
typename T>
struct WasmTypeList {
138 static const bool valid = WasmType<T>::valid;
139 static const size_t size = 1;
140 static bool matches(ValType::ListRef types) {
141 return WasmTypeList<std::tuple<T>>::matches(types);
144 WasmType<T>::store(cx, storage, t);
148 WasmType<T>::store(cx, storage, t);
151 return WasmType<T>::load(cx, storage);
153 static std::vector<ValType> types() {
return {WasmType<T>::kind}; }
157template <>
struct WasmTypeList<std::monostate> {
158 static const bool valid =
true;
159 static const size_t size = 0;
160 static bool matches(ValType::ListRef types) {
return types.size() == 0; }
162 const std::monostate &t) {
170 return std::monostate();
172 static std::vector<ValType> types() {
return {}; }
176template <
typename... T>
struct WasmTypeList<std::tuple<T...>> {
177 static const bool valid = (WasmType<T>::valid && ...);
178 static const size_t size =
sizeof...(T);
179 static bool matches(ValType::ListRef types) {
180 if (types.size() != size) {
184 return ((WasmType<T>::kind == types.begin()[n++].kind()) && ...);
187 std::tuple<T...> &&t) {
191 (WasmType<T>::store(cx, &storage[n++], val), ...);
196 const std::tuple<T...> &t) {
199 [&](
const auto &...val) {
200 (WasmType<T>::store(cx, &storage[n++], val), ...);
206 return std::tuple<T...>{WasmType<T>::load(cx, storage++)...};
208 static std::vector<ValType> types() {
return {WasmType<T>::kind...}; }
214template <
typename R>
struct WasmHostRet {
215 using Results = WasmTypeList<R>;
217 template <
typename F,
typename... A>
220 auto ret = f(args...);
221 Results::store(cx, raw, ret);
227template <>
struct WasmHostRet<void> {
228 using Results = WasmTypeList<std::tuple<>>;
230 template <
typename F,
typename... A>
242template <>
struct WasmHostRet<std::monostate> :
public WasmHostRet<void> {};
246template <
typename R>
struct WasmHostRet<Result<R, Trap>> {
247 using Results = WasmTypeList<R>;
249 template <
typename F,
typename... A>
252 Result<R, Trap> ret = f(args...);
256 Results::store(cx, raw, ret.ok());
261template <
typename F,
typename =
void>
struct WasmHostFunc;
265template <
typename R,
typename... A>
struct WasmHostFunc<R (*)(A...)> {
266 using Params = WasmTypeList<std::tuple<A...>>;
267 using Results =
typename WasmHostRet<R>::Results;
269 template <
typename F>
271 auto params = Params::load(cx, raw);
273 [&](
const auto &...val) {
274 return WasmHostRet<R>::invoke(f, cx, raw, val...);
281template <
typename R,
typename... A>
282struct WasmHostFunc<R (*)(Caller, A...)> :
public WasmHostFunc<R (*)(A...)> {
284 template <
typename F>
286 auto params = WasmTypeList<std::tuple<A...>>::load(cx, raw);
288 [&](
const auto &...val) {
289 return WasmHostRet<R>::invoke(f, cx, raw, cx, val...);
296template <
typename R,
typename C,
typename... A>
297struct WasmHostFunc<R (C::*)(A...)> :
public WasmHostFunc<R (*)(A...)> {};
300template <
typename R,
typename C,
typename... A>
301struct WasmHostFunc<R (C::*)(A...) const> :
public WasmHostFunc<R (*)(A...)> {};
305template <
typename R,
typename C,
typename... A>
306struct WasmHostFunc<R (C::*)(Caller, A...)>
307 :
public WasmHostFunc<R (*)(Caller, A...)> {};
311template <
typename R,
typename C,
typename... A>
312struct WasmHostFunc<R (C::*)(Caller, A...) const>
313 :
public WasmHostFunc<R (*)(Caller, A...)> {};
318struct WasmHostFunc<T, std::void_t<decltype(&T::operator())>>
319 :
public WasmHostFunc<decltype(&T::operator())> {};
323using namespace detail;
326template <
typename Params,
typename Results>
class TypedFunc;
343 template <
typename Params,
typename Results>
friend class TypedFunc;
347 template <
typename F>
353 F *func =
reinterpret_cast<F *
>(env);
356 Span<Val> results_span(
reinterpret_cast<Val *
>(results),
359 (*func)(
Caller(caller), args_span, results_span);
361 return result.
err().capi_release();
366 template <
typename F>
370 size_t nargs_and_results) {
371 (void)nargs_and_results;
372 using HostFunc = WasmHostFunc<F>;
374 F *func =
reinterpret_cast<F *
>(env);
375 auto trap = HostFunc::invoke(*func, cx, args_and_results);
377 return trap->capi_release();
382 template <
typename F>
static void raw_finalize(
void *env) {
383 std::unique_ptr<F> ptr(
reinterpret_cast<F *
>(env));
421 template <
typename F,
423 std::is_invocable_r_v<Result<std::monostate, Trap>, F,
Caller,
428 std::make_unique<F>(f).release(), raw_finalize<F>, &func);
469 template <
typename F,
470 std::enable_if_t<WasmHostFunc<F>::Params::valid,
bool> =
true,
471 std::enable_if_t<WasmHostFunc<F>::Results::valid,
bool> =
true>
473 using HostFunc = WasmHostFunc<F>;
474 auto params = HostFunc::Params::types();
475 auto results = HostFunc::Results::types();
479 std::make_unique<F>(f).release(),
480 raw_finalize<F>, &func);
504 template <
typename I>
506 const I &end)
const {
507 std::vector<wasmtime_val_t> raw_params;
508 raw_params.reserve(end - begin);
509 for (
auto i = begin; i != end; i++) {
510 raw_params.push_back(i->val);
512 size_t nresults = this->type(cx)->results().size();
513 std::vector<wasmtime_val_t> raw_results(nresults);
518 raw_results.data(), raw_results.capacity(), &trap);
519 if (error !=
nullptr) {
522 if (trap !=
nullptr) {
526 std::vector<Val> results;
527 results.reserve(nresults);
528 for (
size_t i = 0; i < nresults; i++) {
529 results.push_back(raw_results[i]);
541 const std::vector<Val> ¶ms)
const {
542 return this->call(cx, params.begin(), params.end());
553 return this->call(cx, params.begin(), params.end());
578 template <
typename Params,
typename Results,
579 std::enable_if_t<WasmTypeList<Params>::valid,
bool> =
true,
580 std::enable_if_t<WasmTypeList<Results>::valid,
bool> =
true>
582 auto ty = this->type(cx);
583 if (!WasmTypeList<Params>::matches(ty->params()) ||
584 !WasmTypeList<Results>::matches(ty->results())) {
585 return Trap(
"static type for this function does not match actual type");
599template <
typename Params,
typename Results>
class TypedFunc {
617 WasmTypeList<Results>::size)>
622 WasmTypeList<Params>::store(cx, ptr, params);
625 storage.size(), &trap);
626 if (error !=
nullptr) {
629 if (trap !=
nullptr) {
632 return WasmTypeList<Results>::load(cx, ptr);
639inline Val::Val(std::optional<Func> func) : val{} {
642 val.
of.funcref = (*func).func;
644 wasmtime_funcref_set_null(&val.
of.funcref);
648inline Val::Val(
Func func) :
Val(std::optional(func)) {}
649inline Val::Val(ExternRef ptr) :
Val(std::optional(ptr)) {}
650inline Val::Val(AnyRef ptr) :
Val(std::optional(ptr)) {}
656 if (val.
of.funcref.store_id == 0) {
659 return Func(val.
of.funcref);
663template <>
struct detail::WasmType<std::optional<Func>> {
665 static const bool valid =
true;
667 static const ValKind kind = ValKind::FuncRef;
670 const std::optional<Func> func) {
Structure provided to host functions to lookup caller information or acquire a Store::Context.
Definition: func.hh:28
std::optional< Extern > get_export(std::string_view name)
Definition: extern.hh:59
Store::Context context()
Explicitly acquire a Store::Context from this Caller.
Definition: func.hh:42
Errors coming from Wasmtime.
Definition: error.hh:26
Type information for a WebAssembly function.
Definition: types/func.hh:15
static FuncType from_iters(P params, R results)
Creates a new function type from the given list of parameters and results.
Definition: types/func.hh:76
Representation of a WebAssembly function.
Definition: func.hh:339
TrapResult< std::vector< Val > > call(Store::Context cx, const I &begin, const I &end) const
Invoke a WebAssembly function.
Definition: func.hh:505
Func(wasmtime_func_t func)
Creates a new function from the raw underlying C API representation.
Definition: func.hh:388
FuncType type(Store::Context cx) const
Returns the type of this function.
Definition: func.hh:557
TrapResult< std::vector< Val > > call(Store::Context cx, const std::vector< Val > ¶ms) const
Helper function for call(Store::Context cx, const I &begin, const I &end)
Definition: func.hh:540
static Func wrap(Store::Context cx, F f)
Creates a new host function from the provided callback f, inferring the WebAssembly function type fro...
Definition: func.hh:472
TrapResult< std::vector< Val > > call(Store::Context cx, const std::initializer_list< Val > ¶ms) const
Helper function for call(Store::Context cx, const I &begin, const I &end)
Definition: func.hh:552
const wasmtime_func_t & capi() const
Returns the raw underlying C API function this is using.
Definition: func.hh:592
Func(Store::Context cx, const FuncType &ty, F f)
Creates a new host-defined function.
Definition: func.hh:426
Result< TypedFunc< Params, Results >, Trap > typed(Store::Context cx) const
Statically checks this function against the provided types.
Definition: func.hh:581
A WebAssembly instance.
Definition: instance.hh:32
Helper class for linking modules together with name-based resolution.
Definition: linker.hh:26
Fallible result type used for Wasmtime.
Definition: error.hh:70
E && err()
Returns the error, if present, aborts if this is not an error.
Definition: error.hh:84
Span class used when c++20 is not available.
Definition: span.hh:47
An interior pointer into a Store.
Definition: store.hh:69
Context(wasmtime_context_t *ptr)
Creates a context from the raw C API pointer.
Definition: store.hh:86
const wasmtime_context_t * capi() const
Returns the underlying C API pointer.
Definition: store.hh:190
Owner of all WebAssembly objects.
Definition: store.hh:45
Information about a WebAssembly trap.
Definition: trap.hh:113
A version of a WebAssembly Func where the type signature of the function is statically known.
Definition: func.hh:599
const Func & func() const
Returns the underlying un-typed Func for this function.
Definition: func.hh:636
TrapResult< Results > call(Store::Context cx, const Params ¶ms) const
Calls this function with the provided parameters.
Definition: func.hh:615
Representation of a generic WebAssembly value.
Definition: val.hh:240
std::optional< Func > funcref() const
Definition: func.hh:652
WASM_API_EXTERN wasmtime_error_t * wasmtime_func_call(wasmtime_context_t *store, const wasmtime_func_t *func, const wasmtime_val_t *args, size_t nargs, wasmtime_val_t *results, size_t nresults, wasm_trap_t **trap)
Call a WebAssembly function.
WASM_API_EXTERN void wasmtime_func_new(wasmtime_context_t *store, const wasm_functype_t *type, wasmtime_func_callback_t callback, void *env, void(*finalizer)(void *), wasmtime_func_t *ret)
Creates a new host-defined function.
WASM_API_EXTERN wasmtime_context_t * wasmtime_caller_context(wasmtime_caller_t *caller)
Returns the store context of the caller object.
WASM_API_EXTERN wasm_functype_t * wasmtime_func_type(const wasmtime_context_t *store, const wasmtime_func_t *func)
Returns the type of the function specified.
WASM_API_EXTERN void * wasmtime_func_to_raw(wasmtime_context_t *context, const wasmtime_func_t *func)
Converts a func which belongs to context into a usize parameter that is suitable for insertion into a...
WASM_API_EXTERN void wasmtime_func_from_raw(wasmtime_context_t *context, void *raw, wasmtime_func_t *ret)
Converts a raw nonzero funcref value from wasmtime_val_raw_t into a wasmtime_func_t.
WASM_API_EXTERN void wasmtime_func_new_unchecked(wasmtime_context_t *store, const wasm_functype_t *type, wasmtime_func_unchecked_callback_t callback, void *env, void(*finalizer)(void *), wasmtime_func_t *ret)
Creates a new host function in the same manner of wasmtime_func_new, but the function-to-call has no ...
WASM_API_EXTERN wasmtime_error_t * wasmtime_func_call_unchecked(wasmtime_context_t *store, const wasmtime_func_t *func, wasmtime_val_raw_t *args_and_results, size_t args_and_results_len, wasm_trap_t **trap)
Call a WebAssembly function in an "unchecked" fashion.
#define NATIVE_WASM_TYPE(native, valkind, field)
Definition: func.hh:60
Opaque struct representing a wasm trap.
Structure used to represent either a Trap or an Error.
Definition: trap.hh:153
Representation of a function in Wasmtime.
Definition: extern.h:26
Container for different kinds of wasm values.
Definition: val.h:546
wasmtime_valkind_t kind
Discriminant of which field of of is valid.
Definition: val.h:548
wasmtime_valunion_t of
Container for the extern item's value.
Definition: val.h:550
ValKind
Different kinds of types accepted by Wasmtime.
Definition: types/val.hh:16
@ V128
WebAssembly's v128 type from the simd proposal.
Container for possible wasm values.
Definition: val.h:470
uint32_t externref
Definition: val.h:506
wasmtime_v128 v128
Definition: val.h:490
void * funcref
Definition: val.h:513
union wasmtime_val_raw wasmtime_val_raw_t
Convenience alias for wasmtime_val_raw.
uint8_t wasmtime_v128[16]
A 128-bit value representing the WebAssembly v128 type. Bytes are stored in little-endian order.
Definition: val.h:401
#define WASMTIME_FUNCREF
Value of wasmtime_valkind_t meaning that wasmtime_val_t is a funcref.
Definition: val.h:388