Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i128 / u128 are not compatible with C's definition. #54341

Open
emilio opened this Issue Sep 19, 2018 · 5 comments

Comments

Projects
None yet
5 participants
@emilio
Copy link
Contributor

commented Sep 19, 2018

While fixing various bindgen bugs related to long double, int128, (rust-lang/rust-bindgen#1370, etc).

I realized that the following Rust program, in my x86_64 Linux machine:

#[repr(C)]
struct Foo {
    f: u128,
}

fn main() {
    println!("Align: {}", ::std::mem::align_of::<Foo>());
}

Prints 8.

While the following C program:

#include <stdio.h>

struct foo {
  unsigned __int128 t;
};

int main() {
  printf("Align: %ld\n", _Alignof(struct foo));
}

Prints 16 on the same system. This is pretty unexpected, and means that i128 / u128 are not really usable for FFI / alignment purposes.

@vext01

This comment has been minimized.

Copy link
Contributor

commented Sep 19, 2018

I think the correct fix would be to add long_double type to libc with the correct alignment.

I guess that's probably not hard? I could have a go at that if it sounds like the right thing to do.

@nagisa

This comment has been minimized.

Copy link
Contributor

commented Sep 19, 2018

This is a bug in llvm. There was an attempt to fix this in the past, but it got reverted because of reasons.

The sysV __int128 should be 16-byte aligned and rust follows that ABI.

@nagisa

This comment has been minimized.

Copy link
Contributor

commented Sep 19, 2018

Rather, this is blocked on LLVM data-layouts getting fixed, because rustc expects them to be matched last time I checked.

@emilio

This comment has been minimized.

Copy link
Contributor Author

commented Sep 19, 2018

Ugh, thanks @nagisa... I think this is also a problem for long double, reading that LLVM patch they'd align it to 64 bits. Sigh.

#include <stdio.h>

struct foo {
  long double bar;
};

int main() {
  printf("%ld\n", _Alignof(struct foo)); // 16
}

emilio added a commit to emilio/rust-bindgen that referenced this issue Sep 19, 2018

Always force repr(align) attributes for stuff with alignment >= 16
To work-around some cases of rust-lang/rust#54341.

Other cases where u128 and u64 are mixed in fields might not behave correctly,
but the field offset assertions would catch them.

Fixes rust-lang#1370
@ubsan

This comment has been minimized.

Copy link
Contributor

commented Oct 10, 2018

Copying from the last thread, since this thread seems to mostly be about long double.

In C and C++, on x86_64 Linux, alignof(__int128) is equal to 16. However, in Rust, align_of::() is equal to 8.

C++: https://gcc.godbolt.org/z/YAq1XC
Rust: https://gcc.godbolt.org/z/QvZeqK

This will cause subtle UB if you ever try to use i128s across FFI boundaries; for example:

C++: https://gcc.godbolt.org/z/PrtHlp
Rust: https://gcc.godbolt.org/z/_SdVqD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.