From 3f94fac150c872f93ee00eaad736eae5e3226aaa Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Wed, 2 Mar 2016 10:10:39 -0800 Subject: [PATCH 1/3] Add tests for #26114 --- src/test/run-pass/enum-discrim-manual-sizing.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/run-pass/enum-discrim-manual-sizing.rs b/src/test/run-pass/enum-discrim-manual-sizing.rs index edad5cc1652..377f52a62c5 100644 --- a/src/test/run-pass/enum-discrim-manual-sizing.rs +++ b/src/test/run-pass/enum-discrim-manual-sizing.rs @@ -71,6 +71,18 @@ enum Euint { Buint = 1 } +#[repr(i64)] +enum Ei64_non_c_like { + _None, + _Some(T), +} + +#[repr(u64)] +enum Eu64_non_c_like { + _None, + _Some(T), +} + pub fn main() { assert_eq!(size_of::(), 1); assert_eq!(size_of::(), 1); @@ -82,4 +94,6 @@ pub fn main() { assert_eq!(size_of::(), 8); assert_eq!(size_of::(), size_of::()); assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>(), 8); } From ffe5162cd1605228a1dae798953a5ea6b8f2e97f Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Wed, 2 Mar 2016 11:57:00 -0800 Subject: [PATCH 2/3] Fix #26114 --- src/librustc_trans/trans/adt.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index ba227d6c38b..07d8175727b 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -400,6 +400,15 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } } + + // If the alignment is smaller than the chosen discriminant size, don't use the + // alignment as the final size. + let min_ty = ll_inttype(&cx, min_ity); + let min_size = machine::llsize_of_real(cx, min_ty); + if (align as u64) < min_size { + use_align = false; + } + let ity = if use_align { // Use the overall alignment match align { @@ -817,11 +826,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 padded_discr_size = roundup(discr_size, align); + assert_eq!(size % align_s, 0); // Ensure division in align_units comes out evenly + let align_units = (size - padded_discr_size) / align_s; let fill_ty = match align_s { 1 => Type::array(&Type::i8(cx), align_units), 2 => Type::array(&Type::i16(cx), align_units), @@ -833,10 +842,10 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => panic!("unsupported enum alignment: {}", align) }; assert_eq!(machine::llalign_of_min(cx, fill_ty), align); - assert_eq!(align_s % discr_size, 0); + assert_eq!(padded_discr_size % discr_size, 0); // Ensure discr_ty can fill pad evenly let mut fields: Vec = [discr_ty, - Type::array(&discr_ty, align_s / discr_size - 1), + Type::array(&discr_ty, (padded_discr_size - discr_size)/discr_size), fill_ty].iter().cloned().collect(); if delay_drop_flag && dtor_needed { fields.pop(); From b5be09564188b39aa2fbc73b057c1e35e99ee99f Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Mon, 7 Mar 2016 12:26:00 -0800 Subject: [PATCH 3/3] Improve tests for #26114 --- .../run-pass/enum-discrim-manual-sizing.rs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/test/run-pass/enum-discrim-manual-sizing.rs b/src/test/run-pass/enum-discrim-manual-sizing.rs index 377f52a62c5..3bbc107e0b9 100644 --- a/src/test/run-pass/enum-discrim-manual-sizing.rs +++ b/src/test/run-pass/enum-discrim-manual-sizing.rs @@ -9,7 +9,7 @@ // except according to those terms. -use std::mem::size_of; +use std::mem::{size_of, align_of}; #[repr(i8)] enum Ei8 { @@ -71,14 +71,20 @@ enum Euint { Buint = 1 } +#[repr(u8)] +enum Eu8NonCLike { + _None, + _Some(T), +} + #[repr(i64)] -enum Ei64_non_c_like { +enum Ei64NonCLike { _None, _Some(T), } #[repr(u64)] -enum Eu64_non_c_like { +enum Eu64NonCLike { _None, _Some(T), } @@ -94,6 +100,17 @@ pub fn main() { assert_eq!(size_of::(), 8); assert_eq!(size_of::(), size_of::()); assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::>(), 8); - assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>(), 8); + let u8_expected_size = round_up(9, align_of::>()); + assert_eq!(size_of::>(), u8_expected_size); + let array_expected_size = round_up(28, align_of::>()); + assert_eq!(size_of::>(), array_expected_size); + assert_eq!(size_of::>(), 32); +} + +// Rounds x up to the next multiple of a +fn round_up(x: usize, a: usize) -> usize { + ((x + (a - 1)) / a) * a }