mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
rustc_trans: don't round up the DST prefix size to its alignment.
This commit is contained in:
parent
1987131063
commit
3e313d9528
@ -124,18 +124,7 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||
/// Returns true if the type is represented as a pair of immediates.
|
||||
pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||
-> bool {
|
||||
let tcx = ccx.tcx();
|
||||
let layout = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
match ty.layout(&infcx) {
|
||||
Ok(layout) => layout,
|
||||
Err(err) => {
|
||||
bug!("type_is_imm_pair: layout for `{:?}` failed: {}",
|
||||
ty, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
match *layout {
|
||||
match *ccx.layout_of(ty) {
|
||||
Layout::FatPointer { .. } => true,
|
||||
Layout::Univariant { ref variant, .. } => {
|
||||
// There must be only 2 fields.
|
||||
|
@ -947,6 +947,14 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
TypeOfDepthLock(self.local())
|
||||
}
|
||||
|
||||
pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout {
|
||||
self.tcx().normalizing_infer_ctxt(traits::Reveal::All).enter(|infcx| {
|
||||
ty.layout(&infcx).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", ty, e);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn check_overflow(&self) -> bool {
|
||||
self.shared.check_overflow
|
||||
}
|
||||
|
@ -338,13 +338,22 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
|
||||
ty::TyStruct(def, substs) => {
|
||||
let ccx = bcx.ccx();
|
||||
// First get the size of all statically known fields.
|
||||
// Don't use type_of::sizing_type_of because that expects t to be sized.
|
||||
// Don't use type_of::sizing_type_of because that expects t to be sized,
|
||||
// and it also rounds up to alignment, which we want to avoid,
|
||||
// as the unsized field's alignment could be smaller.
|
||||
assert!(!t.is_simd());
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let sizing_type = adt::sizing_type_of(ccx, &repr, true);
|
||||
debug!("DST {} sizing_type: {:?}", t, sizing_type);
|
||||
let sized_size = llsize_of_alloc(ccx, sizing_type);
|
||||
let sized_align = llalign_of_min(ccx, sizing_type);
|
||||
let layout = ccx.layout_of(t);
|
||||
debug!("DST {} layout: {:?}", t, layout);
|
||||
|
||||
let (sized_size, sized_align) = match *layout {
|
||||
ty::layout::Layout::Univariant { ref variant, .. } => {
|
||||
(variant.min_size().bytes(), variant.align.abi())
|
||||
}
|
||||
_ => {
|
||||
bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}",
|
||||
t, layout);
|
||||
}
|
||||
};
|
||||
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||
t, sized_size, sized_align);
|
||||
let sized_size = C_uint(ccx, sized_size);
|
||||
|
@ -15,7 +15,6 @@ use abi::FnType;
|
||||
use adt;
|
||||
use common::*;
|
||||
use machine;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
|
||||
use type_::Type;
|
||||
@ -124,37 +123,31 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
||||
cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
|
||||
|
||||
// FIXME(eddyb) Temporary sanity check for ty::layout.
|
||||
let layout = cx.tcx().normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
t.layout(&infcx)
|
||||
});
|
||||
match layout {
|
||||
Ok(layout) => {
|
||||
if !type_is_sized(cx.tcx(), t) {
|
||||
if !layout.is_unsized() {
|
||||
bug!("layout should be unsized for type `{}` / {:#?}",
|
||||
t, layout);
|
||||
}
|
||||
let layout = cx.layout_of(t);
|
||||
if !type_is_sized(cx.tcx(), t) {
|
||||
if !layout.is_unsized() {
|
||||
bug!("layout should be unsized for type `{}` / {:#?}",
|
||||
t, layout);
|
||||
}
|
||||
|
||||
// Unsized types get turned into a fat pointer for LLVM.
|
||||
return llsizingty;
|
||||
}
|
||||
let r = layout.size(&cx.tcx().data_layout).bytes();
|
||||
let l = machine::llsize_of_alloc(cx, llsizingty);
|
||||
if r != l {
|
||||
bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||
r, l, t, layout);
|
||||
}
|
||||
let r = layout.align(&cx.tcx().data_layout).abi();
|
||||
let l = machine::llalign_of_min(cx, llsizingty) as u64;
|
||||
if r != l {
|
||||
bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||
r, l, t, layout);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
bug!("failed to get layout for `{}`: {}", t, e);
|
||||
}
|
||||
// Unsized types get turned into a fat pointer for LLVM.
|
||||
return llsizingty;
|
||||
}
|
||||
|
||||
let r = layout.size(&cx.tcx().data_layout).bytes();
|
||||
let l = machine::llsize_of_alloc(cx, llsizingty);
|
||||
if r != l {
|
||||
bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||
r, l, t, layout);
|
||||
}
|
||||
|
||||
let r = layout.align(&cx.tcx().data_layout).abi();
|
||||
let l = machine::llalign_of_min(cx, llsizingty) as u64;
|
||||
if r != l {
|
||||
bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||
r, l, t, layout);
|
||||
}
|
||||
|
||||
llsizingty
|
||||
}
|
||||
|
||||
|
23
src/test/run-pass/issue-35815.rs
Normal file
23
src/test/run-pass/issue-35815.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2016 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;
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
a: i64,
|
||||
b: bool,
|
||||
c: T,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo: &Foo<i32> = &Foo { a: 1, b: false, c: 2i32 };
|
||||
let foo_unsized: &Foo<Send> = foo;
|
||||
assert_eq!(mem::size_of_val(foo), mem::size_of_val(foo_unsized));
|
||||
}
|
Loading…
Reference in New Issue
Block a user