about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/trans/adt.rs20
-rw-r--r--src/test/run-pass/const-adt-align-mismatch.rs28
2 files changed, 36 insertions, 12 deletions
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 8bb60eca8b1..ddd720f1e84 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -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);
diff --git a/src/test/run-pass/const-adt-align-mismatch.rs b/src/test/run-pass/const-adt-align-mismatch.rs
new file mode 100644
index 00000000000..5377d9a62b9
--- /dev/null
+++ b/src/test/run-pass/const-adt-align-mismatch.rs
@@ -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);
+}