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