diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trans/trans/adt.rs | 20 | ||||
| -rw-r--r-- | src/test/run-pass/const-adt-align-mismatch.rs | 28 |
2 files changed, 36 insertions, 12 deletions
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 8bb60eca8b1..ddd720f1e84 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -323,7 +323,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, mk_struct(cx, &ftys[], false, t) }).collect(); - ensure_enum_fits_in_address_space(cx, ity, &fields[], t); + ensure_enum_fits_in_address_space(cx, &fields[], t); General(ity, fields, dtor) } @@ -582,20 +582,14 @@ fn ensure_struct_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn union_size_and_align(sts: &[Struct]) -> (machine::llsize, machine::llalign) { let size = sts.iter().map(|st| st.size).max().unwrap(); - let most_aligned = sts.iter().max_by(|st| st.align).unwrap(); - (size, most_aligned.align) + let align = sts.iter().map(|st| st.align).max().unwrap(); + (roundup(size, align), align) } fn ensure_enum_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - discr: IntType, fields: &[Struct], scapegoat: Ty<'tcx>) { - let discr_size = machine::llsize_of_alloc(ccx, ll_inttype(ccx, discr)); - let (field_size, field_align) = union_size_and_align(fields); - - // field_align < 1<<32, discr_size <= 8, field_size < OBJ_SIZE_BOUND <= 1<<61 - // so the sum is less than 1<<62 (and can't overflow). - let total_size = roundup(discr_size, field_align) + field_size; + let (total_size, _) = union_size_and_align(fields); if total_size >= ccx.obj_size_bound() { ccx.report_overbig_object(scapegoat); @@ -667,9 +661,11 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // FIXME #10604: this breaks when vector types are present. let (size, align) = union_size_and_align(&sts[]); let align_s = align as u64; + assert_eq!(size % align_s, 0); + let align_units = size / align_s - 1; + let discr_ty = ll_inttype(cx, ity); let discr_size = machine::llsize_of_alloc(cx, discr_ty); - let align_units = (size + align_s - 1) / align_s - 1; let fill_ty = match align_s { 1 => Type::array(&Type::i8(cx), align_units), 2 => Type::array(&Type::i16(cx), align_units), @@ -1049,7 +1045,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr } General(ity, ref cases, _) => { let case = &cases[discr as uint]; - let max_sz = cases.iter().map(|x| x.size).max().unwrap(); + let (max_sz, _) = union_size_and_align(&cases[]); let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true); let mut f = vec![lldiscr]; f.push_all(vals); diff --git a/src/test/run-pass/const-adt-align-mismatch.rs b/src/test/run-pass/const-adt-align-mismatch.rs new file mode 100644 index 00000000000..5377d9a62b9 --- /dev/null +++ b/src/test/run-pass/const-adt-align-mismatch.rs @@ -0,0 +1,28 @@ +// Copyright 2015 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. + +use std::mem; + +#[derive(PartialEq, Show)] +enum Foo { + A(u32), + Bar([u16; 4]), + C +} + +// NOTE(eddyb) Don't make this a const, needs to be a static +// so it is always instantiated as a LLVM constant value. +static FOO: Foo = Foo::C; + +fn main() { + assert_eq!(FOO, Foo::C); + assert_eq!(mem::size_of::<Foo>(), 12); + assert_eq!(mem::min_align_of::<Foo>(), 4); +} |
