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.
|
/// 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>)
|
pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||||
-> bool {
|
-> bool {
|
||||||
let tcx = ccx.tcx();
|
match *ccx.layout_of(ty) {
|
||||||
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 {
|
|
||||||
Layout::FatPointer { .. } => true,
|
Layout::FatPointer { .. } => true,
|
||||||
Layout::Univariant { ref variant, .. } => {
|
Layout::Univariant { ref variant, .. } => {
|
||||||
// There must be only 2 fields.
|
// There must be only 2 fields.
|
||||||
|
@ -947,6 +947,14 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||||||
TypeOfDepthLock(self.local())
|
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 {
|
pub fn check_overflow(&self) -> bool {
|
||||||
self.shared.check_overflow
|
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) => {
|
ty::TyStruct(def, substs) => {
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
// First get the size of all statically known fields.
|
// 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());
|
assert!(!t.is_simd());
|
||||||
let repr = adt::represent_type(ccx, t);
|
let layout = ccx.layout_of(t);
|
||||||
let sizing_type = adt::sizing_type_of(ccx, &repr, true);
|
debug!("DST {} layout: {:?}", t, layout);
|
||||||
debug!("DST {} sizing_type: {:?}", t, sizing_type);
|
|
||||||
let sized_size = llsize_of_alloc(ccx, sizing_type);
|
let (sized_size, sized_align) = match *layout {
|
||||||
let sized_align = llalign_of_min(ccx, sizing_type);
|
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: {}",
|
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||||
t, sized_size, sized_align);
|
t, sized_size, sized_align);
|
||||||
let sized_size = C_uint(ccx, sized_size);
|
let sized_size = C_uint(ccx, sized_size);
|
||||||
|
@ -15,7 +15,6 @@ use abi::FnType;
|
|||||||
use adt;
|
use adt;
|
||||||
use common::*;
|
use common::*;
|
||||||
use machine;
|
use machine;
|
||||||
use rustc::traits::Reveal;
|
|
||||||
use rustc::ty::{self, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
|
|
||||||
use type_::Type;
|
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);
|
cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
|
||||||
|
|
||||||
// FIXME(eddyb) Temporary sanity check for ty::layout.
|
// FIXME(eddyb) Temporary sanity check for ty::layout.
|
||||||
let layout = cx.tcx().normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
|
let layout = cx.layout_of(t);
|
||||||
t.layout(&infcx)
|
if !type_is_sized(cx.tcx(), t) {
|
||||||
});
|
if !layout.is_unsized() {
|
||||||
match layout {
|
bug!("layout should be unsized for type `{}` / {:#?}",
|
||||||
Ok(layout) => {
|
t, layout);
|
||||||
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.
|
// Unsized types get turned into a fat pointer for LLVM.
|
||||||
return llsizingty;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
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