Skip to content

repr(simd) is unsound in C FFI #53346

Description

@gnzlbg

This supersedes #44367 - after #47743 the unsoundness has been restricted to C FFI. The Rust ABI for vector types currently passes all types by memory.

There are sadly many C libraries that use vector types in their ABIs, some of which are pretty much "fundamental" like some of the short-vector math libraries: libmvec, SVML, etc.

As a summary of the previous issue, currently, the behavior of calling bar, `the following snippet of Rust code is sometimes undefined:

#![feature(repr_simd, simd_ffi)]

#[repr(simd)]
struct F32x8(f32, f32, f32, f32, f32, f32, f32, f32);
impl F32x8 { fn splat(x: f32) -> Self { F32x8(x, x, x, x, x, x, x, x) } }

#[allow(improper_ctypes)]
extern "C" {
    fn foo(x: F32x8) -> F32x8;
}

fn main() {
    unsafe { 
        foo(F32x8::splat(0.));  // UB ?
    }
}

When both the Rust program and the C library exposing foo are compiled with the same set of target-features such that their ABIs match, then the program above will work as expected.

When the C library is compiled with say AVX2, but the Rust program is compiled with SSE4.2, then Rust will try to pass the F32x8 in two 128-bit wide vector registers to C, while the C code only expects a single 256-bit wide vector. A similar problem occurs in the opposite case.

cc @rkruppe @parched @alexcrichton @eddyb - did I correctly represent the problem ?


A potential solution discussed in #44367 would be to completely forbid vector types in FFI functions that do not specify their vector ABI:

extern "C" {
    extern "vector-256" fn foo(x: F32x8) -> F32x8;
    extern "vector-128" fn bar(x: F32x8) -> F32x8;
    // fn baz(x: F32x8) -> F32x8; // ERROR: repr(simd) in C-FFI with unspecified vector ABI
}

let x = F32x8::splat(0.);
foo(x); // x is passed in a single 256-bit wide register
bar(x); // x is passed in two 128-bit wide registers

If the C library linked does not expose the specified ABIs for foo and bar, the program would fail to link, preventing undefined behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-SIMDArea: SIMD (Single Instruction Multiple Data)A-reprArea: the `#[repr(stuff)]` attributeC-bugCategory: This is a bug.F-simd_ffi`#![feature(simd_ffi)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamrequires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions