diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index a181a8814571..64b1cd2deb89 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -123,6 +123,18 @@ rust_alignof() { return 4; } +// Issue #2303 +// On 32-bit x86 the alignment of 64-bit ints in structures is 4 bytes +// Which is different from the preferred 8-byte alignment reported +// by __alignof__ (at least on gcc). +#ifdef __i386__ +template<> +inline size_t +rust_alignof() { + return 4; +} +#endif + // Utility classes diff --git a/src/test/run-pass/rec-align-32-bit.rs b/src/test/run-pass/rec-align-32-bit.rs new file mode 100644 index 000000000000..d1c464faa7d3 --- /dev/null +++ b/src/test/run-pass/rec-align-32-bit.rs @@ -0,0 +1,45 @@ +// xfail-pretty +// Issue #2303 + +// This is the type with the questionable alignment +type inner = { + c64: u64 +}; + +// This is the type that contains the type with the +// questionable alignment, for testing +type outer = { + c8: u8, + t: inner +}; + +#[cfg(target_arch = "x86")] +fn main() { + + let x = {c8: 22u8, t: {c64: 44u64}}; + + // Send it through the shape code + let y = #fmt["%?", x]; + + #debug("align inner = %?", sys::align_of::()); // 8 + #debug("size outer = %?", sys::size_of::()); // 12 + #debug("y = %s", y); // (22, (0)) + + // per clang/gcc the alignment of `inner` is 4 on x86. + // we say it's 8 + //assert sys::align_of::() == 4u; // fails + + // per clang/gcc the size of `outer` should be 12 + // because `inner`s alignment was 4. + // LLVM packs the struct the way clang likes, despite + // our intents regarding the alignment of `inner` and + // we end up with the same size `outer` as clang + assert sys::size_of::() == 12u; // passes + + // But now our shape code doesn't find the inner struct + // We print (22, (0)) + assert y == "(22, (44))"; // fails +} + +#[cfg(target_arch = "x86_64")] +fn main() { }