rustc: represent the discriminant as a field for Layout::{Raw,StructWrapped}NullablePointer.
This commit is contained in:
parent
30710609c0
commit
1dc572b85e
4 changed files with 112 additions and 81 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue