about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-04-26 17:49:38 -0700
committerBrian Anderson <banderson@mozilla.com>2012-04-26 18:30:58 -0700
commitbbc4a74dc685a570ebdf53849e8cc2220ed1d586 (patch)
tree8faa33cdd2944106cdd6d9b94ca8dac962a9833f
parent8e15640adacd1f0cab8617d62f445024915e5214 (diff)
downloadrust-bbc4a74dc685a570ebdf53849e8cc2220ed1d586.tar.gz
rust-bbc4a74dc685a570ebdf53849e8cc2220ed1d586.zip
rt: Fix shape alignment of 64-bit ints on x86. Issue #2303
-rw-r--r--src/rt/rust_shape.h12
-rw-r--r--src/test/run-pass/rec-align-32-bit.rs45
2 files changed, 57 insertions, 0 deletions
diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h
index a181a881457..64b1cd2deb8 100644
--- a/src/rt/rust_shape.h
+++ b/src/rt/rust_shape.h
@@ -123,6 +123,18 @@ rust_alignof<double>() {
     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<uint64_t>() {
+    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 00000000000..d1c464faa7d
--- /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::<inner>()); // 8
+    #debug("size outer = %?", sys::size_of::<outer>());   // 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::<inner>() == 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::<outer>() == 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() { }