mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-03 21:47:36 +00:00
rustc: move size/alignment from Layout into layout::Abi.
This commit is contained in:
parent
bd86f3739e
commit
bd51a2bc19
@ -25,7 +25,7 @@ use std::fmt;
|
|||||||
use std::i64;
|
use std::i64;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, Add, Sub, Mul, AddAssign, RangeInclusive};
|
use std::ops::{Add, Sub, Mul, AddAssign, RangeInclusive};
|
||||||
|
|
||||||
use ich::StableHashingContext;
|
use ich::StableHashingContext;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
||||||
@ -856,7 +856,7 @@ impl<'a, 'tcx> Struct {
|
|||||||
// Is this the NonZero lang item wrapping a pointer or integer type?
|
// Is this the NonZero lang item wrapping a pointer or integer type?
|
||||||
(_, &ty::TyAdt(def, _)) if Some(def.did) == tcx.lang_items().non_zero() => {
|
(_, &ty::TyAdt(def, _)) if Some(def.did) == tcx.lang_items().non_zero() => {
|
||||||
let field = layout.field(cx, 0)?;
|
let field = layout.field(cx, 0)?;
|
||||||
match *field {
|
match *field.layout {
|
||||||
Scalar(value) => {
|
Scalar(value) => {
|
||||||
Ok(Some((layout.fields.offset(0), value)))
|
Ok(Some((layout.fields.offset(0), value)))
|
||||||
}
|
}
|
||||||
@ -965,7 +965,7 @@ impl<'a, 'tcx> Union {
|
|||||||
fields: I,
|
fields: I,
|
||||||
scapegoat: Ty<'tcx>)
|
scapegoat: Ty<'tcx>)
|
||||||
-> Result<(), LayoutError<'tcx>>
|
-> Result<(), LayoutError<'tcx>>
|
||||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
|
where I: Iterator<Item=Result<FullLayout<'a>, LayoutError<'tcx>>> {
|
||||||
for (index, field) in fields.enumerate() {
|
for (index, field) in fields.enumerate() {
|
||||||
let field = field?;
|
let field = field?;
|
||||||
if field.is_unsized() {
|
if field.is_unsized() {
|
||||||
@ -1061,8 +1061,80 @@ impl<'a> FieldPlacement<'a> {
|
|||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Abi {
|
pub enum Abi {
|
||||||
Scalar(Primitive),
|
Scalar(Primitive),
|
||||||
Vector,
|
Vector {
|
||||||
Aggregate
|
element: Primitive,
|
||||||
|
count: u64
|
||||||
|
},
|
||||||
|
Aggregate {
|
||||||
|
/// If true, the size is exact, otherwise it's only a lower bound.
|
||||||
|
sized: bool,
|
||||||
|
align: Align,
|
||||||
|
primitive_align: Align,
|
||||||
|
size: Size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Abi {
|
||||||
|
/// Returns true if the layout corresponds to an unsized type.
|
||||||
|
pub fn is_unsized(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Abi::Scalar(_) | Abi::Vector {..} => false,
|
||||||
|
Abi::Aggregate { sized, .. } => !sized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Abi::Scalar(value) => value.size(dl),
|
||||||
|
|
||||||
|
Abi::Vector { element, count } => {
|
||||||
|
let element_size = element.size(dl);
|
||||||
|
let vec_size = match element_size.checked_mul(count, dl) {
|
||||||
|
Some(size) => size,
|
||||||
|
None => bug!("Layout::size({:?}): {} * {} overflowed",
|
||||||
|
self, element_size.bytes(), count)
|
||||||
|
};
|
||||||
|
vec_size.abi_align(self.align(dl))
|
||||||
|
}
|
||||||
|
|
||||||
|
Abi::Aggregate { size, .. } => size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Abi::Scalar(value) => value.align(dl),
|
||||||
|
|
||||||
|
Abi::Vector { element, count } => {
|
||||||
|
let elem_size = element.size(dl);
|
||||||
|
let vec_size = match elem_size.checked_mul(count, dl) {
|
||||||
|
Some(size) => size,
|
||||||
|
None => bug!("Layout::align({:?}): {} * {} overflowed",
|
||||||
|
self, elem_size.bytes(), count)
|
||||||
|
};
|
||||||
|
dl.vector_align(vec_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
Abi::Aggregate { align, .. } => align
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
|
||||||
|
(self.size(cx), self.align(cx))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns alignment before repr alignment is applied
|
||||||
|
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
match *self {
|
||||||
|
Abi::Aggregate { primitive_align, .. } => primitive_align,
|
||||||
|
|
||||||
|
_ => self.align(cx.data_layout())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type layout, from which size and alignment can be cheaply computed.
|
/// Type layout, from which size and alignment can be cheaply computed.
|
||||||
@ -1247,19 +1319,63 @@ impl<'a, 'tcx> Layout {
|
|||||||
};
|
};
|
||||||
let abi = match *layout {
|
let abi = match *layout {
|
||||||
Scalar(value) => Abi::Scalar(value),
|
Scalar(value) => Abi::Scalar(value),
|
||||||
Vector { .. } => Abi::Vector,
|
Vector { element, count } => Abi::Vector { element, count },
|
||||||
|
|
||||||
Array { .. } |
|
Array { sized, align, primitive_align, element_size, count, .. } => {
|
||||||
FatPointer { .. } |
|
let size = match element_size.checked_mul(count, dl) {
|
||||||
Univariant(_) |
|
Some(size) => size,
|
||||||
UntaggedUnion(_) => Abi::Aggregate,
|
None => return Err(LayoutError::SizeOverflow(ty))
|
||||||
|
};
|
||||||
|
Abi::Aggregate {
|
||||||
|
sized,
|
||||||
|
align,
|
||||||
|
primitive_align,
|
||||||
|
size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
General { discr, .. } |
|
FatPointer(metadata) => {
|
||||||
NullablePointer { discr, .. } => {
|
// Effectively a (ptr, meta) tuple.
|
||||||
if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) {
|
let align = Pointer.align(dl).max(metadata.align(dl));
|
||||||
|
Abi::Aggregate {
|
||||||
|
sized: true,
|
||||||
|
align,
|
||||||
|
primitive_align: align,
|
||||||
|
size: (Pointer.size(dl).abi_align(metadata.align(dl)) +
|
||||||
|
metadata.size(dl))
|
||||||
|
.abi_align(align)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Univariant(ref st) => {
|
||||||
|
Abi::Aggregate {
|
||||||
|
sized: st.sized,
|
||||||
|
align: st.align,
|
||||||
|
primitive_align: st.primitive_align,
|
||||||
|
size: st.stride()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UntaggedUnion(ref un ) => {
|
||||||
|
Abi::Aggregate {
|
||||||
|
sized: true,
|
||||||
|
align: un.align,
|
||||||
|
primitive_align: un.primitive_align,
|
||||||
|
size: un.stride()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
General { discr, align, primitive_align, size, .. } |
|
||||||
|
NullablePointer { discr, align, primitive_align, size, .. } => {
|
||||||
|
if fields.offset(0).bytes() == 0 && discr.size(cx) == size {
|
||||||
Abi::Scalar(discr)
|
Abi::Scalar(discr)
|
||||||
} else {
|
} else {
|
||||||
Abi::Aggregate
|
Abi::Aggregate {
|
||||||
|
sized: true,
|
||||||
|
align,
|
||||||
|
primitive_align,
|
||||||
|
size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1330,9 +1446,6 @@ impl<'a, 'tcx> Layout {
|
|||||||
let element = cx.layout_of(element)?;
|
let element = cx.layout_of(element)?;
|
||||||
let element_size = element.size(dl);
|
let element_size = element.size(dl);
|
||||||
let count = count.val.to_const_int().unwrap().to_u64().unwrap();
|
let count = count.val.to_const_int().unwrap().to_u64().unwrap();
|
||||||
if element_size.checked_mul(count, dl).is_none() {
|
|
||||||
return Err(LayoutError::SizeOverflow(ty));
|
|
||||||
}
|
|
||||||
Array {
|
Array {
|
||||||
sized: true,
|
sized: true,
|
||||||
align: element.align(dl),
|
align: element.align(dl),
|
||||||
@ -1408,8 +1521,8 @@ impl<'a, 'tcx> Layout {
|
|||||||
// SIMD vector types.
|
// SIMD vector types.
|
||||||
ty::TyAdt(def, ..) if def.repr.simd() => {
|
ty::TyAdt(def, ..) if def.repr.simd() => {
|
||||||
let element = ty.simd_type(tcx);
|
let element = ty.simd_type(tcx);
|
||||||
match *cx.layout_of(element)? {
|
match cx.layout_of(element)?.abi {
|
||||||
Scalar(value) => {
|
Abi::Scalar(value) => {
|
||||||
return success(Vector {
|
return success(Vector {
|
||||||
element: value,
|
element: value,
|
||||||
count: ty.simd_size(tcx) as u64
|
count: ty.simd_size(tcx) as u64
|
||||||
@ -1459,7 +1572,7 @@ impl<'a, 'tcx> Layout {
|
|||||||
|
|
||||||
let layout = if def.is_union() {
|
let layout = if def.is_union() {
|
||||||
let mut un = Union::new(dl, &def.repr);
|
let mut un = Union::new(dl, &def.repr);
|
||||||
un.extend(dl, variants[0].iter().map(|&f| Ok(f.layout)), ty)?;
|
un.extend(dl, variants[0].iter().map(|&f| Ok(f)), ty)?;
|
||||||
UntaggedUnion(un)
|
UntaggedUnion(un)
|
||||||
} else {
|
} else {
|
||||||
Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
|
Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
|
||||||
@ -1648,112 +1761,13 @@ impl<'a, 'tcx> Layout {
|
|||||||
success(layout)
|
success(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the layout corresponds to an unsized type.
|
|
||||||
pub fn is_unsized(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Scalar(_) | Vector {..} | FatPointer {..} |
|
|
||||||
UntaggedUnion {..} | General {..} |
|
|
||||||
NullablePointer {..} => false,
|
|
||||||
|
|
||||||
Array { sized, .. } |
|
|
||||||
Univariant(Struct { sized, .. }) => !sized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
|
|
||||||
let dl = cx.data_layout();
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
Scalar(value) => {
|
|
||||||
value.size(dl)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector { element, count } => {
|
|
||||||
let element_size = element.size(dl);
|
|
||||||
let vec_size = match element_size.checked_mul(count, dl) {
|
|
||||||
Some(size) => size,
|
|
||||||
None => bug!("Layout::size({:?}): {} * {} overflowed",
|
|
||||||
self, element_size.bytes(), count)
|
|
||||||
};
|
|
||||||
vec_size.abi_align(self.align(dl))
|
|
||||||
}
|
|
||||||
|
|
||||||
Array { element_size, count, .. } => {
|
|
||||||
match element_size.checked_mul(count, dl) {
|
|
||||||
Some(size) => size,
|
|
||||||
None => bug!("Layout::size({:?}): {} * {} overflowed",
|
|
||||||
self, element_size.bytes(), count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FatPointer(metadata) => {
|
|
||||||
// Effectively a (ptr, meta) tuple.
|
|
||||||
(Pointer.size(dl).abi_align(metadata.align(dl)) +
|
|
||||||
metadata.size(dl)).abi_align(self.align(dl))
|
|
||||||
}
|
|
||||||
|
|
||||||
NullablePointer { size, .. } |
|
|
||||||
General { size, .. } => size,
|
|
||||||
UntaggedUnion(ref un) => un.stride(),
|
|
||||||
Univariant(ref variant) => variant.stride()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
|
||||||
let dl = cx.data_layout();
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
Scalar(value) => {
|
|
||||||
value.align(dl)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector { element, count } => {
|
|
||||||
let elem_size = element.size(dl);
|
|
||||||
let vec_size = match elem_size.checked_mul(count, dl) {
|
|
||||||
Some(size) => size,
|
|
||||||
None => bug!("Layout::align({:?}): {} * {} overflowed",
|
|
||||||
self, elem_size.bytes(), count)
|
|
||||||
};
|
|
||||||
dl.vector_align(vec_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
FatPointer(metadata) => {
|
|
||||||
// Effectively a (ptr, meta) tuple.
|
|
||||||
Pointer.align(dl).max(metadata.align(dl))
|
|
||||||
}
|
|
||||||
|
|
||||||
Array { align, .. } |
|
|
||||||
NullablePointer { align, .. } |
|
|
||||||
General { align, .. } => align,
|
|
||||||
UntaggedUnion(ref un) => un.align,
|
|
||||||
Univariant(ref variant) => variant.align
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
|
|
||||||
(self.size(cx), self.align(cx))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns alignment before repr alignment is applied
|
|
||||||
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
|
|
||||||
match *self {
|
|
||||||
Array { primitive_align, .. } |
|
|
||||||
NullablePointer { primitive_align, .. } |
|
|
||||||
General { primitive_align, .. } => primitive_align,
|
|
||||||
|
|
||||||
Univariant(ref variant) => variant.primitive_align,
|
|
||||||
|
|
||||||
_ => self.align(cx.data_layout())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is invoked by the `layout_raw` query to record the final
|
/// This is invoked by the `layout_raw` query to record the final
|
||||||
/// layout of each type.
|
/// layout of each type.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
layout: &Layout) {
|
layout: FullLayout) {
|
||||||
// If we are running with `-Zprint-type-sizes`, record layouts for
|
// If we are running with `-Zprint-type-sizes`, record layouts for
|
||||||
// dumping later. Ignore layouts that are done with non-empty
|
// dumping later. Ignore layouts that are done with non-empty
|
||||||
// environments or non-monomorphic layouts, as the user only wants
|
// environments or non-monomorphic layouts, as the user only wants
|
||||||
@ -1773,7 +1787,7 @@ impl<'a, 'tcx> Layout {
|
|||||||
fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
layout: &Layout) {
|
layout: FullLayout) {
|
||||||
// (delay format until we actually need it)
|
// (delay format until we actually need it)
|
||||||
let record = |kind, opt_discr_size, variants| {
|
let record = |kind, opt_discr_size, variants| {
|
||||||
let type_desc = format!("{:?}", ty);
|
let type_desc = format!("{:?}", ty);
|
||||||
@ -1843,7 +1857,7 @@ impl<'a, 'tcx> Layout {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match *layout {
|
match *layout.layout {
|
||||||
Layout::Univariant(ref variant_layout) => {
|
Layout::Univariant(ref variant_layout) => {
|
||||||
let variant_names = || {
|
let variant_names = || {
|
||||||
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
|
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
|
||||||
@ -1888,7 +1902,7 @@ impl<'a, 'tcx> Layout {
|
|||||||
variant_layout)
|
variant_layout)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
record(adt_kind.into(), match *layout {
|
record(adt_kind.into(), match *layout.layout {
|
||||||
Layout::General { discr, .. } => Some(discr.size(tcx)),
|
Layout::General { discr, .. } => Some(discr.size(tcx)),
|
||||||
_ => None
|
_ => None
|
||||||
}, variant_infos);
|
}, variant_infos);
|
||||||
@ -2075,13 +2089,6 @@ pub struct FullLayout<'tcx> {
|
|||||||
pub abi: Abi,
|
pub abi: Abi,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Deref for FullLayout<'tcx> {
|
|
||||||
type Target = Layout;
|
|
||||||
fn deref(&self) -> &Layout {
|
|
||||||
self.layout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||||
}
|
}
|
||||||
@ -2127,6 +2134,13 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx
|
|||||||
|
|
||||||
let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
|
let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
|
||||||
let cached = tcx.layout_raw(param_env.reveal_all().and(ty))?;
|
let cached = tcx.layout_raw(param_env.reveal_all().and(ty))?;
|
||||||
|
let layout = FullLayout {
|
||||||
|
ty,
|
||||||
|
variant_index: None,
|
||||||
|
layout: cached.layout,
|
||||||
|
fields: cached.fields,
|
||||||
|
abi: cached.abi
|
||||||
|
};
|
||||||
|
|
||||||
// NB: This recording is normally disabled; when enabled, it
|
// NB: This recording is normally disabled; when enabled, it
|
||||||
// can however trigger recursive invocations of `layout_of`.
|
// can however trigger recursive invocations of `layout_of`.
|
||||||
@ -2134,15 +2148,9 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx
|
|||||||
// completed, to avoid problems around recursive structures
|
// completed, to avoid problems around recursive structures
|
||||||
// and the like. (Admitedly, I wasn't able to reproduce a problem
|
// and the like. (Admitedly, I wasn't able to reproduce a problem
|
||||||
// here, but it seems like the right thing to do. -nmatsakis)
|
// here, but it seems like the right thing to do. -nmatsakis)
|
||||||
Layout::record_layout_for_printing(tcx, ty, param_env, cached.layout);
|
Layout::record_layout_for_printing(tcx, ty, param_env, layout);
|
||||||
|
|
||||||
Ok(FullLayout {
|
Ok(layout)
|
||||||
ty,
|
|
||||||
variant_index: None,
|
|
||||||
layout: cached.layout,
|
|
||||||
fields: cached.fields,
|
|
||||||
abi: cached.abi
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2158,6 +2166,13 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
|
let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
|
||||||
let cached = tcx_at.layout_raw(param_env.reveal_all().and(ty))?;
|
let cached = tcx_at.layout_raw(param_env.reveal_all().and(ty))?;
|
||||||
|
let layout = FullLayout {
|
||||||
|
ty,
|
||||||
|
variant_index: None,
|
||||||
|
layout: cached.layout,
|
||||||
|
fields: cached.fields,
|
||||||
|
abi: cached.abi
|
||||||
|
};
|
||||||
|
|
||||||
// NB: This recording is normally disabled; when enabled, it
|
// NB: This recording is normally disabled; when enabled, it
|
||||||
// can however trigger recursive invocations of `layout_of`.
|
// can however trigger recursive invocations of `layout_of`.
|
||||||
@ -2165,15 +2180,9 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
|
|||||||
// completed, to avoid problems around recursive structures
|
// completed, to avoid problems around recursive structures
|
||||||
// and the like. (Admitedly, I wasn't able to reproduce a problem
|
// and the like. (Admitedly, I wasn't able to reproduce a problem
|
||||||
// here, but it seems like the right thing to do. -nmatsakis)
|
// here, but it seems like the right thing to do. -nmatsakis)
|
||||||
Layout::record_layout_for_printing(tcx_at.tcx, ty, param_env, cached.layout);
|
Layout::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
|
||||||
|
|
||||||
Ok(FullLayout {
|
Ok(layout)
|
||||||
ty,
|
|
||||||
variant_index: None,
|
|
||||||
layout: cached.layout,
|
|
||||||
fields: cached.fields,
|
|
||||||
abi: cached.abi
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2189,27 +2198,29 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
|||||||
variants[variant_index].fields.len()
|
variants[variant_index].fields.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = match *self.layout {
|
let (fields, abi) = match *self.layout {
|
||||||
Univariant(ref variant) => {
|
Univariant(_) => (self.fields, self.abi),
|
||||||
FieldPlacement::Arbitrary {
|
|
||||||
offsets: &variant.offsets
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NullablePointer { ref variants, .. } |
|
NullablePointer { ref variants, .. } |
|
||||||
General { ref variants, .. } => {
|
General { ref variants, .. } => {
|
||||||
FieldPlacement::Arbitrary {
|
let variant = &variants[variant_index];
|
||||||
offsets: &variants[variant_index].offsets
|
(FieldPlacement::Arbitrary {
|
||||||
}
|
offsets: &variant.offsets
|
||||||
|
}, Abi::Aggregate {
|
||||||
|
sized: true,
|
||||||
|
align: variant.align,
|
||||||
|
primitive_align: variant.primitive_align,
|
||||||
|
size: variant.stride(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => FieldPlacement::union(count)
|
_ => (FieldPlacement::union(count), self.abi)
|
||||||
};
|
};
|
||||||
|
|
||||||
FullLayout {
|
FullLayout {
|
||||||
variant_index: Some(variant_index),
|
variant_index: Some(variant_index),
|
||||||
fields,
|
fields,
|
||||||
abi: Abi::Aggregate,
|
abi,
|
||||||
..*self
|
..*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2313,6 +2324,28 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
|||||||
-> C::FullLayout {
|
-> C::FullLayout {
|
||||||
cx.layout_of(self.field_type_unnormalized(cx.tcx(), i))
|
cx.layout_of(self.field_type_unnormalized(cx.tcx(), i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the layout corresponds to an unsized type.
|
||||||
|
pub fn is_unsized(&self) -> bool {
|
||||||
|
self.abi.is_unsized()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
|
||||||
|
self.abi.size(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
self.abi.align(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size_and_align<C: HasDataLayout>(&self, cx: C) -> (Size, Align) {
|
||||||
|
self.abi.size_and_align(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns alignment before repr alignment is applied
|
||||||
|
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
self.abi.primitive_align(cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
|
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
|
||||||
@ -2411,12 +2444,18 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi {
|
|||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Scalar(value) => {
|
Scalar(ref value) => {
|
||||||
value.hash_stable(hcx, hasher);
|
value.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
Vector => {
|
Vector { ref element, count } => {
|
||||||
|
element.hash_stable(hcx, hasher);
|
||||||
|
count.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
Aggregate => {
|
Aggregate { sized, size, align, primitive_align } => {
|
||||||
|
sized.hash_stable(hcx, hasher);
|
||||||
|
size.hash_stable(hcx, hasher);
|
||||||
|
align.hash_stable(hcx, hasher);
|
||||||
|
primitive_align.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,7 +753,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||||||
bug!("failed to get layout for `{}`: {}", t, e)
|
bug!("failed to get layout for `{}`: {}", t, e)
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Layout::General { ref variants, ref size, discr, .. } = *layout {
|
if let Layout::General { ref variants, size, discr, .. } = *layout.layout {
|
||||||
let discr_size = discr.size(cx.tcx).bytes();
|
let discr_size = discr.size(cx.tcx).bytes();
|
||||||
|
|
||||||
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||||
|
@ -278,8 +278,8 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
|
|||||||
fn is_aggregate(&self) -> bool {
|
fn is_aggregate(&self) -> bool {
|
||||||
match self.abi {
|
match self.abi {
|
||||||
layout::Abi::Scalar(_) |
|
layout::Abi::Scalar(_) |
|
||||||
layout::Abi::Vector => false,
|
layout::Abi::Vector { .. } => false,
|
||||||
layout::Abi::Aggregate => true
|
layout::Abi::Aggregate { .. } => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,14 +299,14 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
layout::Abi::Vector => {
|
layout::Abi::Vector { .. } => {
|
||||||
Some(Reg {
|
Some(Reg {
|
||||||
kind: RegKind::Vector,
|
kind: RegKind::Vector,
|
||||||
size: self.size(ccx)
|
size: self.size(ccx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
layout::Abi::Aggregate => {
|
layout::Abi::Aggregate { .. } => {
|
||||||
if let Layout::Array { count, .. } = *self.layout {
|
if let Layout::Array { count, .. } = *self.layout {
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
return self.field(ccx, 0).homogeneous_aggregate(ccx);
|
return self.field(ccx, 0).homogeneous_aggregate(ccx);
|
||||||
@ -767,7 +767,7 @@ impl<'a, 'tcx> FnType<'tcx> {
|
|||||||
for ty in inputs.iter().chain(extra_args.iter()) {
|
for ty in inputs.iter().chain(extra_args.iter()) {
|
||||||
let mut arg = arg_of(ty, false);
|
let mut arg = arg_of(ty, false);
|
||||||
|
|
||||||
if let ty::layout::FatPointer { .. } = *arg.layout {
|
if let ty::layout::FatPointer { .. } = *arg.layout.layout {
|
||||||
let mut data = ArgType::new(arg.layout.field(ccx, 0));
|
let mut data = ArgType::new(arg.layout.field(ccx, 0));
|
||||||
let mut info = ArgType::new(arg.layout.field(ccx, 1));
|
let mut info = ArgType::new(arg.layout.field(ccx, 1));
|
||||||
|
|
||||||
@ -809,7 +809,7 @@ impl<'a, 'tcx> FnType<'tcx> {
|
|||||||
abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
|
abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
|
||||||
let fixup = |arg: &mut ArgType<'tcx>| {
|
let fixup = |arg: &mut ArgType<'tcx>| {
|
||||||
match arg.layout.abi {
|
match arg.layout.abi {
|
||||||
layout::Abi::Aggregate => {}
|
layout::Abi::Aggregate { .. } => {}
|
||||||
_ => return
|
_ => return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
if let layout::Abi::Scalar(_) = l.abi {
|
if let layout::Abi::Scalar(_) = l.abi {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::NullablePointer { .. } |
|
layout::NullablePointer { .. } |
|
||||||
layout::General { .. } |
|
layout::General { .. } |
|
||||||
layout::UntaggedUnion { .. } => { }
|
layout::UntaggedUnion { .. } => { }
|
||||||
@ -101,7 +101,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
if let layout::Abi::Scalar(value) = l.abi {
|
if let layout::Abi::Scalar(value) = l.abi {
|
||||||
return cx.llvm_type_of(value.to_ty(cx.tcx()));
|
return cx.llvm_type_of(value.to_ty(cx.tcx()));
|
||||||
}
|
}
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::Univariant(ref variant) => {
|
layout::Univariant(ref variant) => {
|
||||||
match name {
|
match name {
|
||||||
None => {
|
None => {
|
||||||
|
@ -29,7 +29,7 @@ fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
match layout.abi {
|
match layout.abi {
|
||||||
layout::Abi::Scalar(layout::F32) |
|
layout::Abi::Scalar(layout::F32) |
|
||||||
layout::Abi::Scalar(layout::F64) => true,
|
layout::Abi::Scalar(layout::F64) => true,
|
||||||
layout::Abi::Aggregate => {
|
layout::Abi::Aggregate { .. } => {
|
||||||
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
||||||
is_single_fp_element(ccx, layout.field(ccx, 0))
|
is_single_fp_element(ccx, layout.field(ccx, 0))
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,7 +24,7 @@ fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
match layout.abi {
|
match layout.abi {
|
||||||
layout::Abi::Scalar(layout::F32) |
|
layout::Abi::Scalar(layout::F32) |
|
||||||
layout::Abi::Scalar(layout::F64) => true,
|
layout::Abi::Scalar(layout::F64) => true,
|
||||||
layout::Abi::Aggregate => {
|
layout::Abi::Aggregate { .. } => {
|
||||||
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
||||||
is_single_fp_element(ccx, layout.field(ccx, 0))
|
is_single_fp_element(ccx, layout.field(ccx, 0))
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,22 +75,22 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
|
|||||||
unify(cls, off, reg);
|
unify(cls, off, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
layout::Abi::Vector => {
|
layout::Abi::Vector { element, count } => {
|
||||||
unify(cls, off, Class::Sse);
|
unify(cls, off, Class::Sse);
|
||||||
|
|
||||||
// everything after the first one is the upper
|
// everything after the first one is the upper
|
||||||
// half of a register.
|
// half of a register.
|
||||||
let eltsz = layout.field(ccx, 0).size(ccx);
|
let eltsz = element.size(ccx);
|
||||||
for i in 1..layout.fields.count() {
|
for i in 1..count {
|
||||||
unify(cls, off + eltsz * (i as u64), Class::SseUp);
|
unify(cls, off + eltsz * (i as u64), Class::SseUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layout::Abi::Aggregate => {
|
layout::Abi::Aggregate { .. } => {
|
||||||
// FIXME(eddyb) have to work around Rust enums for now.
|
// FIXME(eddyb) have to work around Rust enums for now.
|
||||||
// Fix is either guarantee no data where there is no field,
|
// Fix is either guarantee no data where there is no field,
|
||||||
// by putting variants in fields, or be more clever.
|
// by putting variants in fields, or be more clever.
|
||||||
match *layout {
|
match *layout.layout {
|
||||||
Layout::General { .. } |
|
Layout::General { .. } |
|
||||||
Layout::NullablePointer { .. } => return Err(Memory),
|
Layout::NullablePointer { .. } => return Err(Memory),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -8,32 +8,36 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use abi::{ArgType, FnType, LayoutExt, Reg};
|
use abi::{ArgType, FnType, Reg};
|
||||||
use common::CrateContext;
|
use common::CrateContext;
|
||||||
|
|
||||||
use rustc::ty::layout::Layout;
|
use rustc::ty::layout;
|
||||||
|
|
||||||
// Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
// Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
||||||
|
|
||||||
pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||||
let fixup = |a: &mut ArgType<'tcx>| {
|
let fixup = |a: &mut ArgType<'tcx>| {
|
||||||
let size = a.layout.size(ccx);
|
let size = a.layout.size(ccx);
|
||||||
if a.layout.is_aggregate() {
|
match a.layout.abi {
|
||||||
match size.bits() {
|
layout::Abi::Aggregate { .. } => {
|
||||||
8 => a.cast_to(Reg::i8()),
|
match size.bits() {
|
||||||
16 => a.cast_to(Reg::i16()),
|
8 => a.cast_to(Reg::i8()),
|
||||||
32 => a.cast_to(Reg::i32()),
|
16 => a.cast_to(Reg::i16()),
|
||||||
64 => a.cast_to(Reg::i64()),
|
32 => a.cast_to(Reg::i32()),
|
||||||
_ => a.make_indirect(ccx)
|
64 => a.cast_to(Reg::i64()),
|
||||||
};
|
_ => a.make_indirect(ccx)
|
||||||
} else {
|
}
|
||||||
if let Layout::Vector { .. } = *a.layout {
|
}
|
||||||
|
layout::Abi::Vector { .. } => {
|
||||||
// FIXME(eddyb) there should be a size cap here
|
// FIXME(eddyb) there should be a size cap here
|
||||||
// (probably what clang calls "illegal vectors").
|
// (probably what clang calls "illegal vectors").
|
||||||
} else if size.bytes() > 8 {
|
}
|
||||||
a.make_indirect(ccx);
|
layout::Abi::Scalar(_) => {
|
||||||
} else {
|
if size.bytes() > 8 {
|
||||||
a.extend_integer_width_to(32);
|
a.make_indirect(ccx);
|
||||||
|
} else {
|
||||||
|
a.extend_integer_width_to(32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||||||
pub use context::{CrateContext, SharedCrateContext};
|
pub use context::{CrateContext, SharedCrateContext};
|
||||||
|
|
||||||
pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
if let Layout::FatPointer { .. } = *ccx.layout_of(ty) {
|
if let Layout::FatPointer { .. } = *ccx.layout_of(ty).layout {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -51,9 +51,9 @@ pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) ->
|
|||||||
pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
let layout = ccx.layout_of(ty);
|
let layout = ccx.layout_of(ty);
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
layout::Abi::Scalar(_) | layout::Abi::Vector => true,
|
layout::Abi::Scalar(_) | layout::Abi::Vector { .. } => true,
|
||||||
|
|
||||||
layout::Abi::Aggregate => {
|
layout::Abi::Aggregate { .. } => {
|
||||||
!layout.is_unsized() && layout.size(ccx).bytes() == 0
|
!layout.is_unsized() && layout.size(ccx).bytes() == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
|||||||
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 layout = ccx.layout_of(ty);
|
let layout = ccx.layout_of(ty);
|
||||||
match *layout {
|
match *layout.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.
|
||||||
|
@ -941,7 +941,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
|||||||
let layout = cx.layout_of(self.ty);
|
let layout = cx.layout_of(self.ty);
|
||||||
|
|
||||||
let tmp;
|
let tmp;
|
||||||
let offsets = match *layout {
|
let offsets = match *layout.layout {
|
||||||
layout::Univariant(ref variant) => &variant.offsets,
|
layout::Univariant(ref variant) => &variant.offsets,
|
||||||
layout::Vector { element, count } => {
|
layout::Vector { element, count } => {
|
||||||
let element_size = element.size(cx).bytes();
|
let element_size = element.size(cx).bytes();
|
||||||
@ -1022,7 +1022,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
|||||||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
||||||
-> Vec<MemberDescription> {
|
-> Vec<MemberDescription> {
|
||||||
let layout = cx.layout_of(self.ty);
|
let layout = cx.layout_of(self.ty);
|
||||||
let offsets = if let layout::Univariant(ref variant) = *layout {
|
let offsets = if let layout::Univariant(ref variant) = *layout.layout {
|
||||||
&variant.offsets
|
&variant.offsets
|
||||||
} else {
|
} else {
|
||||||
bug!("{} is not a tuple", self.ty);
|
bug!("{} is not a tuple", self.ty);
|
||||||
@ -1339,7 +1339,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
span: Span)
|
span: Span)
|
||||||
-> (DICompositeType, MemberDescriptionFactory<'tcx>) {
|
-> (DICompositeType, MemberDescriptionFactory<'tcx>) {
|
||||||
let layout = cx.layout_of(enum_type);
|
let layout = cx.layout_of(enum_type);
|
||||||
let maybe_discr = match *layout {
|
let maybe_discr = match *layout.layout {
|
||||||
layout::General { .. } => Some(layout.field(cx, 0).ty),
|
layout::General { .. } => Some(layout.field(cx, 0).ty),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@ -1491,7 +1491,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
let type_rep = cx.layout_of(enum_type);
|
let type_rep = cx.layout_of(enum_type);
|
||||||
|
|
||||||
let discriminant_type_metadata = match *type_rep {
|
let discriminant_type_metadata = match *type_rep.layout {
|
||||||
layout::NullablePointer { .. } | layout::Univariant { .. } => None,
|
layout::NullablePointer { .. } | layout::Univariant { .. } => None,
|
||||||
layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
|
layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
|
||||||
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
||||||
|
@ -58,7 +58,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
|
|||||||
let layout = ccx.layout_of(t);
|
let layout = ccx.layout_of(t);
|
||||||
debug!("DST {} layout: {:?}", t, layout);
|
debug!("DST {} layout: {:?}", t, layout);
|
||||||
|
|
||||||
let (sized_size, sized_align) = match *layout {
|
let (sized_size, sized_align) = match *layout.layout {
|
||||||
ty::layout::Layout::Univariant(ref variant) => {
|
ty::layout::Layout::Univariant(ref variant) => {
|
||||||
(variant.offsets.last().map_or(0, |o| o.bytes()), variant.align.abi())
|
(variant.offsets.last().map_or(0, |o| o.bytes()), variant.align.abi())
|
||||||
}
|
}
|
||||||
|
@ -1090,7 +1090,7 @@ fn trans_const_adt<'a, 'tcx>(
|
|||||||
mir::AggregateKind::Adt(_, index, _, _) => index,
|
mir::AggregateKind::Adt(_, index, _, _) => index,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::General { ref variants, .. } => {
|
layout::General { ref variants, .. } => {
|
||||||
let discr = match *kind {
|
let discr = match *kind {
|
||||||
mir::AggregateKind::Adt(adt_def, _, _, _) => {
|
mir::AggregateKind::Adt(adt_def, _, _, _) => {
|
||||||
|
@ -208,10 +208,10 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
let field = l.field(ccx, ix);
|
let field = l.field(ccx, ix);
|
||||||
let offset = l.fields.offset(ix).bytes();
|
let offset = l.fields.offset(ix).bytes();
|
||||||
|
|
||||||
let alignment = self.alignment | Alignment::from(&*l);
|
let alignment = self.alignment | Alignment::from(l.layout);
|
||||||
|
|
||||||
// Unions and newtypes only use an offset of 0.
|
// Unions and newtypes only use an offset of 0.
|
||||||
match *l {
|
match *l.layout {
|
||||||
// FIXME(eddyb) The fields of a fat pointer aren't correct, especially
|
// FIXME(eddyb) The fields of a fat pointer aren't correct, especially
|
||||||
// to unsized structs, we can't represent their pointee types in `Ty`.
|
// to unsized structs, we can't represent their pointee types in `Ty`.
|
||||||
Layout::FatPointer { .. } => {}
|
Layout::FatPointer { .. } => {}
|
||||||
@ -234,7 +234,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Discriminant field of enums.
|
// Discriminant field of enums.
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::NullablePointer { .. } if l.variant_index.is_none() => {
|
layout::NullablePointer { .. } if l.variant_index.is_none() => {
|
||||||
let ty = ccx.llvm_type_of(field.ty);
|
let ty = ccx.llvm_type_of(field.ty);
|
||||||
let size = field.size(ccx).bytes();
|
let size = field.size(ccx).bytes();
|
||||||
@ -271,7 +271,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Check whether the variant being used is packed, if applicable.
|
// Check whether the variant being used is packed, if applicable.
|
||||||
let is_packed = match (&*l, l.variant_index) {
|
let is_packed = match (l.layout, l.variant_index) {
|
||||||
(&layout::Univariant(ref variant), _) => variant.packed,
|
(&layout::Univariant(ref variant), _) => variant.packed,
|
||||||
(&layout::NullablePointer { ref variants, .. }, Some(v)) |
|
(&layout::NullablePointer { ref variants, .. }, Some(v)) |
|
||||||
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
|
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
|
||||||
@ -354,7 +354,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
let l = bcx.ccx.layout_of(self.ty.to_ty(bcx.tcx()));
|
let l = bcx.ccx.layout_of(self.ty.to_ty(bcx.tcx()));
|
||||||
|
|
||||||
let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
|
let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::Univariant { .. } |
|
layout::Univariant { .. } |
|
||||||
layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
|
layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -366,7 +366,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
layout::Abi::Scalar(discr) => discr,
|
layout::Abi::Scalar(discr) => discr,
|
||||||
_ => bug!("discriminant not scalar: {:#?}", discr_layout)
|
_ => bug!("discriminant not scalar: {:#?}", discr_layout)
|
||||||
};
|
};
|
||||||
let (min, max) = match *l {
|
let (min, max) = match *l.layout {
|
||||||
layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
|
layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
|
||||||
_ => (0, u64::max_value()),
|
_ => (0, u64::max_value()),
|
||||||
};
|
};
|
||||||
@ -392,7 +392,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
bcx.load(discr.llval, discr.alignment.non_abi())
|
bcx.load(discr.llval, discr.alignment.non_abi())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::General { .. } => {
|
layout::General { .. } => {
|
||||||
let signed = match discr_scalar {
|
let signed = match discr_scalar {
|
||||||
layout::Int(_, signed) => signed,
|
layout::Int(_, signed) => signed,
|
||||||
@ -416,7 +416,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
let to = l.ty.ty_adt_def().unwrap()
|
let to = l.ty.ty_adt_def().unwrap()
|
||||||
.discriminant_for_variant(bcx.tcx(), variant_index)
|
.discriminant_for_variant(bcx.tcx(), variant_index)
|
||||||
.to_u128_unchecked() as u64;
|
.to_u128_unchecked() as u64;
|
||||||
match *l {
|
match *l.layout {
|
||||||
layout::General { .. } => {
|
layout::General { .. } => {
|
||||||
let ptr = self.project_field(bcx, 0);
|
let ptr = self.project_field(bcx, 0);
|
||||||
bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
|
bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
|
||||||
@ -471,7 +471,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||||||
|
|
||||||
// If this is an enum, cast to the appropriate variant struct type.
|
// If this is an enum, cast to the appropriate variant struct type.
|
||||||
let layout = bcx.ccx.layout_of(ty).for_variant(variant_index);
|
let layout = bcx.ccx.layout_of(ty).for_variant(variant_index);
|
||||||
match *layout {
|
match *layout.layout {
|
||||||
layout::NullablePointer { ref variants, .. } |
|
layout::NullablePointer { ref variants, .. } |
|
||||||
layout::General { ref variants, .. } => {
|
layout::General { ref variants, .. } => {
|
||||||
let st = &variants[variant_index];
|
let st = &variants[variant_index];
|
||||||
|
@ -576,7 +576,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
|||||||
};
|
};
|
||||||
|
|
||||||
let layout = bcx.ccx.layout_of(closure_ty);
|
let layout = bcx.ccx.layout_of(closure_ty);
|
||||||
let offsets = match *layout {
|
let offsets = match *layout.layout {
|
||||||
layout::Univariant(ref variant) => &variant.offsets[..],
|
layout::Univariant(ref variant) => &variant.offsets[..],
|
||||||
_ => bug!("Closures are only supposed to be Univariant")
|
_ => bug!("Closures are only supposed to be Univariant")
|
||||||
};
|
};
|
||||||
|
@ -277,7 +277,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||||||
let llval = operand.immediate();
|
let llval = operand.immediate();
|
||||||
let l = bcx.ccx.layout_of(operand.ty);
|
let l = bcx.ccx.layout_of(operand.ty);
|
||||||
|
|
||||||
if let Layout::General { ref discr_range, .. } = *l {
|
if let Layout::General { ref discr_range, .. } = *l.layout {
|
||||||
if discr_range.end > discr_range.start {
|
if discr_range.end > discr_range.start {
|
||||||
// We want `table[e as usize]` to not
|
// We want `table[e as usize]` to not
|
||||||
// have bound checks, and this is the most
|
// have bound checks, and this is the most
|
||||||
|
@ -240,7 +240,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
|||||||
if let layout::Abi::Scalar(_) = self.abi {
|
if let layout::Abi::Scalar(_) = self.abi {
|
||||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self);
|
bug!("FullLayout::llvm_field_index({:?}): not applicable", self);
|
||||||
}
|
}
|
||||||
match **self {
|
match *self.layout {
|
||||||
Layout::Scalar { .. } |
|
Layout::Scalar { .. } |
|
||||||
Layout::UntaggedUnion { .. } => {
|
Layout::UntaggedUnion { .. } => {
|
||||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||||
|
Loading…
Reference in New Issue
Block a user