about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-04 02:10:33 -0700
committerbors <bors@rust-lang.org>2013-06-04 02:10:33 -0700
commitb50030718cf28f2a5a81857a26b57442734fe854 (patch)
treee13f9b1071d0c6a2fbebe162cc3b6ac93724e335
parent133d45171564c8b7de14523c9f3aa87140b9f043 (diff)
parent0c9510ac389dc796e183e4125dbdd3a2e51b1f50 (diff)
downloadrust-b50030718cf28f2a5a81857a26b57442734fe854.tar.gz
rust-b50030718cf28f2a5a81857a26b57442734fe854.zip
auto merge of #6927 : jld/rust/monomorphize-abi-alignment, r=sanxiyn
-rw-r--r--src/librustc/middle/trans/monomorphize.rs8
-rw-r--r--src/test/run-pass/monomorphize-abi-alignment.rs31
2 files changed, 37 insertions, 2 deletions
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 7e29d3bd33a..062f72b6feb 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -30,7 +30,7 @@ use middle::trans::type_use;
 use middle::ty;
 use middle::ty::{FnSig};
 use middle::typeck;
-use util::ppaux::Repr;
+use util::ppaux::{Repr,ty_to_str};
 
 use core::vec;
 use syntax::ast;
@@ -379,10 +379,14 @@ pub fn make_mono_id(ccx: @CrateContext,
                         {
                             let llty = type_of::type_of(ccx, subst);
                             let size = machine::llbitsize_of_real(ccx, llty);
-                            let align = machine::llalign_of_pref(ccx, llty);
+                            let align = machine::llalign_of_min(ccx, llty);
                             let mode = datum::appropriate_mode(subst);
                             let data_class = mono_data_classify(subst);
 
+                            debug!("make_mono_id: type %s -> size %u align %u mode %? class %?",
+                                  ty_to_str(ccx.tcx, subst),
+                                  size, align, mode, data_class);
+
                             // Special value for nil to prevent problems
                             // with undef return pointers.
                             if size <= 8u && ty::type_is_nil(subst) {
diff --git a/src/test/run-pass/monomorphize-abi-alignment.rs b/src/test/run-pass/monomorphize-abi-alignment.rs
new file mode 100644
index 00000000000..12c882a8708
--- /dev/null
+++ b/src/test/run-pass/monomorphize-abi-alignment.rs
@@ -0,0 +1,31 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment,
+ * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment
+ * of any field.  (Also, u64 has 8-byte ABI alignment; this is not always true).
+ *
+ * On such platforms, if monomorphize uses the "preferred" alignment, then it will unify
+ * `A` and `B`, even though `S<A>` and `S<B>` have the field `t` at different offsets,
+ * and apply the wrong instance of the method `unwrap`.
+ */
+
+struct S<T> { i:u8, t:T }
+impl<T> S<T> { fn unwrap(self) -> T { self.t } }
+struct A((u32, u32));
+struct B(u64);
+
+pub fn main() {
+	static Ca: S<A> = S { i: 0, t: A((13, 104)) };
+	static Cb: S<B> = S { i: 0, t: B(31337) };
+	assert_eq!(*(Ca.unwrap()), (13, 104));
+	assert_eq!(*(Cb.unwrap()), 31337);
+}