Skip to content

Commit

Permalink
Auto merge of rust-lang#32010 - devonhollowood:non-c-like-enum-repr, …
Browse files Browse the repository at this point in the history
…r=Aatch

Add tests for rust-lang#26114

First step in fixing rust-lang#26114
  • Loading branch information
bors committed Mar 20, 2016
2 parents 978bc07 + b5be095 commit 2af3dd7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
19 changes: 14 additions & 5 deletions src/librustc_trans/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand All @@ -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();
Expand Down
33 changes: 32 additions & 1 deletion src/test/run-pass/enum-discrim-manual-sizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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
}

0 comments on commit 2af3dd7

Please sign in to comment.