Skip to content

Commit f960e9a

Browse files
authored
Add support for structref to the C and C++ APIs (#12915)
* Add support for `structref` to the C and C++ APIs Also requires adding support for struct and field types, as well as `StructRefPre`. * review feedback and rebase * fix doc build * really fix doc build * fix more docs
1 parent 4d4e903 commit f960e9a

5 files changed

Lines changed: 689 additions & 1 deletion

File tree

crates/c-api/include/wasmtime/gc.h

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,222 @@ WASM_API_EXTERN bool wasmtime_eqref_i31_get_s(wasmtime_context_t *context,
126126
const wasmtime_eqref_t *eqref,
127127
int32_t *dst);
128128

129+
// ============================================================================
130+
// StructRef
131+
// ============================================================================
132+
133+
/**
134+
* \brief Discriminant for storage types in struct/array field types.
135+
*
136+
* Extends #wasmtime_valkind_t with packed storage types
137+
* #WASMTIME_STORAGE_KIND_I8 and #WASMTIME_STORAGE_KIND_I16.
138+
*/
139+
typedef uint8_t wasmtime_storage_kind_t;
140+
141+
/// \brief An 8-bit packed integer (only valid inside struct/array fields).
142+
#define WASMTIME_STORAGE_KIND_I8 9
143+
/// \brief A 16-bit packed integer (only valid inside struct/array fields).
144+
#define WASMTIME_STORAGE_KIND_I16 10
145+
146+
/**
147+
* \typedef wasmtime_field_type_t
148+
* \brief Convenience alias for #wasmtime_field_type
149+
*
150+
* \struct wasmtime_field_type
151+
* \brief Describes the type and mutability of a struct field or array element.
152+
*/
153+
typedef struct wasmtime_field_type {
154+
/// The storage type of this field. Use #WASMTIME_I32, #WASMTIME_I64,
155+
/// #WASMTIME_F32, etc. for value types, or #WASMTIME_STORAGE_KIND_I8 /
156+
/// #WASMTIME_STORAGE_KIND_I16 for packed types.
157+
wasmtime_storage_kind_t kind;
158+
/// Whether this field is mutable. `true` for mutable, `false` for
159+
/// immutable.
160+
bool mutable_;
161+
} wasmtime_field_type_t;
162+
163+
/**
164+
* \brief An opaque handle to a WebAssembly struct type definition.
165+
*
166+
* A struct type describes the fields of a struct. It is used to create a
167+
* #wasmtime_struct_ref_pre_t, which can then allocate struct instances.
168+
*
169+
* Owned. Must be deleted with #wasmtime_struct_type_delete.
170+
*/
171+
typedef struct wasmtime_struct_type wasmtime_struct_type_t;
172+
173+
/**
174+
* \brief Create a new struct type.
175+
*
176+
* \param engine The engine to register the type with.
177+
* \param fields Pointer to an array of field type descriptors.
178+
* \param nfields Number of fields.
179+
*
180+
* \return Returns a new struct type, or NULL on error (e.g. invalid field
181+
* types).
182+
*/
183+
WASM_API_EXTERN wasmtime_struct_type_t *
184+
wasmtime_struct_type_new(const wasm_engine_t *engine,
185+
const wasmtime_field_type_t *fields, size_t nfields);
186+
187+
/**
188+
* \brief Delete a struct type.
189+
*/
190+
WASM_API_EXTERN void wasmtime_struct_type_delete(wasmtime_struct_type_t *ty);
191+
192+
/**
193+
* \brief An opaque, pre-allocated, and registered struct layout for faster
194+
* allocation.
195+
*
196+
* Created from a #wasmtime_struct_type_t and a store context. Reusable for
197+
* allocating many struct instances of the same type.
198+
*
199+
* Owned. Must be deleted with #wasmtime_struct_ref_pre_delete.
200+
*/
201+
typedef struct wasmtime_struct_ref_pre wasmtime_struct_ref_pre_t;
202+
203+
/**
204+
* \brief Create a new struct pre-allocator.
205+
*
206+
* \param context The store context.
207+
* \param ty The struct type.
208+
*
209+
* \return Returns a new struct ref pre-allocator.
210+
*/
211+
WASM_API_EXTERN wasmtime_struct_ref_pre_t *
212+
wasmtime_struct_ref_pre_new(wasmtime_context_t *context,
213+
const wasmtime_struct_type_t *ty);
214+
215+
/**
216+
* \brief Delete a struct pre-allocator.
217+
*/
218+
WASM_API_EXTERN void
219+
wasmtime_struct_ref_pre_delete(wasmtime_struct_ref_pre_t *pre);
220+
221+
/**
222+
* \typedef wasmtime_structref_t
223+
* \brief Convenience alias for #wasmtime_structref
224+
*
225+
* \struct wasmtime_structref
226+
* \brief A WebAssembly `structref` value.
227+
*
228+
* This structure represents a reference to a GC struct. It is a subtype of
229+
* `eqref` and `anyref`.
230+
*
231+
* Values must be explicitly unrooted via #wasmtime_structref_unroot.
232+
*/
233+
typedef struct wasmtime_structref {
234+
/// Internal metadata.
235+
uint64_t store_id;
236+
/// Internal to Wasmtime.
237+
uint32_t __private1;
238+
/// Internal to Wasmtime.
239+
uint32_t __private2;
240+
/// Internal to Wasmtime.
241+
void *__private3;
242+
} wasmtime_structref_t;
243+
244+
/// \brief Initialize the `ref` to a null `structref` value.
245+
static inline void wasmtime_structref_set_null(wasmtime_structref_t *ref) {
246+
ref->store_id = 0;
247+
}
248+
249+
/// \brief Returns whether the provided `ref` is a null `structref` value.
250+
static inline bool wasmtime_structref_is_null(const wasmtime_structref_t *ref) {
251+
return ref->store_id == 0;
252+
}
253+
254+
/**
255+
* \brief Allocate a new struct instance.
256+
*
257+
* \param context The store context.
258+
* \param pre The struct pre-allocator.
259+
* \param fields Pointer to array of field values (#wasmtime_val_t).
260+
* \param nfields Number of fields (must match the struct type).
261+
* \param out Receives the new structref on success.
262+
*
263+
* \return NULL on success, or a #wasmtime_error_t on failure.
264+
*/
265+
WASM_API_EXTERN wasmtime_error_t *wasmtime_structref_new(
266+
wasmtime_context_t *context, const wasmtime_struct_ref_pre_t *pre,
267+
const wasmtime_val_t *fields, size_t nfields, wasmtime_structref_t *out);
268+
269+
/**
270+
* \brief Clone a `structref`, creating a new root.
271+
*/
272+
WASM_API_EXTERN void
273+
wasmtime_structref_clone(const wasmtime_structref_t *structref,
274+
wasmtime_structref_t *out);
275+
276+
/**
277+
* \brief Unroot a `structref` to allow garbage collection.
278+
*/
279+
WASM_API_EXTERN void wasmtime_structref_unroot(wasmtime_structref_t *ref);
280+
281+
/**
282+
* \brief Upcast a `structref` to an `anyref`.
283+
*/
284+
WASM_API_EXTERN void
285+
wasmtime_structref_to_anyref(const wasmtime_structref_t *structref,
286+
wasmtime_anyref_t *out);
287+
288+
/**
289+
* \brief Upcast a `structref` to an `eqref`.
290+
*/
291+
WASM_API_EXTERN void
292+
wasmtime_structref_to_eqref(const wasmtime_structref_t *structref,
293+
wasmtime_eqref_t *out);
294+
295+
/**
296+
* \brief Read a field from a struct.
297+
*
298+
* \param context The store context.
299+
* \param structref The struct to read from (not consumed).
300+
* \param index The field index.
301+
* \param out Receives the field value on success.
302+
*
303+
* \return NULL on success, or a #wasmtime_error_t on failure.
304+
*/
305+
WASM_API_EXTERN wasmtime_error_t *
306+
wasmtime_structref_field(wasmtime_context_t *context,
307+
const wasmtime_structref_t *structref, size_t index,
308+
wasmtime_val_t *out);
309+
310+
/**
311+
* \brief Set a field of a struct.
312+
*
313+
* \param context The store context.
314+
* \param structref The struct to write to (not consumed).
315+
* \param index The field index.
316+
* \param val The value to write (not consumed; caller must still unroot if
317+
* applicable).
318+
*
319+
* \return NULL on success, or a #wasmtime_error_t on failure.
320+
*/
321+
WASM_API_EXTERN wasmtime_error_t *
322+
wasmtime_structref_set_field(wasmtime_context_t *context,
323+
const wasmtime_structref_t *structref,
324+
size_t index, const wasmtime_val_t *val);
325+
326+
/**
327+
* \brief Test whether an `eqref` is a `structref`.
328+
*
329+
* Returns `false` for null references.
330+
*/
331+
WASM_API_EXTERN bool wasmtime_eqref_is_struct(wasmtime_context_t *context,
332+
const wasmtime_eqref_t *eqref);
333+
334+
/**
335+
* \brief Downcast an `eqref` to a `structref`.
336+
*
337+
* If the given `eqref` is a `structref`, a new root for it is stored in `out`
338+
* and `true` is returned. Otherwise `false` is returned and `out` is set to
339+
* null.
340+
*/
341+
WASM_API_EXTERN bool wasmtime_eqref_as_struct(wasmtime_context_t *context,
342+
const wasmtime_eqref_t *eqref,
343+
wasmtime_structref_t *out);
344+
129345
#ifdef __cplusplus
130346
} // extern "C"
131347
#endif

0 commit comments

Comments
 (0)