Doesn't seem to be possible to make linked library call FFI-safe

Essentially I have a piece of code that looks something like this:

    #[link(name = "vaes")]
    extern "C" {
        pub fn func(
            keys: *const __m128i,
        );

And then getting message like this:

warning: `extern` block uses type `std::arch::x86_64::__m128i`, which is not FFI-safe
   --> src/aes_low_level/vaes.rs:265:19
    |
265 |             keys: *const __m128i,
    |                   ^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: `#[warn(improper_ctypes)]` on by default
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout

I found 2574-simd-ffi - The Rust RFC Book and that #[target_feature(enable = "sse2")] is needed to be added, but then I get:

error: attribute should be applied to a function

So apparently there is something about linked library that doesn't work.

The library is supposed to be cross-platform, so I'd like to not hardcode compiler flags in .cargo/config.

The exact abi of an __m128i argument depends on the target features enabled for the calling function.

Yes, I read that, but there doesn't seem to be a way to specify target feature for that function unless I'm missing something.

I think this sentence within the error message is kind of misleading: the struct has unspecified ABI, but a well-specified layout.

If the extern "C" function were to use a __m128i by value, then this could indeed be problematic since so doing relies on the ABI of that type (which, includes, among other things, the layout of the type).

However, your function does not use a __m128i by value, but through pointer indirection. This leads to relying on the ABI of a (slim) pointer, which is well defined. Later on, though, if code dereferences that pointer it can still be problematic, since so doing relies on the layout (and the layout only!) of the pointee.

But, AFAIK, the layout of a __m128i is well defined! It's a 16-byte-long and 8-byte-aligned (this is the part I'm not 100% sure about) bag of bytes.

In that case, if you (stack-)allocate, for instance, a __m128i local, and then give its address to func, all should be fine.

1 Like

Thank you for the answer!
Indeed I never use it as value across FFI boundary.

So is this something that should be reported as a bug in rustc?
I'm really not very knowledgeable with FFI and especially this deep. Also this scope of functionality seems to be used by rather small number of people, so it is really hard to find answers.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.