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

Rust thinks u64 and f64 have 4 byte alignment on Linux 32bit #43899

Closed
upsuper opened this issue Aug 16, 2017 · 8 comments
Closed

Rust thinks u64 and f64 have 4 byte alignment on Linux 32bit #43899

upsuper opened this issue Aug 16, 2017 · 8 comments

Comments

@upsuper
Copy link
Contributor

upsuper commented Aug 16, 2017

The following code:

use std::mem;
fn main() {
    println!("sizeof u64: {}, alignof u64: {}",
             mem::size_of::<u64>(), mem::align_of::<u64>());
    println!("sizeof f64: {}, alignof f64: {}",
             mem::size_of::<f64>(), mem::align_of::<f64>());
}

with

rustc test.rs --target=i686-unknown-linux-gnu

The generated executable outputs:

sizeof u64: 8, alignof u64: 4
sizeof f64: 8, alignof f64: 4

which matches neither gcc nor clang.

And this issue seems to block linux32-stylo.

@upsuper
Copy link
Contributor Author

upsuper commented Aug 16, 2017

cc @emilio

@sfackler
Copy link
Member

According to the i386 System V ABI, u64 and f64 are 4 byte aligned - see Table 2.1 in https://www.uclibc.org/docs/psABI-i386.pdf.

@emilio
Copy link
Contributor

emilio commented Aug 16, 2017

Yes, but C++ compilers seem to disagree with that, apparently, which causes trouble :(

@sfackler
Copy link
Member

sfackler commented Aug 16, 2017

C++ doesn't have a stable ABI, it has "whatever gcc and clang decided to do" IIRC.

@nagisa
Copy link
Member

nagisa commented Aug 16, 2017

Seems to match C in both gcc and clang just fine:

#include<inttypes.h>

#define alignof(type) (unsigned)((&((struct { char c; type d; } *)0)->d))

int main(void) {
    printf("%u %u %u %u\n", sizeof(uint64_t), alignof(uint64_t), sizeof(double), alignof(double));
    return 0;
}

where both output 8 4 8 4.

@upsuper
Copy link
Contributor Author

upsuper commented Aug 16, 2017

Actually even in C++, something like

struct Test1 { char c; uint64_t u; };

would have the second field aligned to 4 bytes rather than 8 bytes, as can be found in my bug report to gcc.

So the behavior really is, when the type are the first field of a struct, or they are on themselves, they have a different alignment.

@upsuper
Copy link
Contributor Author

upsuper commented Aug 16, 2017

OK, so I don't think this is really a valid issue. It is reasonable that u64 and f64 have 4byte alignment on 32bit Linux (actually they should).

There may be problem when passing u64 and f64 through FFI since if IIUC, the 8byte alignment is used for that. But that's a different issue.

So the real problem here is actually a mix of bindgen issue and lack of language support from Rust side when manual alignment (alignas/alignof) is used in C++.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants