From 0c9510ac389dc796e183e4125dbdd3a2e51b1f50 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Mon, 3 Jun 2013 22:34:51 -0700 Subject: [PATCH] Use ABI alignment, not "preferred" alignment, to unify monomorphizations. See the comment in the added test case for details. --- src/librustc/middle/trans/monomorphize.rs | 8 +++-- .../run-pass/monomorphize-abi-alignment.rs | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/monomorphize-abi-alignment.rs 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::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 or the MIT license +// , 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` and `S` have the field `t` at different offsets, + * and apply the wrong instance of the method `unwrap`. + */ + +struct S { i:u8, t:T } +impl S { fn unwrap(self) -> T { self.t } } +struct A((u32, u32)); +struct B(u64); + +pub fn main() { + static Ca: S = S { i: 0, t: A((13, 104)) }; + static Cb: S = S { i: 0, t: B(31337) }; + assert_eq!(*(Ca.unwrap()), (13, 104)); + assert_eq!(*(Cb.unwrap()), 31337); +}