rustc_trans: correctly round up the largest variant to the enum's alignment.
This commit is contained in:
parent
f4473a4664
commit
48662d7cba
2 changed files with 36 additions and 12 deletions
|
|
@ -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);
|
||||
|
|
|
|||
28
src/test/run-pass/const-adt-align-mismatch.rs
Normal file
28
src/test/run-pass/const-adt-align-mismatch.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue