From 12ff05fc506335c64e6237dd14d797795c384c19 Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Sat, 24 Sep 2016 17:37:24 -0400 Subject: [PATCH] Clean up matches that determine integers for specific alignment requirements --- src/librustc/ty/layout.rs | 37 +++++++++++++++++++++++-------------- src/librustc_trans/adt.rs | 17 ++++++++--------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 9bc1c1bc960d9..0451daf3d5fb3 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -339,6 +339,16 @@ impl Integer { } } + pub fn align(&self, dl: &TargetDataLayout)-> Align { + match *self { + I1 => dl.i1_align, + I8 => dl.i8_align, + I16 => dl.i16_align, + I32 => dl.i32_align, + I64 => dl.i64_align, + } + } + pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx> { match (*self, signed) { @@ -377,6 +387,18 @@ impl Integer { } } + //Find the smallest integer with the given alignment. + pub fn for_abi_align(dl: &TargetDataLayout, align: Align) -> Option { + let wanted = align.abi(); + for &candidate in &[I8, I16, I32, I64] { + let ty = Int(candidate); + if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() { + return Some(candidate); + } + } + None + } + /// Get the Integer type from an attr::IntType. pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> Integer { match ity { @@ -1149,20 +1171,7 @@ impl<'a, 'gcx, 'tcx> Layout { // won't be so conservative. // Use the initial field alignment - let wanted = start_align.abi(); - let mut ity = min_ity; - for &candidate in &[I16, I32, I64] { - let ty = Int(candidate); - if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() { - ity = candidate; - break; - } - } - - // FIXME(eddyb) conservative only to avoid diverging from trans::adt. - if align.abi() != start_align.abi() { - ity = min_ity; - } + let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity); // If the alignment is not larger than the chosen discriminant size, // don't use the alignment as the final size. diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index c7528c0cf69e5..c31714351dc6e 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -286,16 +286,15 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn union_fill(cx: &CrateContext, size: u64, align: u64) -> Type { assert_eq!(size%align, 0); + assert_eq!(align.count_ones(), 1, "Alignment must be a power fof 2. Got {}", align); let align_units = size/align; - match align { - 1 => Type::array(&Type::i8(cx), align_units), - 2 => Type::array(&Type::i16(cx), align_units), - 4 => Type::array(&Type::i32(cx), align_units), - 8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 => - Type::array(&Type::i64(cx), align_units), - a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(cx), a / 4), - align_units), - _ => bug!("unsupported union alignment: {}", align) + let dl = &cx.tcx().data_layout; + let layout_align = layout::Align::from_bytes(align, align).unwrap(); + if let Some(ity) = layout::Integer::for_abi_align(dl, layout_align) { + Type::array(&Type::from_integer(cx, ity), align_units) + } else { + Type::array(&Type::vector(&Type::i32(cx), align/4), + align_units) } }