diff options
| author | bors <bors@rust-lang.org> | 2016-03-20 12:49:46 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-03-20 12:49:46 -0700 |
| commit | 2af3dd73dbc71e0f345746e123df4ac71d3f392c (patch) | |
| tree | 6fd6e286356b6cfcd3dece5681b80a04467a46bf | |
| parent | 978bc070a66f7f4f82dc0f2c4a4e4e35478851b6 (diff) | |
| parent | b5be09564188b39aa2fbc73b057c1e35e99ee99f (diff) | |
| download | rust-2af3dd73dbc71e0f345746e123df4ac71d3f392c.tar.gz rust-2af3dd73dbc71e0f345746e123df4ac71d3f392c.zip | |
Auto merge of #32010 - devonhollowood:non-c-like-enum-repr, r=Aatch
Add tests for #26114 First step in fixing #26114
| -rw-r--r-- | src/librustc_trans/trans/adt.rs | 19 | ||||
| -rw-r--r-- | src/test/run-pass/enum-discrim-manual-sizing.rs | 33 |
2 files changed, 46 insertions, 6 deletions
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 45a1236647e..db0fa2a64bd 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -396,6 +396,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 { @@ -813,11 +822,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), @@ -829,10 +838,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<Type> = [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(); diff --git a/src/test/run-pass/enum-discrim-manual-sizing.rs b/src/test/run-pass/enum-discrim-manual-sizing.rs index edad5cc1652..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,6 +71,24 @@ enum Euint { Buint = 1 } +#[repr(u8)] +enum Eu8NonCLike<T> { + _None, + _Some(T), +} + +#[repr(i64)] +enum Ei64NonCLike<T> { + _None, + _Some(T), +} + +#[repr(u64)] +enum Eu64NonCLike<T> { + _None, + _Some(T), +} + pub fn main() { assert_eq!(size_of::<Ei8>(), 1); assert_eq!(size_of::<Eu8>(), 1); @@ -82,4 +100,17 @@ pub fn main() { assert_eq!(size_of::<Eu64>(), 8); assert_eq!(size_of::<Eint>(), size_of::<isize>()); assert_eq!(size_of::<Euint>(), size_of::<usize>()); + assert_eq!(size_of::<Eu8NonCLike<()>>(), 1); + assert_eq!(size_of::<Ei64NonCLike<()>>(), 8); + assert_eq!(size_of::<Eu64NonCLike<()>>(), 8); + let u8_expected_size = round_up(9, align_of::<Eu64NonCLike<u8>>()); + assert_eq!(size_of::<Eu64NonCLike<u8>>(), u8_expected_size); + let array_expected_size = round_up(28, align_of::<Eu64NonCLike<[u32; 5]>>()); + assert_eq!(size_of::<Eu64NonCLike<[u32; 5]>>(), array_expected_size); + assert_eq!(size_of::<Eu64NonCLike<[u32; 6]>>(), 32); +} + +// Rounds x up to the next multiple of a +fn round_up(x: usize, a: usize) -> usize { + ((x + (a - 1)) / a) * a } |
