Spoc_core.MemoryByte size of each Bigarray element kind on a 64-bit target. Replaces Ctypes_static.sizeof (Ctypes.typ_of_bigarray_kind kind) so that the numeric-only path is free of ctypes. Sizes are identical to what ctypes sizeof returns on 64-bit: the underlying C representation widths.
val bigarray_void_ptr :
'a 'b. ('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t ->
unit Ctypes.ptrRaw data pointer of a host bigarray, for the H2D/D2H byte transfers.
Ctypes.bigarray_start cannot be used for f16: ctypes maps a Bigarray.kind to its own Ctypes_bigarray.kind GADT, and that mapping has NO Float16 arm — it ends in failwith "Unsupported bigarray kind" (ctypes_bigarray_stubs.ml). An f16 vector therefore raised on its first transfer even though every byte size involved was already correct.
This corrects a claim in the f16 design spec (§3.3, "transfer is element-type-agnostic beyond byte size — no change needed"): the transfer ARITHMETIC is indeed element-agnostic, but ACQUIRING the host pointer is not.
Ctypes_bigarray.unsafe_address is the kind-independent primitive (it is just Caml_ba_data_val) and is used for f16 only, keeping every other element type on the exact pre-existing code path.
GC ROOTS (#57 slice 1 review, MF3). The f16 arm must NOT be built with Ctypes.ptr_of_raw_address: that is make_unmanaged, and it silently drops the GC root that Ctypes.bigarray_start establishes. ctypes' own bigarray_start returns a MANAGED fat pointer — Fat.make ~managed:(Some (Obj.repr ba)) ~reftyp raw (ctypes_memory.ml :302-305) — so for every non-f16 kind the pointer VALUE is itself a root for the bigarray, and ctypes' FFI keeps it alive across the call (ctypes_ffi.ml:112-119). Probe, three pointers built over the same shape and then subjected to a major GC with the pointer still live:
f32 bigarray_start (managed) : freed during ffi call = 0 f16 ptr_of_raw_address (unmanaged) : freed during ffi call = 1 f16 Fat.make ~managed (this arm) : freed during ffi call = 0
So the f16 arm reconstructs the SAME fat-pointer shape as ctypes, over the kind-independent address. That restores pre-existing GC semantics for f16 with zero per-caller discipline, rather than asking five call sites to remember a keepalive (three of which did not).
This does deepen an existing dependency on ctypes internals — already present via Ctypes_bigarray.unsafe_address here and via Ctypes_ptr.voidp = nativeint at Vector_transfer/Framework_sig — now also on Ctypes_static.CPointer and Ctypes_ptr.Fat.make. Both are exposed in ctypes_static.mli (the pointer GADT) and ctypes_ptr.ml's signature, and they are the only way to express "managed pointer to a Float16 bigarray" while ctypes' kind GADT has no Float16 arm. If ctypes ever grows one, this whole function collapses back to bigarray_start.
Callers converting the result to a bare nativeint via Ctypes.raw_address_of_ptr strip the root again — that is a SEPARATE obligation, stated verbatim at Framework_sig.ml:218-223, and it applies to every element type, not just f16. It is discharged with Sys.opaque_identity at the sites below and in Transfer.ml.
module type BUFFER = sig ... endA buffer packages backend-specific buffer with its operations. All transfers use raw pointers with byte sizes to avoid type parameter escaping issues in first-class modules.
Buffer with phantom type parameter for element type safety. The 'a parameter is not used at runtime but ensures type-safe transfers.
Allocate a buffer on a device for standard Bigarray types
Allocate a buffer for custom types with explicit element size in bytes
val free : 'a. 'a buffer -> unitFree a buffer
val host_to_device :
'a 'b. src:('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t ->
dst:'a buffer ->
unitCopy data from host bigarray to device. Converts bigarray to pointer internally. Type parameter ensures bigarray element type matches buffer type.
val device_to_host :
'a 'b. src:'a buffer ->
dst:('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t ->
unitCopy data from device to host bigarray. Converts bigarray to pointer internally. Type parameter ensures bigarray element type matches buffer type.
val host_ptr_to_device : 'a. src_ptr:unit Ctypes.ptr -> dst:'a buffer -> unitCopy data from raw pointer to device buffer (for custom types)
val device_to_host_ptr : 'a. src:'a buffer -> dst_ptr:unit Ctypes.ptr -> unitCopy data from device buffer to raw pointer (for custom types)
Copy data between device buffers (same device). Type parameter ensures both buffers have same element type.
val size : 'a. 'a buffer -> intGet buffer size in elements
val elem_size : 'a. 'a buffer -> intGet buffer element size in bytes
val device_ptr : 'a. 'a buffer -> nativeintGet raw device pointer
val bind_to_kargs :
'a. 'a buffer ->
Spoc_framework.Framework_sig.kargs ->
int ->
unitBind buffer to kernel args