1 /**
2  * \file wasmtime/val.h
3  *
4  * APIs for interacting with WebAssembly values in Wasmtime.
5  */
6 
7 #ifndef WASMTIME_VAL_H
8 #define WASMTIME_VAL_H
9 
10 #include <stdalign.h>
11 #include <wasm.h>
12 #include <wasmtime/extern.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 struct wasmtime_eqref;
19 /// Convenience alias for #wasmtime_eqref
20 typedef struct wasmtime_eqref wasmtime_eqref_t;
21 
22 /**
23  * \typedef wasmtime_anyref_t
24  * \brief Convenience alias for #wasmtime_anyref
25  *
26  * \struct wasmtime_anyref
27  * \brief A WebAssembly value in the `any` hierarchy of GC types.
28  *
29  * This structure represents an `anyref` that WebAssembly can create and
30  * pass back to the host. The host can also create values to pass to a guest.
31  *
32  * Note that this structure does not itself contain the data that it refers to.
33  * Instead to contains metadata to point back within a #wasmtime_context_t, so
34  * referencing the internal data requires using a `wasmtime_context_t`.
35  *
36  * Anyref values are required to be explicitly unrooted via
37  * #wasmtime_anyref_unroot to enable them to be garbage-collected.
38  *
39  * If you do not unroot the value, *even if you free the corresponding
40  * Store*, there will be some memory leaked, because GC roots use a
41  * separate allocation to track liveness.
42  *
43  * Null anyref values are represented by this structure and can be tested and
44  * created with the `wasmtime_anyref_is_null` and `wasmtime_anyref_set_null`
45  * functions.
46  */
47 typedef struct wasmtime_anyref {
48   /// Internal metadata tracking within the store, embedders should not
49   /// configure or modify these fields.
50   uint64_t store_id;
51   /// Internal to Wasmtime.
52   uint32_t __private1;
53   /// Internal to Wasmtime.
54   uint32_t __private2;
55   /// Internal to Wasmtime.
56   void *__private3;
57 } wasmtime_anyref_t;
58 
59 /// \brief Helper function to initialize the `ref` provided to a null anyref
60 /// value.
wasmtime_anyref_set_null(wasmtime_anyref_t * ref)61 static inline void wasmtime_anyref_set_null(wasmtime_anyref_t *ref) {
62   ref->store_id = 0;
63 }
64 
65 /// \brief Helper function to return whether the provided `ref` points to a null
66 /// `anyref` value.
67 ///
68 /// Note that `ref` itself should not be null as null is represented internally
69 /// within a #wasmtime_anyref_t value.
wasmtime_anyref_is_null(const wasmtime_anyref_t * ref)70 static inline bool wasmtime_anyref_is_null(const wasmtime_anyref_t *ref) {
71   return ref->store_id == 0;
72 }
73 
74 /**
75  * \brief Creates a new reference pointing to the same data that `anyref`
76  * points to (depending on the configured collector this might increase a
77  * reference count or create a new GC root).
78  *
79  * The returned reference is stored in `out`.
80  */
81 WASM_API_EXTERN void wasmtime_anyref_clone(const wasmtime_anyref_t *anyref,
82                                            wasmtime_anyref_t *out);
83 
84 /**
85  * \brief Downcast an `anyref` to an `eqyref`.
86  *
87  * Returns `true` if the downcast succeeded, and `out` is initialized. Returns
88  * `false` if the downcast failed, and `out` is left uninitialized.
89  *
90  * The original `anyref` is not consumed; `out` receives a new cloned root
91  * pointing to the same GC object as `anyref`.
92  */
93 WASM_API_EXTERN bool wasmtime_anyref_to_eqref(wasmtime_context_t *context,
94                                               const wasmtime_anyref_t *anyref,
95                                               wasmtime_eqref_t *out);
96 
97 /**
98  * \brief Unroots the `ref` provided within the `context`.
99  *
100  * This API is required to enable the `ref` value provided to be
101  * garbage-collected. This API itself does not necessarily garbage-collect the
102  * value, but it's possible to collect it in the future after this.
103  *
104  * This may modify `ref` and the contents of `ref` are left in an undefined
105  * state after this API is called and it should no longer be used.
106  *
107  * Note that null or i32 anyref values do not need to be unrooted but are still
108  * valid to pass to this function.
109  */
110 WASM_API_EXTERN void wasmtime_anyref_unroot(wasmtime_anyref_t *ref);
111 
112 /**
113  * \brief Converts a raw `anyref` value coming from #wasmtime_val_raw_t into
114  * a #wasmtime_anyref_t.
115  *
116  * The provided `out` pointer is filled in with a reference converted from
117  * `raw`.
118  */
119 WASM_API_EXTERN void wasmtime_anyref_from_raw(wasmtime_context_t *context,
120                                               uint32_t raw,
121                                               wasmtime_anyref_t *out);
122 
123 /**
124  * \brief Converts a #wasmtime_anyref_t to a raw value suitable for storing
125  * into a #wasmtime_val_raw_t.
126  *
127  * Note that the returned underlying value is not tracked by Wasmtime's garbage
128  * collector until it enters WebAssembly. This means that a GC may release the
129  * context's reference to the raw value, making the raw value invalid within the
130  * context of the store. Do not perform a GC between calling this function and
131  * passing it to WebAssembly.
132  */
133 WASM_API_EXTERN uint32_t wasmtime_anyref_to_raw(wasmtime_context_t *context,
134                                                 const wasmtime_anyref_t *ref);
135 
136 /**
137  * \brief Create a new `i31ref` value.
138  *
139  * Creates a new `i31ref` value (which is a subtype of `anyref`) and returns a
140  * pointer to it.
141  *
142  * If `i31val` does not fit in 31 bits, it is wrapped.
143  */
144 WASM_API_EXTERN void wasmtime_anyref_from_i31(wasmtime_context_t *context,
145                                               uint32_t i31val,
146                                               wasmtime_anyref_t *out);
147 
148 /**
149  * \brief Test whether an `anyref` is an `i31ref`.
150  *
151  * Returns `true` if the given `anyref` is an `i31ref`, `false` otherwise.
152  * Returns `false` for null references.
153  */
154 WASM_API_EXTERN bool wasmtime_anyref_is_i31(wasmtime_context_t *context,
155                                             const wasmtime_anyref_t *anyref);
156 
157 /**
158  * \brief Get the `anyref`'s underlying `i31ref` value, zero extended, if any.
159  *
160  * If the given `anyref` is an instance of `i31ref`, then its value is zero
161  * extended to 32 bits, written to `dst`, and `true` is returned.
162  *
163  * If the given `anyref` is not an instance of `i31ref`, then `false` is
164  * returned and `dst` is left unmodified.
165  */
166 WASM_API_EXTERN bool wasmtime_anyref_i31_get_u(wasmtime_context_t *context,
167                                                const wasmtime_anyref_t *anyref,
168                                                uint32_t *dst);
169 
170 /**
171  * \brief Get the `anyref`'s underlying `i31ref` value, sign extended, if any.
172  *
173  * If the given `anyref` is an instance of `i31ref`, then its value is sign
174  * extended to 32 bits, written to `dst`, and `true` is returned.
175  *
176  * If the given `anyref` is not an instance of `i31ref`, then `false` is
177  * returned and `dst` is left unmodified.
178  */
179 WASM_API_EXTERN bool wasmtime_anyref_i31_get_s(wasmtime_context_t *context,
180                                                const wasmtime_anyref_t *anyref,
181                                                int32_t *dst);
182 
183 /**
184  * \typedef wasmtime_externref_t
185  * \brief Convenience alias for #wasmtime_externref
186  *
187  * \struct wasmtime_externref
188  * \brief A host-defined un-forgeable reference to pass into WebAssembly.
189  *
190  * This structure represents an `externref` that can be passed to WebAssembly.
191  * It cannot be forged by WebAssembly itself and is guaranteed to have been
192  * created by the host.
193  *
194  * This structure is similar to #wasmtime_anyref_t but represents the
195  * `externref` type in WebAssembly. This can be created on the host from
196  * arbitrary host pointers/destructors. Note that this value is itself a
197  * reference into a #wasmtime_context_t and must be explicitly unrooted to
198  * enable garbage collection.
199  *
200  * Note that null is represented with this structure and created with
201  * `wasmtime_externref_set_null`. Null can be tested for with the
202  * `wasmtime_externref_is_null` function.
203  */
204 typedef struct wasmtime_externref {
205   /// Internal metadata tracking within the store, embedders should not
206   /// configure or modify these fields.
207   uint64_t store_id;
208   /// Internal to Wasmtime.
209   uint32_t __private1;
210   /// Internal to Wasmtime.
211   uint32_t __private2;
212   /// Internal to Wasmtime.
213   void *__private3;
214 } wasmtime_externref_t;
215 
216 /// \brief Helper function to initialize the `ref` provided to a null externref
217 /// value.
wasmtime_externref_set_null(wasmtime_externref_t * ref)218 static inline void wasmtime_externref_set_null(wasmtime_externref_t *ref) {
219   ref->store_id = 0;
220 }
221 
222 /// \brief Helper function to return whether the provided `ref` points to a null
223 /// `externref` value.
224 ///
225 /// Note that `ref` itself should not be null as null is represented internally
226 /// within a #wasmtime_externref_t value.
wasmtime_externref_is_null(const wasmtime_externref_t * ref)227 static inline bool wasmtime_externref_is_null(const wasmtime_externref_t *ref) {
228   return ref->store_id == 0;
229 }
230 
231 /**
232  * \brief Create a new `externref` value.
233  *
234  * Creates a new `externref` value wrapping the provided data, returning whether
235  * it was created or not.
236  *
237  * \param context the store context to allocate this externref within
238  * \param data the host-specific data to wrap
239  * \param finalizer an optional finalizer for `data`
240  * \param out where to store the created value.
241  *
242  * When the reference is reclaimed, the wrapped data is cleaned up with the
243  * provided `finalizer`.
244  *
245  * If `true` is returned then `out` has been filled in and must be unrooted
246  * in the future with #wasmtime_externref_unroot. If `false` is returned then
247  * the host wasn't able to create more GC values at this time. Performing a GC
248  * may free up enough space to try again.
249  *
250  * If you do not unroot the value, *even if you free the corresponding
251  * Store*, there will be some memory leaked, because GC roots use a
252  * separate allocation to track liveness.
253  */
254 WASM_API_EXTERN bool wasmtime_externref_new(wasmtime_context_t *context,
255                                             void *data,
256                                             void (*finalizer)(void *),
257                                             wasmtime_externref_t *out);
258 
259 /**
260  * \brief Get an `externref`'s wrapped data
261  *
262  * Returns the original `data` passed to #wasmtime_externref_new. It is required
263  * that `data` is not `NULL`.
264  */
265 WASM_API_EXTERN void *wasmtime_externref_data(wasmtime_context_t *context,
266                                               const wasmtime_externref_t *data);
267 
268 /**
269  * \brief Creates a new reference pointing to the same data that `ref` points
270  * to (depending on the configured collector this might increase a reference
271  * count or create a new GC root).
272  *
273  * The `out` parameter stores the cloned reference. This reference must
274  * eventually be unrooted with #wasmtime_externref_unroot in the future to
275  * enable GC'ing it.
276  */
277 WASM_API_EXTERN void wasmtime_externref_clone(const wasmtime_externref_t *ref,
278                                               wasmtime_externref_t *out);
279 
280 /**
281  * \brief Unroots the pointer `ref` from the `context` provided.
282  *
283  * This function will enable future garbage collection of the value pointed to
284  * by `ref` once there are no more references. The `ref` value may be mutated in
285  * place by this function and its contents are undefined after this function
286  * returns. It should not be used until after re-initializing it.
287  *
288  * Note that null externref values do not need to be unrooted but are still
289  * valid to pass to this function.
290  */
291 WASM_API_EXTERN void wasmtime_externref_unroot(wasmtime_externref_t *ref);
292 
293 /**
294  * \brief Converts a raw `externref` value coming from #wasmtime_val_raw_t into
295  * a #wasmtime_externref_t.
296  *
297  * The `out` reference is filled in with the non-raw version of this externref.
298  * It must eventually be unrooted with #wasmtime_externref_unroot.
299  */
300 WASM_API_EXTERN void wasmtime_externref_from_raw(wasmtime_context_t *context,
301                                                  uint32_t raw,
302                                                  wasmtime_externref_t *out);
303 
304 /**
305  * \brief Converts a #wasmtime_externref_t to a raw value suitable for storing
306  * into a #wasmtime_val_raw_t.
307  *
308  * Note that the returned underlying value is not tracked by Wasmtime's garbage
309  * collector until it enters WebAssembly. This means that a GC may release the
310  * context's reference to the raw value, making the raw value invalid within the
311  * context of the store. Do not perform a GC between calling this function and
312  * passing it to WebAssembly.
313  */
314 WASM_API_EXTERN uint32_t wasmtime_externref_to_raw(
315     wasmtime_context_t *context, const wasmtime_externref_t *ref);
316 
317 /**
318  * \typedef wasmtime_exnref_t
319  * \brief Convenience alias for #wasmtime_exnref
320  *
321  * \struct wasmtime_exnref
322  * \brief A WebAssembly exception reference value.
323  *
324  * This structure represents an `exnref` value, which is a reference to a
325  * WebAssembly exception object. Like other GC reference types, it must be
326  * explicitly unrooted via #wasmtime_exnref_unroot to enable garbage
327  * collection.
328  *
329  * Null exnref values are represented with `store_id == 0`.
330  */
331 typedef struct wasmtime_exnref {
332   /// Internal metadata tracking within the store, embedders should not
333   /// configure or modify these fields.
334   uint64_t store_id;
335   /// Internal to Wasmtime.
336   uint32_t __private1;
337   /// Internal to Wasmtime.
338   uint32_t __private2;
339   /// Internal to Wasmtime.
340   void *__private3;
341 } wasmtime_exnref_t;
342 
343 /// \brief Helper function to initialize the `ref` provided to a null exnref
344 /// value.
wasmtime_exnref_set_null(wasmtime_exnref_t * ref)345 static inline void wasmtime_exnref_set_null(wasmtime_exnref_t *ref) {
346   ref->store_id = 0;
347 }
348 
349 /// \brief Helper function to return whether the provided `ref` points to a null
350 /// `exnref` value.
wasmtime_exnref_is_null(const wasmtime_exnref_t * ref)351 static inline bool wasmtime_exnref_is_null(const wasmtime_exnref_t *ref) {
352   return ref->store_id == 0;
353 }
354 
355 /**
356  * \brief Creates a new reference pointing to the same exception that `ref`
357  * points to.
358  *
359  * The returned reference is stored in `out`.
360  */
361 WASM_API_EXTERN void wasmtime_exnref_clone(const wasmtime_exnref_t *ref,
362                                            wasmtime_exnref_t *out);
363 
364 /**
365  * \brief Unroots the `ref` provided, enabling future garbage collection.
366  *
367  * After this call, `ref` is left in an undefined state and should not be used.
368  */
369 WASM_API_EXTERN void wasmtime_exnref_unroot(wasmtime_exnref_t *ref);
370 
371 /// \brief Discriminant stored in #wasmtime_val::kind
372 typedef uint8_t wasmtime_valkind_t;
373 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an i32
374 #define WASMTIME_I32 0
375 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an i64
376 #define WASMTIME_I64 1
377 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a f32
378 #define WASMTIME_F32 2
379 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a f64
380 #define WASMTIME_F64 3
381 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a v128
382 #define WASMTIME_V128 4
383 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is a
384 /// funcref
385 #define WASMTIME_FUNCREF 5
386 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an
387 /// externref
388 #define WASMTIME_EXTERNREF 6
389 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an
390 /// anyref
391 #define WASMTIME_ANYREF 7
392 /// \brief Value of #wasmtime_valkind_t meaning that #wasmtime_val_t is an
393 /// exnref
394 #define WASMTIME_EXNREF 8
395 
396 /// \brief A 128-bit value representing the WebAssembly `v128` type. Bytes are
397 /// stored in little-endian order.
398 typedef uint8_t wasmtime_v128[16];
399 
400 /**
401  * \typedef wasmtime_valunion_t
402  * \brief Convenience alias for #wasmtime_valunion
403  *
404  * \union wasmtime_valunion
405  * \brief Container for different kinds of wasm values.
406  *
407  * This type is contained in #wasmtime_val_t and contains the payload for the
408  * various kinds of items a value can be.
409  */
410 typedef union wasmtime_valunion {
411   /// Field used if #wasmtime_val_t::kind is #WASMTIME_I32
412   int32_t i32;
413   /// Field used if #wasmtime_val_t::kind is #WASMTIME_I64
414   int64_t i64;
415   /// Field used if #wasmtime_val_t::kind is #WASMTIME_F32
416   float32_t f32;
417   /// Field used if #wasmtime_val_t::kind is #WASMTIME_F64
418   float64_t f64;
419   /// Field used if #wasmtime_val_t::kind is #WASMTIME_ANYREF
420   wasmtime_anyref_t anyref;
421   /// Field used if #wasmtime_val_t::kind is #WASMTIME_EXTERNREF
422   wasmtime_externref_t externref;
423   /// Field used if #wasmtime_val_t::kind is #WASMTIME_EXNREF
424   wasmtime_exnref_t exnref;
425   /// Field used if #wasmtime_val_t::kind is #WASMTIME_FUNCREF
426   ///
427   /// Use `wasmtime_funcref_is_null` to test whether this is a null function
428   /// reference.
429   wasmtime_func_t funcref;
430   /// Field used if #wasmtime_val_t::kind is #WASMTIME_V128
431   wasmtime_v128 v128;
432 } wasmtime_valunion_t;
433 
434 /// \brief Initialize a `wasmtime_func_t` value as a null function reference.
435 ///
436 /// This function will initialize the `func` provided to be a null function
437 /// reference. Used in conjunction with #wasmtime_val_t and
438 /// #wasmtime_valunion_t.
wasmtime_funcref_set_null(wasmtime_func_t * func)439 static inline void wasmtime_funcref_set_null(wasmtime_func_t *func) {
440   func->store_id = 0;
441 }
442 
443 /// \brief Helper function to test whether the `func` provided is a null
444 /// function reference.
445 ///
446 /// This function is used with #wasmtime_val_t and #wasmtime_valunion_t and its
447 /// `funcref` field. This will test whether the field represents a null funcref.
wasmtime_funcref_is_null(const wasmtime_func_t * func)448 static inline bool wasmtime_funcref_is_null(const wasmtime_func_t *func) {
449   return func->store_id == 0;
450 }
451 
452 /**
453  * \typedef wasmtime_val_raw_t
454  * \brief Convenience alias for #wasmtime_val_raw
455  *
456  * \union wasmtime_val_raw
457  * \brief Container for possible wasm values.
458  *
459  * This type is used on conjunction with #wasmtime_func_new_unchecked as well
460  * as #wasmtime_func_call_unchecked. Instances of this type do not have type
461  * information associated with them, it's up to the embedder to figure out
462  * how to interpret the bits contained within, often using some other channel
463  * to determine the type.
464  */
465 typedef union wasmtime_val_raw {
466   /// Field for when this val is a WebAssembly `i32` value.
467   ///
468   /// Note that this field is always stored in a little-endian format.
469   int32_t i32;
470   /// Field for when this val is a WebAssembly `i64` value.
471   ///
472   /// Note that this field is always stored in a little-endian format.
473   int64_t i64;
474   /// Field for when this val is a WebAssembly `f32` value.
475   ///
476   /// Note that this field is always stored in a little-endian format.
477   float32_t f32;
478   /// Field for when this val is a WebAssembly `f64` value.
479   ///
480   /// Note that this field is always stored in a little-endian format.
481   float64_t f64;
482   /// Field for when this val is a WebAssembly `v128` value.
483   ///
484   /// Note that this field is always stored in a little-endian format.
485   wasmtime_v128 v128;
486   /// Field for when this val is a WebAssembly `anyref` value.
487   ///
488   /// If this is set to 0 then it's a null anyref, otherwise this must be
489   /// passed to `wasmtime_anyref_from_raw` to determine the
490   /// `wasmtime_anyref_t`.
491   ///
492   /// Note that this field is always stored in a little-endian format.
493   uint32_t anyref;
494   /// Field for when this val is a WebAssembly `externref` value.
495   ///
496   /// If this is set to 0 then it's a null externref, otherwise this must be
497   /// passed to `wasmtime_externref_from_raw` to determine the
498   /// `wasmtime_externref_t`.
499   ///
500   /// Note that this field is always stored in a little-endian format.
501   uint32_t externref;
502   /// Field for when this val is a WebAssembly `funcref` value.
503   ///
504   /// If this is set to 0 then it's a null funcref, otherwise this must be
505   /// passed to `wasmtime_func_from_raw` to determine the `wasmtime_func_t`.
506   ///
507   /// Note that this field is always stored in a little-endian format.
508   void *funcref;
509 } wasmtime_val_raw_t;
510 
511 // Assert that the shape of this type is as expected since it needs to match
512 // Rust.
__wasmtime_val_assertions()513 static inline void __wasmtime_val_assertions() {
514   static_assert(sizeof(wasmtime_valunion_t) >= 16 &&
515                     sizeof(wasmtime_valunion_t) <= 24,
516                 "should be 16 bytes plus a pointer large (plus alignment on "
517                 "some platforms)");
518   static_assert(__alignof(wasmtime_valunion_t) == 8,
519                 "should be 8-byte aligned");
520   static_assert(sizeof(wasmtime_val_raw_t) == 16, "should be 16 bytes large");
521   static_assert(__alignof(wasmtime_val_raw_t) == 8, "should be 8-byte aligned");
522 }
523 
524 /**
525  * \typedef wasmtime_val_t
526  * \brief Convenience alias for #wasmtime_val_t
527  *
528  * \union wasmtime_val
529  * \brief Container for different kinds of wasm values.
530  *
531  * Note that this structure may contain an owned value, namely rooted GC
532  * references, depending on the context in which this is used. APIs which
533  * consume a #wasmtime_val_t do not take ownership, but APIs that return
534  * #wasmtime_val_t require that #wasmtime_val_unroot is called to clean up
535  * any possible GC roots in the value.
536  *
537  * If you do not unroot the value, *even if you free the corresponding
538  * Store*, there will be some memory leaked, because GC roots use a
539  * separate allocation to track liveness.
540  */
541 typedef struct wasmtime_val {
542   /// Discriminant of which field of #of is valid.
543   wasmtime_valkind_t kind;
544   /// Container for the extern item's value.
545   wasmtime_valunion_t of;
546 } wasmtime_val_t;
547 
548 /**
549  * \brief Unroot the value contained by `val`.
550  *
551  * This function will unroot any GC references that `val` points to, for
552  * example if it has the `WASMTIME_EXTERNREF`, `WASMTIME_ANYREF`, or
553  * `WASMTIME_EXNREF` kinds. This
554  * function leaves `val` in an undefined state and it should not be used again
555  * without re-initializing.
556  *
557  * This method does not need to be called for integers, floats, v128, or
558  * funcref values.
559  */
560 WASM_API_EXTERN void wasmtime_val_unroot(wasmtime_val_t *val);
561 
562 /**
563  * \brief Clones the value pointed to by `src` into the `dst` provided.
564  *
565  * This function will clone any rooted GC values in `src` and have them
566  * newly rooted inside of `dst`. When using this API the `dst` should be
567  * later unrooted with #wasmtime_val_unroot if it contains GC values.
568  */
569 WASM_API_EXTERN void wasmtime_val_clone(const wasmtime_val_t *src,
570                                         wasmtime_val_t *dst);
571 
572 #ifdef __cplusplus
573 } // extern "C"
574 #endif
575 
576 #endif // WASMTIME_VAL_H
577