rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Avoid use of non-FFI safe type u128 for alignment

Open vthib opened this issue 3 years ago • 2 comments

Input C/C++ Header

typedef struct _Foo {} __attribute__((__aligned__(16))) Foo;
typedef struct _Bar {} __attribute__((__aligned__(16))) Bar;

Foo *foo_new();
Bar *bar_new();

Bindgen Invocation

$ bindgen input.h --allowlist-function '.*' --opaque-type Foo --opaque-type _Bar --no-layout-tests

Actual Results

/* automatically generated by rust-bindgen 0.59.1 */

pub type Foo = [u128; 0usize];
#[repr(C)]
#[repr(align(16))]
#[derive(Debug, Copy, Clone)]
pub struct _Bar {
    pub _bindgen_opaque_blob: [u128; 0usize],
}
pub type Bar = _Bar;
extern "C" {
    pub fn foo_new() -> *mut Foo;
}
extern "C" {
    pub fn bar_new() -> *mut Bar;
}

Expected Results

The issue with this codegen is that u128 is used to get the 16-bytes alignment, but its use causes warnings:

warning: `extern` block uses type `u128`, which is not FFI-safe
  --> new.rs:25:25
   |
25 |     pub fn foo_new() -> *mut Foo;
   |                         ^^^^^^^^ not FFI-safe
   |
   = note: `#[warn(improper_ctypes)]` on by default
   = note: 128-bit integers don't currently have a known stable ABI

Instead, it would be better if the generated code used the #[repr(align(16))] for alignment, and only used u8 for sizes. However, this isn't always easily doable.

I included both Foo and Bar examples because the bar one is easily fixable, replacing u128 with u8, as the struct is properly aligned. However, in the case of Foo, #[repr(align(...))] cannot be used directly. A solution would be to codegen:

#[repr(align(16))]
pub struct Foo([u8; 0usize]);

or to do the same codegen as is done for _Bar:

#[repr(align(16))]
pub struct Foo {
    pub _bindgen_opaque_blob = [u8; 0usize],
}

i'm not entirely sure when bindgen decides to use a type alias, or use a struct with a single opaque field.

vthib avatar Oct 11 '21 11:10 vthib