libffi can marshal vector (SIMD) types — the values produced
by GCC’s __attribute__((vector_size (N))) and Clang’s
ext_vector_type — on the platforms listed in the support table
below. A vector is described just like a structure, except that every
element pointer refers to the same fundamental scalar type and the
number of elements is the number of vector lanes.
size_t sizeThis must be set to 0. libffi computes the storage size
(see below) from the element type and lane count.
unsigned short alignmentThis must be set to 0. libffi computes the alignment.
unsigned short typeFor a vector type, this must be set to FFI_TYPE_VECTOR.
ffi_type **elementsThis is a ‘NULL’-terminated array of pointers to ffi_type
objects. Every entry must point to the same scalar element type, and the
number of entries is the vector’s lane count N (N >= 1). The
element type must be one of ffi_type_float, ffi_type_double,
or a fixed-width integer (ffi_type_uint8 through
ffi_type_sint64); long double and aggregate element types are
not permitted.
Because the caller leaves size and alignment at 0,
libffi derives them so that applications need not encode
compiler- or platform-specific rules:
size is lane\_size \times N rounded up to the next
power of two. This matches Clang’s ext_vector_type storage — for
example a three-lane float vector occupies 16 bytes and a three-lane
double vector occupies 32 bytes. GCC’s vector_size already
requires power-of-two byte totals, so the rule is identical there.
alignment is min(size, 16).
If the element list is heterogeneous, empty, or uses a disallowed element
type, ffi_prep_cif returns FFI_BAD_TYPEDEF.
At the call boundary the platform’s processor-specific ABI (AAPCS64 on
AArch64, the System V x86-64 psABI on x86-64) decides how a vector is
passed and returned, independently of which compiler produced it. The
historical divergence between GCC’s vector_size and Clang’s
ext_vector_type concerns only in-memory layout (notably the
padding of odd-lane vectors such as float3); the power-of-two size
rule above pins that layout down, so a value marshalled by libffi
matches what a natively compiled caller or callee expects.
| Port | Vector support |
|---|---|
| AArch64 (AAPCS64) | 8- and 16-byte vectors in a single V/Q register; homogeneous vector
aggregates (structs of up to four identical 8- or 16-byte vectors) in
consecutive V/Q registers. A bare vector larger than 16 bytes (for
example a 32-byte double4) has no short-vector register class and is
passed and returned in memory, exactly as AAPCS64 and current compilers do. |
| x86-64 (System V psABI) | 8- and 16-byte vectors in an SSE register (%xmm0 for returns).
A bare vector larger than 16 bytes needs %ymm/%zmm register
handling that this port does not yet implement, so ffi_prep_cif
returns FFI_BAD_TYPEDEF for it. |
| Other ports | Not supported: ffi_prep_cif returns FFI_BAD_TYPEDEF for
any signature that mentions a vector type, including one nested inside a
struct. |