Wasmtime
wasmtime.hh
Go to the documentation of this file.
1
30#ifndef WASMTIME_HH
31#define WASMTIME_HH
32
33#include <any>
34#include <array>
35#include <cstdio>
36#include <initializer_list>
37#include <iosfwd>
38#include <limits>
39#include <memory>
40#include <optional>
41#include <ostream>
42#include <variant>
43#include <vector>
44
45#include <wasmtime.h>
46#include <wasmtime/config.hh>
47#include <wasmtime/engine.hh>
48#include <wasmtime/error.hh>
49#include <wasmtime/module.hh>
50#include <wasmtime/store.hh>
51#include <wasmtime/trap.hh>
52#include <wasmtime/types.hh>
53#include <wasmtime/wasi.hh>
54#include <wasmtime/val.hh>
55
56namespace wasmtime {
57
58class Caller;
59class Func;
60class Global;
61class Instance;
62class Memory;
63class Table;
64
67typedef std::variant<Func, Global, Memory, Table> Extern;
68
69template <typename Params, typename Results> class TypedFunc;
70
78class Caller {
79 friend class Func;
80 friend class Store;
82 Caller(wasmtime_caller_t *ptr) : ptr(ptr) {}
83
84public:
89 std::optional<Extern> get_export(std::string_view name);
90
92 Store::Context context() { return this; }
93};
94
95inline Store::Context::Context(Caller &caller)
96 : Context(wasmtime_caller_context(caller.ptr)) {}
97inline Store::Context::Context(Caller *caller) : Context(*caller) {}
98
99namespace detail {
100
103template <typename T> struct WasmType { static const bool valid = false; };
104
107// NOLINTNEXTLINE
108#define NATIVE_WASM_TYPE(native, valkind, field) \
109 template <> struct WasmType<native> { \
110 static const bool valid = true; \
111 static const ValKind kind = ValKind::valkind; \
112 static void store(Store::Context cx, wasmtime_val_raw_t *p, \
113 const native &t) { \
114 p->field = t; \
115 } \
116 static native load(Store::Context cx, wasmtime_val_raw_t *p) { \
117 return p->field; \
118 } \
119 };
120
121NATIVE_WASM_TYPE(int32_t, I32, i32)
122NATIVE_WASM_TYPE(uint32_t, I32, i32)
123NATIVE_WASM_TYPE(int64_t, I64, i64)
124NATIVE_WASM_TYPE(uint64_t, I64, i64)
125NATIVE_WASM_TYPE(float, F32, f32)
126NATIVE_WASM_TYPE(double, F64, f64)
127
128#undef NATIVE_WASM_TYPE
129
132template <> struct WasmType<std::optional<ExternRef>> {
133 static const bool valid = true;
134 static const ValKind kind = ValKind::ExternRef;
135 static void store(Store::Context cx, wasmtime_val_raw_t *p,
136 const std::optional<ExternRef> &ref) {
137 if (ref) {
138 p->externref = wasmtime_externref_to_raw(cx.raw_context(), ref->raw());
139 } else {
140 p->externref = 0;
141 }
142 }
143 static std::optional<ExternRef> load(Store::Context cx,
145 if (p->externref == 0) {
146 return std::nullopt;
147 }
149 wasmtime_externref_from_raw(cx.raw_context(), p->externref, &val);
150 return ExternRef(val);
151 }
152};
153
155template <> struct WasmType<V128> {
156 static const bool valid = true;
157 static const ValKind kind = ValKind::V128;
158 static void store(Store::Context cx, wasmtime_val_raw_t *p, const V128 &t) {
159 memcpy(&p->v128[0], &t.v128[0], sizeof(wasmtime_v128));
160 }
161 static V128 load(Store::Context cx, wasmtime_val_raw_t *p) { return p->v128; }
162};
163
168template <typename T> struct WasmTypeList {
169 static const bool valid = WasmType<T>::valid;
170 static const size_t size = 1;
171 static bool matches(ValType::ListRef types) {
172 return WasmTypeList<std::tuple<T>>::matches(types);
173 }
174 static void store(Store::Context cx, wasmtime_val_raw_t *storage,
175 const T &t) {
176 WasmType<T>::store(cx, storage, t);
177 }
178 static T load(Store::Context cx, wasmtime_val_raw_t *storage) {
179 return WasmType<T>::load(cx, storage);
180 }
181 static std::vector<ValType> types() { return {WasmType<T>::kind}; }
182};
183
185template <> struct WasmTypeList<std::monostate> {
186 static const bool valid = true;
187 static const size_t size = 0;
188 static bool matches(ValType::ListRef types) { return types.size() == 0; }
189 static void store(Store::Context cx, wasmtime_val_raw_t *storage,
190 const std::monostate &t) {}
191 static std::monostate load(Store::Context cx, wasmtime_val_raw_t *storage) {
192 return std::monostate();
193 }
194 static std::vector<ValType> types() { return {}; }
195};
196
198template <typename... T> struct WasmTypeList<std::tuple<T...>> {
199 static const bool valid = (WasmType<T>::valid && ...);
200 static const size_t size = sizeof...(T);
201 static bool matches(ValType::ListRef types) {
202 if (types.size() != size) {
203 return false;
204 }
205 size_t n = 0;
206 return ((WasmType<T>::kind == types.begin()[n++].kind()) && ...);
207 }
208 static void store(Store::Context cx, wasmtime_val_raw_t *storage,
209 const std::tuple<T...> &t) {
210 size_t n = 0;
211 std::apply(
212 [&](const auto &...val) {
213 (WasmType<T>::store(cx, &storage[n++], val), ...); // NOLINT
214 },
215 t);
216 }
217 static std::tuple<T...> load(Store::Context cx, wasmtime_val_raw_t *storage) {
218 size_t n = 0;
219 return std::tuple<T...>{WasmType<T>::load(cx, &storage[n++])...}; // NOLINT
220 }
221 static std::vector<ValType> types() { return {WasmType<T>::kind...}; }
222};
223
227template <typename R> struct WasmHostRet {
228 using Results = WasmTypeList<R>;
229
230 template <typename F, typename... A>
231 static std::optional<Trap> invoke(F f, Caller cx, wasmtime_val_raw_t *raw,
232 A... args) {
233 auto ret = f(args...);
234 Results::store(cx, raw, ret);
235 return std::nullopt;
236 }
237};
238
240template <> struct WasmHostRet<void> {
241 using Results = WasmTypeList<std::tuple<>>;
242
243 template <typename F, typename... A>
244 static std::optional<Trap> invoke(F f, Caller cx, wasmtime_val_raw_t *raw,
245 A... args) {
246 f(args...);
247 return std::nullopt;
248 }
249};
250
251// Alternative method of returning "nothing" (also enables `std::monostate` in
252// the `R` type of `Result` below)
253template <> struct WasmHostRet<std::monostate> : public WasmHostRet<void> {};
254
257template <typename R> struct WasmHostRet<Result<R, Trap>> {
258 using Results = WasmTypeList<R>;
259
260 template <typename F, typename... A>
261 static std::optional<Trap> invoke(F f, Caller cx, wasmtime_val_raw_t *raw,
262 A... args) {
263 Result<R, Trap> ret = f(args...);
264 if (!ret) {
265 return ret.err();
266 }
267 Results::store(cx, raw, ret.ok());
268 return std::nullopt;
269 }
270};
271
272template <typename F, typename = void> struct WasmHostFunc;
273
276template <typename R, typename... A> struct WasmHostFunc<R (*)(A...)> {
277 using Params = WasmTypeList<std::tuple<A...>>;
278 using Results = typename WasmHostRet<R>::Results;
279
280 template <typename F>
281 static std::optional<Trap> invoke(F &f, Caller cx, wasmtime_val_raw_t *raw) {
282 auto params = Params::load(cx, raw);
283 return std::apply(
284 [&](const auto &...val) {
285 return WasmHostRet<R>::invoke(f, cx, raw, val...);
286 },
287 params);
288 }
289};
290
292template <typename R, typename... A>
293struct WasmHostFunc<R (*)(Caller, A...)> : public WasmHostFunc<R (*)(A...)> {
294 // Override `invoke` here to pass the `cx` as the first parameter
295 template <typename F>
296 static std::optional<Trap> invoke(F &f, Caller cx, wasmtime_val_raw_t *raw) {
297 auto params = WasmTypeList<std::tuple<A...>>::load(cx, raw);
298 return std::apply(
299 [&](const auto &...val) {
300 return WasmHostRet<R>::invoke(f, cx, raw, cx, val...);
301 },
302 params);
303 }
304};
305
307template <typename R, typename C, typename... A>
308struct WasmHostFunc<R (C::*)(A...)> : public WasmHostFunc<R (*)(A...)> {};
309
311template <typename R, typename C, typename... A>
312struct WasmHostFunc<R (C::*)(A...) const> : public WasmHostFunc<R (*)(A...)> {};
313
316template <typename R, typename C, typename... A>
317struct WasmHostFunc<R (C::*)(Caller, A...)>
318 : public WasmHostFunc<R (*)(Caller, A...)> {};
319
322template <typename R, typename C, typename... A>
323struct WasmHostFunc<R (C::*)(Caller, A...) const>
324 : public WasmHostFunc<R (*)(Caller, A...)> {};
325
328template <typename T>
329struct WasmHostFunc<T, std::void_t<decltype(&T::operator())>>
330 : public WasmHostFunc<decltype(&T::operator())> {};
331
332} // namespace detail
333
334using namespace detail;
335
347class Func {
348 friend class Val;
349 friend class Instance;
350 friend class Linker;
351 template <typename Params, typename Results> friend class TypedFunc;
352
353 wasmtime_func_t func;
354
355 template <typename F>
356 static wasm_trap_t *raw_callback(void *env, wasmtime_caller_t *caller,
357 const wasmtime_val_t *args, size_t nargs,
358 wasmtime_val_t *results, size_t nresults) {
359 static_assert(alignof(Val) == alignof(wasmtime_val_t));
360 static_assert(sizeof(Val) == sizeof(wasmtime_val_t));
361 F *func = reinterpret_cast<F *>(env); // NOLINT
362 Span<const Val> args_span(reinterpret_cast<const Val *>(args), // NOLINT
363 nargs);
364 Span<Val> results_span(reinterpret_cast<Val *>(results), // NOLINT
365 nresults);
367 (*func)(Caller(caller), args_span, results_span);
368 if (!result) {
369 return result.err().ptr.release();
370 }
371 return nullptr;
372 }
373
374 template <typename F>
375 static wasm_trap_t *
376 raw_callback_unchecked(void *env, wasmtime_caller_t *caller,
377 wasmtime_val_raw_t *args_and_results,
378 size_t nargs_and_results) {
379 using HostFunc = WasmHostFunc<F>;
380 Caller cx(caller);
381 F *func = reinterpret_cast<F *>(env); // NOLINT
382 auto trap = HostFunc::invoke(*func, cx, args_and_results);
383 if (trap) {
384 return trap->ptr.release();
385 }
386 return nullptr;
387 }
388
389 template <typename F> static void raw_finalize(void *env) {
390 std::unique_ptr<F> ptr(reinterpret_cast<F *>(env)); // NOLINT
391 }
392
393public:
395 Func(wasmtime_func_t func) : func(func) {}
396
428 template <typename F,
429 std::enable_if_t<
430 std::is_invocable_r_v<Result<std::monostate, Trap>, F, Caller,
432 bool> = true>
433 Func(Store::Context cx, const FuncType &ty, F f) : func({}) {
434 wasmtime_func_new(cx.ptr, ty.ptr.get(), raw_callback<F>,
435 std::make_unique<F>(f).release(), raw_finalize<F>, &func);
436 }
437
476 template <typename F,
477 std::enable_if_t<WasmHostFunc<F>::Params::valid, bool> = true,
478 std::enable_if_t<WasmHostFunc<F>::Results::valid, bool> = true>
479 static Func wrap(Store::Context cx, F f) {
480 using HostFunc = WasmHostFunc<F>;
481 auto params = HostFunc::Params::types();
482 auto results = HostFunc::Results::types();
483 auto ty = FuncType::from_iters(params, results);
484 wasmtime_func_t func;
485 wasmtime_func_new_unchecked(cx.ptr, ty.ptr.get(), raw_callback_unchecked<F>,
486 std::make_unique<F>(f).release(),
487 raw_finalize<F>, &func);
488 return func;
489 }
490
511 template <typename I>
513 const I &end) const {
514 std::vector<wasmtime_val_t> raw_params;
515 raw_params.reserve(end - begin);
516 for (auto i = begin; i != end; i++) {
517 raw_params.push_back(i->val);
518 }
519 size_t nresults = this->type(cx)->results().size();
520 std::vector<wasmtime_val_t> raw_results(nresults);
521
522 wasm_trap_t *trap = nullptr;
523 auto *error =
524 wasmtime_func_call(cx.ptr, &func, raw_params.data(), raw_params.size(),
525 raw_results.data(), raw_results.capacity(), &trap);
526 if (error != nullptr) {
527 return TrapError(Error(error));
528 }
529 if (trap != nullptr) {
530 return TrapError(Trap(trap));
531 }
532
533 std::vector<Val> results;
534 results.reserve(nresults);
535 for (size_t i = 0; i < nresults; i++) {
536 results.push_back(raw_results[i]);
537 }
538 return results;
539 }
540
548 const std::vector<Val> &params) const {
549 return this->call(cx, params.begin(), params.end());
550 }
551
559 call(Store::Context cx, const std::initializer_list<Val> &params) const {
560 return this->call(cx, params.begin(), params.end());
561 }
562
565 return wasmtime_func_type(cx.ptr, &func);
566 }
567
585 template <typename Params, typename Results,
586 std::enable_if_t<WasmTypeList<Params>::valid, bool> = true,
587 std::enable_if_t<WasmTypeList<Results>::valid, bool> = true>
589 auto ty = this->type(cx);
590 if (!WasmTypeList<Params>::matches(ty->params()) ||
591 !WasmTypeList<Results>::matches(ty->results())) {
592 return Trap("static type for this function does not match actual type");
593 }
595 return ret;
596 }
597
599 const wasmtime_func_t &raw_func() const { return func; }
600};
601
606template <typename Params, typename Results> class TypedFunc {
607 friend class Func;
608 Func f;
609 TypedFunc(Func func) : f(func) {}
610
611public:
622 TrapResult<Results> call(Store::Context cx, Params params) const {
623 std::array<wasmtime_val_raw_t, std::max(WasmTypeList<Params>::size,
624 WasmTypeList<Results>::size)>
625 storage;
626 wasmtime_val_raw_t *ptr = storage.data();
627 if (ptr == nullptr)
628 ptr = reinterpret_cast<wasmtime_val_raw_t*>(alignof(wasmtime_val_raw_t));
629 WasmTypeList<Params>::store(cx, ptr, params);
630 wasm_trap_t *trap = nullptr;
631 auto *error = wasmtime_func_call_unchecked(
632 cx.raw_context(), &f.func, ptr, storage.size(), &trap);
633 if (error != nullptr) {
634 return TrapError(Error(error));
635 }
636 if (trap != nullptr) {
637 return TrapError(Trap(trap));
638 }
639 return WasmTypeList<Results>::load(cx, ptr);
640 }
641
643 const Func &func() const { return f; }
644};
645
646inline Val::Val(std::optional<Func> func) : val{} {
648 if (func) {
649 val.of.funcref = (*func).func;
650 } else {
651 wasmtime_funcref_set_null(&val.of.funcref);
652 }
653}
654
655inline Val::Val(Func func) : Val(std::optional(func)) {}
656inline Val::Val(ExternRef ptr) : Val(std::optional(ptr)) {}
657inline Val::Val(AnyRef ptr) : Val(std::optional(ptr)) {}
658
659inline std::optional<Func> Val::funcref() const {
660 if (val.kind != WASMTIME_FUNCREF) {
661 std::abort();
662 }
663 if (val.of.funcref.store_id == 0) {
664 return std::nullopt;
665 }
666 return Func(val.of.funcref);
667}
668
670template <> struct detail::WasmType<std::optional<Func>> {
672 static const bool valid = true;
674 static const ValKind kind = ValKind::FuncRef;
676 static void store(Store::Context cx, wasmtime_val_raw_t *p,
677 const std::optional<Func> func) {
678 if (func) {
679 p->funcref = wasmtime_func_to_raw(cx.raw_context(), &func->raw_func());
680 } else {
681 p->funcref = 0;
682 }
683 }
685 static std::optional<Func> load(Store::Context cx, wasmtime_val_raw_t *p) {
686 if (p->funcref == 0) {
687 return std::nullopt;
688 }
689 wasmtime_func_t ret;
690 wasmtime_func_from_raw(cx.raw_context(), p->funcref, &ret);
691 return ret;
692 }
693};
694
707class Global {
708 friend class Instance;
709 wasmtime_global_t global;
710
711public:
713 Global(wasmtime_global_t global) : global(global) {}
714
725 const Val &init) {
726 wasmtime_global_t global;
727 auto *error = wasmtime_global_new(cx.ptr, ty.ptr.get(), &init.val, &global);
728 if (error != nullptr) {
729 return Error(error);
730 }
731 return Global(global);
732 }
733
736 return wasmtime_global_type(cx.ptr, &global);
737 }
738
740 Val get(Store::Context cx) const;
741
746 auto *error = wasmtime_global_set(cx.ptr, &global, &val.val);
747 if (error != nullptr) {
748 return Error(error);
749 }
750 return std::monostate();
751 }
752};
753
766class Table {
767 friend class Instance;
768 wasmtime_table_t table;
769
770public:
772 Table(wasmtime_table_t table) : table(table) {}
773
784 const Val &init) {
785 wasmtime_table_t table;
786 auto *error = wasmtime_table_new(cx.ptr, ty.ptr.get(), &init.val, &table);
787 if (error != nullptr) {
788 return Error(error);
789 }
790 return Table(table);
791 }
792
795 return wasmtime_table_type(cx.ptr, &table);
796 }
797
799 uint64_t size(Store::Context cx) const {
800 return wasmtime_table_size(cx.ptr, &table);
801 }
802
806 std::optional<Val> get(Store::Context cx, uint64_t idx) const {
807 Val val;
808 if (wasmtime_table_get(cx.ptr, &table, idx, &val.val)) {
809 return val;
810 }
811 return std::nullopt;
812 }
813
818 const Val &val) const {
819 auto *error = wasmtime_table_set(cx.ptr, &table, idx, &val.val);
820 if (error != nullptr) {
821 return Error(error);
822 }
823 return std::monostate();
824 }
825
835 const Val &init) const {
836 uint64_t prev = 0;
837 auto *error = wasmtime_table_grow(cx.ptr, &table, delta, &init.val, &prev);
838 if (error != nullptr) {
839 return Error(error);
840 }
841 return prev;
842 }
843};
844
845// gcc 8.3.0 seems to require that this comes after the definition of `Table`. I
846// don't know why...
848 Val val;
849 wasmtime_global_get(cx.ptr, &global, &val.val);
850 return val;
851}
852
864class Memory {
865 friend class Instance;
866 wasmtime_memory_t memory;
867
868public:
870 Memory(wasmtime_memory_t memory) : memory(memory) {}
871
874 wasmtime_memory_t memory;
875 auto *error = wasmtime_memory_new(cx.ptr, ty.ptr.get(), &memory);
876 if (error != nullptr) {
877 return Error(error);
878 }
879 return Memory(memory);
880 }
881
884 return wasmtime_memory_type(cx.ptr, &memory);
885 }
886
888 uint64_t size(Store::Context cx) const {
889 return wasmtime_memory_size(cx.ptr, &memory);
890 }
891
898 auto *base = wasmtime_memory_data(cx.ptr, &memory);
899 auto size = wasmtime_memory_data_size(cx.ptr, &memory);
900 return {base, size};
901 }
902
907 Result<uint64_t> grow(Store::Context cx, uint64_t delta) const {
908 uint64_t prev = 0;
909 auto *error = wasmtime_memory_grow(cx.ptr, &memory, delta, &prev);
910 if (error != nullptr) {
911 return Error(error);
912 }
913 return prev;
914 }
915};
916
929class Instance {
930 friend class Linker;
931 friend class Caller;
932
933 wasmtime_instance_t instance;
934
935 static Extern cvt(wasmtime_extern_t &e) {
936 switch (e.kind) {
938 return Func(e.of.func);
940 return Global(e.of.global);
942 return Memory(e.of.memory);
944 return Table(e.of.table);
945 }
946 std::abort();
947 }
948
949 static void cvt(const Extern &e, wasmtime_extern_t &raw) {
950 if (const auto *func = std::get_if<Func>(&e)) {
952 raw.of.func = func->func;
953 } else if (const auto *global = std::get_if<Global>(&e)) {
955 raw.of.global = global->global;
956 } else if (const auto *table = std::get_if<Table>(&e)) {
958 raw.of.table = table->table;
959 } else if (const auto *memory = std::get_if<Memory>(&e)) {
961 raw.of.memory = memory->memory;
962 } else {
963 std::abort();
964 }
965 }
966
967public:
969 Instance(wasmtime_instance_t instance) : instance(instance) {}
970
988 const std::vector<Extern> &imports) {
989 std::vector<wasmtime_extern_t> raw_imports;
990 for (const auto &item : imports) {
991 raw_imports.push_back(wasmtime_extern_t{});
992 auto &last = raw_imports.back();
993 Instance::cvt(item, last);
994 }
995 wasmtime_instance_t instance;
996 wasm_trap_t *trap = nullptr;
997 auto *error = wasmtime_instance_new(cx.ptr, m.ptr.get(), raw_imports.data(),
998 raw_imports.size(), &instance, &trap);
999 if (error != nullptr) {
1000 return TrapError(Error(error));
1001 }
1002 if (trap != nullptr) {
1003 return TrapError(Trap(trap));
1004 }
1005 return Instance(instance);
1006 }
1007
1014 std::optional<Extern> get(Store::Context cx, std::string_view name) {
1016 if (!wasmtime_instance_export_get(cx.ptr, &instance, name.data(),
1017 name.size(), &e)) {
1018 return std::nullopt;
1019 }
1020 return Instance::cvt(e);
1021 }
1022
1029 std::optional<std::pair<std::string_view, Extern>> get(Store::Context cx,
1030 size_t idx) {
1032 // I'm not sure why clang-tidy thinks this is using va_list or anything
1033 // related to that...
1034 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
1035 char *name = nullptr;
1036 size_t len = 0;
1037 if (!wasmtime_instance_export_nth(cx.ptr, &instance, idx, &name, &len,
1038 &e)) {
1039 return std::nullopt;
1040 }
1041 std::string_view n(name, len);
1042 return std::pair(n, Instance::cvt(e));
1043 }
1044};
1045
1046inline std::optional<Extern> Caller::get_export(std::string_view name) {
1047 wasmtime_extern_t item;
1048 if (wasmtime_caller_export_get(ptr, name.data(), name.size(), &item)) {
1049 return Instance::cvt(item);
1050 }
1051 return std::nullopt;
1052}
1053
1061class Linker {
1062 struct deleter {
1063 void operator()(wasmtime_linker_t *p) const { wasmtime_linker_delete(p); }
1064 };
1065
1066 std::unique_ptr<wasmtime_linker_t, deleter> ptr;
1067
1068public:
1070 explicit Linker(Engine &engine)
1071 : ptr(wasmtime_linker_new(engine.ptr.get())) {}
1072
1076 void allow_shadowing(bool allow) {
1077 wasmtime_linker_allow_shadowing(ptr.get(), allow);
1078 }
1079
1082 std::string_view name, const Extern &item) {
1084 Instance::cvt(item, raw);
1085 auto *error =
1086 wasmtime_linker_define(ptr.get(), cx.ptr, module.data(), module.size(),
1087 name.data(), name.size(), &raw);
1088 if (error != nullptr) {
1089 return Error(error);
1090 }
1091 return std::monostate();
1092 }
1093
1099 auto *error = wasmtime_linker_define_wasi(ptr.get());
1100 if (error != nullptr) {
1101 return Error(error);
1102 }
1103 return std::monostate();
1104 }
1105
1109 define_instance(Store::Context cx, std::string_view name, Instance instance) {
1110 auto *error = wasmtime_linker_define_instance(
1111 ptr.get(), cx.ptr, name.data(), name.size(), &instance.instance);
1112 if (error != nullptr) {
1113 return Error(error);
1114 }
1115 return std::monostate();
1116 }
1117
1121 wasmtime_instance_t instance;
1122 wasm_trap_t *trap = nullptr;
1123 auto *error = wasmtime_linker_instantiate(ptr.get(), cx.ptr, m.ptr.get(),
1124 &instance, &trap);
1125 if (error != nullptr) {
1126 return TrapError(Error(error));
1127 }
1128 if (trap != nullptr) {
1129 return TrapError(Trap(trap));
1130 }
1131 return Instance(instance);
1132 }
1133
1137 const Module &m) {
1138 auto *error = wasmtime_linker_module(ptr.get(), cx.ptr, name.data(),
1139 name.size(), m.ptr.get());
1140 if (error != nullptr) {
1141 return Error(error);
1142 }
1143 return std::monostate();
1144 }
1145
1148 [[nodiscard]] std::optional<Extern>
1149 get(Store::Context cx, std::string_view module, std::string_view name) {
1150 wasmtime_extern_t item;
1151 if (wasmtime_linker_get(ptr.get(), cx.ptr, module.data(), module.size(),
1152 name.data(), name.size(), &item)) {
1153 return Instance::cvt(item);
1154 }
1155 return std::nullopt;
1156 }
1157
1160 template <typename F,
1161 std::enable_if_t<
1162 std::is_invocable_r_v<Result<std::monostate, Trap>, F, Caller,
1164 bool> = true>
1166 std::string_view name, const FuncType &ty,
1167 F&& f) {
1168
1169 auto *error = wasmtime_linker_define_func(
1170 ptr.get(), module.data(), module.length(), name.data(), name.length(),
1171 ty.ptr.get(), Func::raw_callback<std::remove_reference_t<F>>, std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f)).release(),
1172 Func::raw_finalize<std::remove_reference_t<F>>);
1173
1174 if (error != nullptr) {
1175 return Error(error);
1176 }
1177
1178 return std::monostate();
1179 }
1180
1183 template <typename F,
1184 std::enable_if_t<WasmHostFunc<F>::Params::valid, bool> = true,
1185 std::enable_if_t<WasmHostFunc<F>::Results::valid, bool> = true>
1187 std::string_view name, F&& f) {
1188 using HostFunc = WasmHostFunc<F>;
1189 auto params = HostFunc::Params::types();
1190 auto results = HostFunc::Results::types();
1191 auto ty = FuncType::from_iters(params, results);
1193 ptr.get(), module.data(), module.length(), name.data(), name.length(),
1194 ty.ptr.get(), Func::raw_callback_unchecked<std::remove_reference_t<F>>,
1195 std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f)).release(), Func::raw_finalize<std::remove_reference_t<F>>);
1196
1197 if (error != nullptr) {
1198 return Error(error);
1199 }
1200
1201 return std::monostate();
1202 }
1203
1206 Result<Func> get_default(Store::Context cx, std::string_view name) {
1207 wasmtime_func_t item;
1208 auto *error = wasmtime_linker_get_default(ptr.get(), cx.ptr, name.data(),
1209 name.size(), &item);
1210 if (error != nullptr) {
1211 return Error(error);
1212 }
1213 return Func(item);
1214 }
1215};
1216
1217} // namespace wasmtime
1218
1219#endif // WASMTIME_HH
Representation of a WebAssembly anyref value.
Definition: val.hh:82
Structure provided to host functions to lookup caller information or acquire a Store::Context.
Definition: wasmtime.hh:78
std::optional< Extern > get_export(std::string_view name)
Definition: wasmtime.hh:1046
Store::Context context()
Explicitly acquire a Store::Context from this Caller.
Definition: wasmtime.hh:92
Global compilation state in Wasmtime.
Definition: engine.hh:21
Errors coming from Wasmtime.
Definition: error.hh:24
Representation of a WebAssembly externref value.
Definition: val.hh:28
Type information for a WebAssembly function.
Definition: 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: func.hh:75
Representation of a WebAssembly function.
Definition: wasmtime.hh:347
TrapResult< std::vector< Val > > call(Store::Context cx, const I &begin, const I &end) const
Invoke a WebAssembly function.
Definition: wasmtime.hh:512
Func(wasmtime_func_t func)
Creates a new function from the raw underlying C API representation.
Definition: wasmtime.hh:395
FuncType type(Store::Context cx) const
Returns the type of this function.
Definition: wasmtime.hh:564
const wasmtime_func_t & raw_func() const
Returns the raw underlying C API function this is using.
Definition: wasmtime.hh:599
TrapResult< std::vector< Val > > call(Store::Context cx, const std::vector< Val > &params) const
Helper function for call(Store::Context cx, const I &begin, const I &end)
Definition: wasmtime.hh:547
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: wasmtime.hh:479
TrapResult< std::vector< Val > > call(Store::Context cx, const std::initializer_list< Val > &params) const
Helper function for call(Store::Context cx, const I &begin, const I &end)
Definition: wasmtime.hh:559
Func(Store::Context cx, const FuncType &ty, F f)
Creates a new host-defined function.
Definition: wasmtime.hh:433
Result< TypedFunc< Params, Results >, Trap > typed(Store::Context cx) const
Statically checks this function against the provided types.
Definition: wasmtime.hh:588
Type information about a WebAssembly global.
Definition: global.hh:15
A WebAssembly global.
Definition: wasmtime.hh:707
Global(wasmtime_global_t global)
Creates as global from the raw underlying C API representation.
Definition: wasmtime.hh:713
Result< std::monostate > set(Store::Context cx, const Val &val) const
Definition: wasmtime.hh:745
Val get(Store::Context cx) const
Returns the current value of this global.
Definition: wasmtime.hh:847
GlobalType type(Store::Context cx) const
Returns the type of this global.
Definition: wasmtime.hh:735
static Result< Global > create(Store::Context cx, const GlobalType &ty, const Val &init)
Create a new WebAssembly global.
Definition: wasmtime.hh:724
A WebAssembly instance.
Definition: wasmtime.hh:929
Instance(wasmtime_instance_t instance)
Creates a new instance from the raw underlying C API representation.
Definition: wasmtime.hh:969
std::optional< std::pair< std::string_view, Extern > > get(Store::Context cx, size_t idx)
Load an instance's export by index.
Definition: wasmtime.hh:1029
std::optional< Extern > get(Store::Context cx, std::string_view name)
Load an instance's export by name.
Definition: wasmtime.hh:1014
static TrapResult< Instance > create(Store::Context cx, const Module &m, const std::vector< Extern > &imports)
Instantiates the module m with the provided imports
Definition: wasmtime.hh:987
Helper class for linking modules together with name-based resolution.
Definition: wasmtime.hh:1061
Result< std::monostate > define(Store::Context cx, std::string_view module, std::string_view name, const Extern &item)
Defines the provided item into this linker with the given name.
Definition: wasmtime.hh:1081
Result< std::monostate > func_wrap(std::string_view module, std::string_view name, F &&f)
Definition: wasmtime.hh:1186
Linker(Engine &engine)
Creates a new linker which will instantiate in the given engine.
Definition: wasmtime.hh:1070
Result< std::monostate > func_new(std::string_view module, std::string_view name, const FuncType &ty, F &&f)
Definition: wasmtime.hh:1165
void allow_shadowing(bool allow)
Definition: wasmtime.hh:1076
Result< std::monostate > module(Store::Context cx, std::string_view name, const Module &m)
Definition: wasmtime.hh:1136
std::optional< Extern > get(Store::Context cx, std::string_view module, std::string_view name)
Definition: wasmtime.hh:1149
Result< Func > get_default(Store::Context cx, std::string_view name)
Definition: wasmtime.hh:1206
TrapResult< Instance > instantiate(Store::Context cx, const Module &m)
Definition: wasmtime.hh:1120
Result< std::monostate > define_instance(Store::Context cx, std::string_view name, Instance instance)
Definition: wasmtime.hh:1109
Result< std::monostate > define_wasi()
Definition: wasmtime.hh:1098
Type information about a WebAssembly linear memory.
Definition: memory.hh:18
A WebAssembly linear memory.
Definition: wasmtime.hh:864
Memory(wasmtime_memory_t memory)
Creates a new memory from the raw underlying C API representation.
Definition: wasmtime.hh:870
static Result< Memory > create(Store::Context cx, const MemoryType &ty)
Creates a new host-defined memory with the type specified.
Definition: wasmtime.hh:873
Span< uint8_t > data(Store::Context cx) const
Definition: wasmtime.hh:897
MemoryType type(Store::Context cx) const
Returns the type of this memory.
Definition: wasmtime.hh:883
uint64_t size(Store::Context cx) const
Returns the size, in WebAssembly pages, of this memory.
Definition: wasmtime.hh:888
Result< uint64_t > grow(Store::Context cx, uint64_t delta) const
Definition: wasmtime.hh:907
Representation of a compiled WebAssembly module.
Definition: module.hh:27
Fallible result type used for Wasmtime.
Definition: error.hh:83
E && err()
Returns the error, if present, aborts if this is not an error.
Definition: error.hh:97
Span class used when c++20 is not available.
Definition: span.hh:45
An interior pointer into a Store.
Definition: store.hh:60
wasmtime_context_t * raw_context()
Returns the raw context pointer for the C API.
Definition: store.hh:153
Owner of all WebAssembly objects.
Definition: store.hh:33
Type information about a WebAssembly table.
Definition: table.hh:16
A WebAssembly table.
Definition: wasmtime.hh:766
Table(wasmtime_table_t table)
Creates a new table from the raw underlying C API representation.
Definition: wasmtime.hh:772
Result< std::monostate > set(Store::Context cx, uint64_t idx, const Val &val) const
Definition: wasmtime.hh:817
static Result< Table > create(Store::Context cx, const TableType &ty, const Val &init)
Creates a new host-defined table.
Definition: wasmtime.hh:783
Result< uint64_t > grow(Store::Context cx, uint64_t delta, const Val &init) const
Definition: wasmtime.hh:834
uint64_t size(Store::Context cx) const
Returns the size, in elements, that the table currently has.
Definition: wasmtime.hh:799
TableType type(Store::Context cx) const
Returns the type of this table.
Definition: wasmtime.hh:794
std::optional< Val > get(Store::Context cx, uint64_t idx) const
Definition: wasmtime.hh:806
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: wasmtime.hh:606
const Func & func() const
Returns the underlying un-typed Func for this function.
Definition: wasmtime.hh:643
TrapResult< Results > call(Store::Context cx, Params params) const
Calls this function with the provided parameters.
Definition: wasmtime.hh:622
Representation of a generic WebAssembly value.
Definition: val.hh:160
std::optional< Func > funcref() const
Definition: wasmtime.hh:659
#define WASMTIME_EXTERN_TABLE
Value of wasmtime_extern_kind_t meaning that wasmtime_extern_t is a table.
Definition: extern.h:89
#define WASMTIME_EXTERN_GLOBAL
Value of wasmtime_extern_kind_t meaning that wasmtime_extern_t is a global.
Definition: extern.h:86
#define WASMTIME_EXTERN_FUNC
Value of wasmtime_extern_kind_t meaning that wasmtime_extern_t is a function.
Definition: extern.h:83
#define WASMTIME_EXTERN_MEMORY
Value of wasmtime_extern_kind_t meaning that wasmtime_extern_t is a memory.
Definition: extern.h:92
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.
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.
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...
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.
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.
wasmtime_context_t * wasmtime_caller_context(wasmtime_caller_t *caller)
Returns the store context of the caller object.
bool wasmtime_caller_export_get(wasmtime_caller_t *caller, const char *name, size_t name_len, wasmtime_extern_t *item)
Loads a wasmtime_extern_t from the caller's context.
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_functype_t * wasmtime_func_type(const wasmtime_context_t *store, const wasmtime_func_t *func)
Returns the type of the function specified.
wasmtime_error_t * wasmtime_global_new(wasmtime_context_t *store, const wasm_globaltype_t *type, const wasmtime_val_t *val, wasmtime_global_t *ret)
Creates a new global value.
wasmtime_error_t * wasmtime_global_set(wasmtime_context_t *store, const wasmtime_global_t *global, const wasmtime_val_t *val)
Sets a global to a new value.
wasm_globaltype_t * wasmtime_global_type(const wasmtime_context_t *store, const wasmtime_global_t *global)
Returns the wasm type of the specified global.
void wasmtime_global_get(wasmtime_context_t *store, const wasmtime_global_t *global, wasmtime_val_t *out)
Get the value of the specified global.
bool wasmtime_instance_export_get(wasmtime_context_t *store, const wasmtime_instance_t *instance, const char *name, size_t name_len, wasmtime_extern_t *item)
Get an export by name from an instance.
bool wasmtime_instance_export_nth(wasmtime_context_t *store, const wasmtime_instance_t *instance, size_t index, char **name, size_t *name_len, wasmtime_extern_t *item)
Get an export by index from an instance.
wasmtime_error_t * wasmtime_instance_new(wasmtime_context_t *store, const wasmtime_module_t *module, const wasmtime_extern_t *imports, size_t nimports, wasmtime_instance_t *instance, wasm_trap_t **trap)
Instantiate a wasm module.
wasmtime_linker_t * wasmtime_linker_new(wasm_engine_t *engine)
Creates a new linker for the specified engine.
bool wasmtime_linker_get(const wasmtime_linker_t *linker, wasmtime_context_t *store, const char *module, size_t module_len, const char *name, size_t name_len, wasmtime_extern_t *item)
Loads an item by name from this linker.
wasmtime_error_t * wasmtime_linker_define_func_unchecked(wasmtime_linker_t *linker, const char *module, size_t module_len, const char *name, size_t name_len, const wasm_functype_t *ty, wasmtime_func_unchecked_callback_t cb, void *data, void(*finalizer)(void *))
Defines a new function in this linker.
wasmtime_error_t * wasmtime_linker_get_default(const wasmtime_linker_t *linker, wasmtime_context_t *store, const char *name, size_t name_len, wasmtime_func_t *func)
Acquires the "default export" of the named module in this linker.
wasmtime_error_t * wasmtime_linker_define_wasi(wasmtime_linker_t *linker)
Defines WASI functions in this linker.
wasmtime_error_t * wasmtime_linker_define(wasmtime_linker_t *linker, wasmtime_context_t *store, const char *module, size_t module_len, const char *name, size_t name_len, const wasmtime_extern_t *item)
Defines a new item in this linker.
void wasmtime_linker_allow_shadowing(wasmtime_linker_t *linker, bool allow_shadowing)
Configures whether this linker allows later definitions to shadow previous definitions.
wasmtime_error_t * wasmtime_linker_module(wasmtime_linker_t *linker, wasmtime_context_t *store, const char *name, size_t name_len, const wasmtime_module_t *module)
Defines automatic instantiations of a wasm_module_t in this linker.
wasmtime_error_t * wasmtime_linker_define_instance(wasmtime_linker_t *linker, wasmtime_context_t *store, const char *name, size_t name_len, const wasmtime_instance_t *instance)
Defines an instance under the specified name in this linker.
void wasmtime_linker_delete(wasmtime_linker_t *linker)
Deletes a linker.
wasmtime_error_t * wasmtime_linker_define_func(wasmtime_linker_t *linker, const char *module, size_t module_len, const char *name, size_t name_len, const wasm_functype_t *ty, wasmtime_func_callback_t cb, void *data, void(*finalizer)(void *))
Defines a new function in this linker.
wasmtime_error_t * wasmtime_linker_instantiate(const wasmtime_linker_t *linker, wasmtime_context_t *store, const wasmtime_module_t *module, wasmtime_instance_t *instance, wasm_trap_t **trap)
Instantiates a wasm_module_t with the items defined in this linker.
uint8_t * wasmtime_memory_data(const wasmtime_context_t *store, const wasmtime_memory_t *memory)
Returns the base pointer in memory where the linear memory starts.
wasmtime_error_t * wasmtime_memory_grow(wasmtime_context_t *store, const wasmtime_memory_t *memory, uint64_t delta, uint64_t *prev_size)
Attempts to grow the specified memory by delta pages.
wasmtime_error_t * wasmtime_memory_new(wasmtime_context_t *store, const wasm_memorytype_t *ty, wasmtime_memory_t *ret)
Creates a new WebAssembly linear memory.
size_t wasmtime_memory_data_size(const wasmtime_context_t *store, const wasmtime_memory_t *memory)
Returns the byte length of this linear memory.
uint64_t wasmtime_memory_size(const wasmtime_context_t *store, const wasmtime_memory_t *memory)
Returns the length, in WebAssembly pages, of this linear memory.
wasm_memorytype_t * wasmtime_memory_type(const wasmtime_context_t *store, const wasmtime_memory_t *memory)
Returns the type of the memory specified.
Opaque struct representing a wasm trap.
Structure used to represent either a Trap or an Error.
Definition: trap.hh:162
Container for different kinds of extern items.
Definition: extern.h:133
wasmtime_extern_union_t of
Container for the extern item's value.
Definition: extern.h:137
wasmtime_extern_kind_t kind
Discriminant of which field of of is valid.
Definition: extern.h:135
A host-defined un-forgeable reference to pass into WebAssembly.
Definition: val.h:174
Representation of a function in Wasmtime.
Definition: extern.h:25
uint64_t store_id
Definition: extern.h:31
Representation of a global in Wasmtime.
Definition: extern.h:71
Representation of a instance in Wasmtime.
Definition: instance.h:26
Object used to conveniently link together and instantiate wasm modules.
Representation of a memory in Wasmtime.
Definition: extern.h:57
Representation of a table in Wasmtime.
Definition: extern.h:43
Container for different kinds of wasm values.
Definition: val.h:441
wasmtime_valkind_t kind
Discriminant of which field of of is valid.
Definition: val.h:443
wasmtime_valunion_t of
Container for the extern item's value.
Definition: val.h:445
wasm_tabletype_t * wasmtime_table_type(const wasmtime_context_t *store, const wasmtime_table_t *table)
Returns the type of this table.
wasmtime_error_t * wasmtime_table_set(wasmtime_context_t *store, const wasmtime_table_t *table, uint64_t index, const wasmtime_val_t *value)
Sets a value in a table.
wasmtime_error_t * wasmtime_table_new(wasmtime_context_t *store, const wasm_tabletype_t *ty, const wasmtime_val_t *init, wasmtime_table_t *table)
Creates a new host-defined wasm table.
bool wasmtime_table_get(wasmtime_context_t *store, const wasmtime_table_t *table, uint64_t index, wasmtime_val_t *val)
Gets a value in a table.
wasmtime_error_t * wasmtime_table_grow(wasmtime_context_t *store, const wasmtime_table_t *table, uint64_t delta, const wasmtime_val_t *init, uint64_t *prev_size)
Grows a table.
uint64_t wasmtime_table_size(const wasmtime_context_t *store, const wasmtime_table_t *table)
Returns the size, in elements, of the specified table.
ValKind
Different kinds of types accepted by Wasmtime.
Definition: types/val.hh:16
@ V128
WebAssembly's v128 type from the simd proposal.
wasmtime_memory_t memory
Field used if wasmtime_extern_t::kind is WASMTIME_EXTERN_MEMORY.
Definition: extern.h:115
wasmtime_func_t func
Field used if wasmtime_extern_t::kind is WASMTIME_EXTERN_FUNC.
Definition: extern.h:109
wasmtime_global_t global
Field used if wasmtime_extern_t::kind is WASMTIME_EXTERN_GLOBAL.
Definition: extern.h:111
wasmtime_table_t table
Field used if wasmtime_extern_t::kind is WASMTIME_EXTERN_TABLE.
Definition: extern.h:113
Container for possible wasm values.
Definition: val.h:372
uint32_t externref
Definition: val.h:408
wasmtime_v128 v128
Definition: val.h:392
void * funcref
Definition: val.h:415
wasmtime_func_t funcref
Definition: val.h:336
uint32_t wasmtime_externref_to_raw(wasmtime_context_t *context, const wasmtime_externref_t *ref)
Converts a wasmtime_externref_t to a raw value suitable for storing into a wasmtime_val_raw_t.
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:307
void wasmtime_externref_from_raw(wasmtime_context_t *context, uint32_t raw, wasmtime_externref_t *out)
Converts a raw externref value coming from wasmtime_val_raw_t into a wasmtime_externref_t.
#define WASMTIME_FUNCREF
Value of wasmtime_valkind_t meaning that wasmtime_val_t is a funcref.
Definition: val.h:297
Wasmtime's C API.
#define NATIVE_WASM_TYPE(native, valkind, field)
Definition: wasmtime.hh:108
std::variant< Func, Global, Memory, Table > Extern
Representation of an external WebAssembly item.
Definition: wasmtime.hh:67