rustc: represent the discriminant as a field for Layout::{Raw,StructWrapped}NullablePointer.

This commit is contained in:
Eduard-Mihai Burtescu 2017-09-14 00:02:53 +03:00
parent 30710609c0
commit 1dc572b85e
4 changed files with 112 additions and 81 deletions

View file

@ -12,6 +12,7 @@ pub use self::Integer::*;
pub use self::Layout::*;
pub use self::Primitive::*;
use rustc_back::slice::ref_slice;
use session::{self, DataTypeKind, Session};
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
@ -582,7 +583,7 @@ pub enum Primitive {
Pointer
}
impl Primitive {
impl<'a, 'tcx> Primitive {
pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
let dl = cx.data_layout();
@ -611,6 +612,15 @@ impl Primitive {
Pointer => dl.pointer_align
}
}
pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
match *self {
Int(i) => i.to_ty(tcx, false),
F32 => tcx.types.f32,
F64 => tcx.types.f64,
Pointer => tcx.mk_mut_ptr(tcx.mk_nil()),
}
}
}
/// A structure, a product type in ADT terms.
@ -1202,9 +1212,7 @@ impl<'a, 'tcx> Layout {
let layout = tcx.intern_layout(layout);
let fields = match *layout {
Scalar { .. } |
CEnum { .. } |
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => {
CEnum { .. } => {
FieldPlacement::union(0)
}
@ -1241,7 +1249,14 @@ impl<'a, 'tcx> Layout {
FieldPlacement::union(def.struct_variant().fields.len())
}
General { .. } => FieldPlacement::union(1)
General { .. } |
RawNullablePointer { .. } => FieldPlacement::union(1),
StructWrappedNullablePointer { ref discr_offset, .. } => {
FieldPlacement::Arbitrary {
offsets: ref_slice(discr_offset)
}
}
};
Ok(CachedLayout {
layout,
@ -1520,7 +1535,7 @@ impl<'a, 'tcx> Layout {
if let Some((discr, offset, primitive)) = choice {
// HACK(eddyb) work around not being able to move
// out of arrays with just the indexing operator.
let st = if discr == 0 { st0 } else { st1 };
let mut st = if discr == 0 { st0 } else { st1 };
// FIXME(eddyb) should take advantage of a newtype.
if offset.bytes() == 0 && primitive.size(dl) == st.stride() &&
@ -1531,6 +1546,14 @@ impl<'a, 'tcx> Layout {
});
}
let mut discr_align = primitive.align(dl);
if offset.abi_align(discr_align) != offset {
st.packed = true;
discr_align = dl.i8_align;
}
st.align = st.align.max(discr_align);
st.primitive_align = st.primitive_align.max(discr_align);
return success(StructWrappedNullablePointer {
nndiscr: discr as u64,
nonnull: st,
@ -2292,7 +2315,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
match tcx.struct_tail(pointee).sty {
ty::TySlice(element) => slice(element),
ty::TyStr => slice(tcx.types.u8),
ty::TyDynamic(..) => tcx.mk_mut_ptr(tcx.mk_nil()),
ty::TyDynamic(..) => Pointer.to_ty(tcx),
_ => bug!("FullLayout::field_type({:?}): not applicable", self)
}
};
@ -2350,6 +2373,10 @@ impl<'a, 'tcx> FullLayout<'tcx> {
General { discr, .. } => {
return [discr.to_ty(tcx, false)][i];
}
RawNullablePointer { discr, .. } |
StructWrappedNullablePointer { discr, .. } => {
return [discr.to_ty(tcx)][i];
}
_ if def.variants.len() > 1 => return [][i],
// Enums with one variant behave like structs.