rustc: make Layout::NullablePointer a lot more like Layout::General.
This commit is contained in:
parent
33a205b56f
commit
bd86f3739e
@ -1128,9 +1128,12 @@ pub enum Layout {
|
||||
/// identity function.
|
||||
NullablePointer {
|
||||
nndiscr: u64,
|
||||
nonnull: Struct,
|
||||
discr: Primitive,
|
||||
discr_offset: Size,
|
||||
variants: Vec<Struct>,
|
||||
size: Size,
|
||||
align: Align,
|
||||
primitive_align: Align,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1471,23 +1474,20 @@ impl<'a, 'tcx> Layout {
|
||||
!def.repr.inhibit_enum_layout_opt() &&
|
||||
no_explicit_discriminants {
|
||||
// Nullable pointer optimization
|
||||
let st0 = Struct::new(dl, &variants[0],
|
||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
let st1 = Struct::new(dl, &variants[1],
|
||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
let mut st = vec![
|
||||
Struct::new(dl, &variants[0],
|
||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
|
||||
Struct::new(dl, &variants[1],
|
||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?
|
||||
];
|
||||
|
||||
let mut choice = None;
|
||||
for discr in 0..2 {
|
||||
let (st, other) = if discr == 0 {
|
||||
(&st0, &st1)
|
||||
} else {
|
||||
(&st1, &st0)
|
||||
};
|
||||
if other.stride().bytes() > 0 {
|
||||
if st[1 - discr].stride().bytes() > 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let field = st.non_zero_field(tcx, param_env,
|
||||
let field = st[discr].non_zero_field(tcx, param_env,
|
||||
variants[discr].iter().map(|&f| Ok(f)))?;
|
||||
if let Some((offset, primitive)) = field {
|
||||
choice = Some((discr, offset, primitive));
|
||||
@ -1496,23 +1496,22 @@ 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 mut st = if discr == 0 { st0 } else { st1 };
|
||||
|
||||
let mut discr_align = primitive.align(dl);
|
||||
if offset.abi_align(discr_align) != offset {
|
||||
st.packed = true;
|
||||
st[discr].packed = true;
|
||||
discr_align = dl.i8_align;
|
||||
}
|
||||
st.align = st.align.max(discr_align);
|
||||
st.primitive_align = st.primitive_align.max(discr_align);
|
||||
let align = st[discr].align.max(discr_align);
|
||||
let primitive_align = st[discr].primitive_align.max(discr_align);
|
||||
|
||||
return success(NullablePointer {
|
||||
nndiscr: discr as u64,
|
||||
nonnull: st,
|
||||
discr: primitive,
|
||||
discr_offset: offset,
|
||||
size: st[discr].stride(),
|
||||
align,
|
||||
primitive_align,
|
||||
variants: st,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1693,13 +1692,10 @@ impl<'a, 'tcx> Layout {
|
||||
metadata.size(dl)).abi_align(self.align(dl))
|
||||
}
|
||||
|
||||
NullablePointer { size, .. } |
|
||||
General { size, .. } => size,
|
||||
UntaggedUnion(ref un) => un.stride(),
|
||||
|
||||
Univariant(ref variant) |
|
||||
NullablePointer { nonnull: ref variant, .. } => {
|
||||
variant.stride()
|
||||
}
|
||||
Univariant(ref variant) => variant.stride()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1726,13 +1722,11 @@ impl<'a, 'tcx> Layout {
|
||||
Pointer.align(dl).max(metadata.align(dl))
|
||||
}
|
||||
|
||||
Array { align, .. } | General { align, .. } => align,
|
||||
Array { align, .. } |
|
||||
NullablePointer { align, .. } |
|
||||
General { align, .. } => align,
|
||||
UntaggedUnion(ref un) => un.align,
|
||||
|
||||
Univariant(ref variant) |
|
||||
NullablePointer { nonnull: ref variant, .. } => {
|
||||
variant.align
|
||||
}
|
||||
Univariant(ref variant) => variant.align
|
||||
}
|
||||
}
|
||||
|
||||
@ -1743,11 +1737,11 @@ impl<'a, 'tcx> Layout {
|
||||
/// Returns alignment before repr alignment is applied
|
||||
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||
match *self {
|
||||
Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
|
||||
Univariant(ref variant) |
|
||||
NullablePointer { nonnull: ref variant, .. } => {
|
||||
variant.primitive_align
|
||||
},
|
||||
Array { primitive_align, .. } |
|
||||
NullablePointer { primitive_align, .. } |
|
||||
General { primitive_align, .. } => primitive_align,
|
||||
|
||||
Univariant(ref variant) => variant.primitive_align,
|
||||
|
||||
_ => self.align(cx.data_layout())
|
||||
}
|
||||
@ -1850,23 +1844,6 @@ impl<'a, 'tcx> Layout {
|
||||
};
|
||||
|
||||
match *layout {
|
||||
Layout::NullablePointer { nonnull: ref variant_layout,
|
||||
nndiscr,
|
||||
discr: _,
|
||||
discr_offset: _ } => {
|
||||
debug!("print-type-size t: `{:?}` adt nullable nndiscr {} is {:?}",
|
||||
ty, nndiscr, variant_layout);
|
||||
let variant_def = &adt_def.variants[nndiscr as usize];
|
||||
let fields: Vec<_> =
|
||||
variant_def.fields.iter()
|
||||
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
|
||||
.collect();
|
||||
record(adt_kind.into(),
|
||||
None,
|
||||
vec![build_variant_info(Some(variant_def.name),
|
||||
&fields,
|
||||
variant_layout)]);
|
||||
}
|
||||
Layout::Univariant(ref variant_layout) => {
|
||||
let variant_names = || {
|
||||
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
|
||||
@ -1893,7 +1870,8 @@ impl<'a, 'tcx> Layout {
|
||||
}
|
||||
}
|
||||
|
||||
Layout::General { ref variants, discr, .. } => {
|
||||
Layout::NullablePointer { ref variants, .. } |
|
||||
Layout::General { ref variants, .. } => {
|
||||
debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
|
||||
ty, adt_def.variants.len(), variants.len(), variants);
|
||||
let variant_infos: Vec<_> =
|
||||
@ -1910,7 +1888,10 @@ impl<'a, 'tcx> Layout {
|
||||
variant_layout)
|
||||
})
|
||||
.collect();
|
||||
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
|
||||
record(adt_kind.into(), match *layout {
|
||||
Layout::General { discr, .. } => Some(discr.size(tcx)),
|
||||
_ => None
|
||||
}, variant_infos);
|
||||
}
|
||||
|
||||
Layout::UntaggedUnion(ref un) => {
|
||||
@ -2215,19 +2196,13 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
NullablePointer { ref variants, .. } |
|
||||
General { ref variants, .. } => {
|
||||
FieldPlacement::Arbitrary {
|
||||
offsets: &variants[variant_index].offsets
|
||||
}
|
||||
}
|
||||
|
||||
NullablePointer { nndiscr, ref nonnull, .. }
|
||||
if nndiscr as usize == variant_index => {
|
||||
FieldPlacement::Arbitrary {
|
||||
offsets: &nonnull.offsets
|
||||
}
|
||||
}
|
||||
|
||||
_ => FieldPlacement::union(count)
|
||||
};
|
||||
|
||||
@ -2390,14 +2365,20 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
|
||||
}
|
||||
NullablePointer {
|
||||
nndiscr,
|
||||
ref nonnull,
|
||||
ref variants,
|
||||
ref discr,
|
||||
discr_offset,
|
||||
size,
|
||||
align,
|
||||
primitive_align
|
||||
} => {
|
||||
nndiscr.hash_stable(hcx, hasher);
|
||||
nonnull.hash_stable(hcx, hasher);
|
||||
variants.hash_stable(hcx, hasher);
|
||||
discr.hash_stable(hcx, hasher);
|
||||
discr_offset.hash_stable(hcx, hasher);
|
||||
size.hash_stable(hcx, hasher);
|
||||
align.hash_stable(hcx, hasher);
|
||||
primitive_align.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,28 +68,24 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
t: Ty<'tcx>, llty: &mut Type) {
|
||||
let l = cx.layout_of(t);
|
||||
debug!("finish_type_of: {} with layout {:#?}", t, l);
|
||||
if let layout::Abi::Scalar(_) = l.abi {
|
||||
return;
|
||||
}
|
||||
match *l {
|
||||
layout::General { .. } | layout::UntaggedUnion { .. } => { }
|
||||
layout::Univariant { ..} | layout::NullablePointer { .. } => {
|
||||
if let layout::Abi::Scalar(_) = l.abi {
|
||||
return;
|
||||
}
|
||||
let (variant_layout, variant) = match *l {
|
||||
layout::Univariant(ref variant) => {
|
||||
let is_enum = if let ty::TyAdt(def, _) = t.sty {
|
||||
def.is_enum()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if is_enum {
|
||||
(l.for_variant(0), variant)
|
||||
} else {
|
||||
(l, variant)
|
||||
}
|
||||
}
|
||||
layout::NullablePointer { nndiscr, ref nonnull, .. } =>
|
||||
(l.for_variant(nndiscr as usize), nonnull),
|
||||
_ => unreachable!()
|
||||
layout::NullablePointer { .. } |
|
||||
layout::General { .. } |
|
||||
layout::UntaggedUnion { .. } => { }
|
||||
|
||||
layout::Univariant(ref variant) => {
|
||||
let is_enum = if let ty::TyAdt(def, _) = t.sty {
|
||||
def.is_enum()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let variant_layout = if is_enum {
|
||||
l.for_variant(0)
|
||||
} else {
|
||||
l
|
||||
};
|
||||
llty.set_struct_body(&struct_llfields(cx, variant_layout, variant), variant.packed)
|
||||
},
|
||||
@ -106,18 +102,6 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
return cx.llvm_type_of(value.to_ty(cx.tcx()));
|
||||
}
|
||||
match *l {
|
||||
layout::NullablePointer { nndiscr, ref nonnull, .. } => {
|
||||
match name {
|
||||
None => {
|
||||
Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
|
||||
nonnull),
|
||||
nonnull.packed)
|
||||
}
|
||||
Some(name) => {
|
||||
Type::named_struct(cx, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
layout::Univariant(ref variant) => {
|
||||
match name {
|
||||
None => {
|
||||
@ -143,6 +127,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
}
|
||||
layout::NullablePointer { size, align, .. } |
|
||||
layout::General { size, align, .. } => {
|
||||
let fill = union_fill(cx, size, align);
|
||||
match name {
|
||||
|
@ -1218,11 +1218,13 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
}
|
||||
}
|
||||
layout::NullablePointer {
|
||||
nonnull: ref struct_def,
|
||||
nndiscr,
|
||||
discr,
|
||||
discr_offset
|
||||
discr_offset,
|
||||
ref variants,
|
||||
..
|
||||
} => {
|
||||
let struct_def = &variants[nndiscr as usize];
|
||||
// Create a description of the non-null variant
|
||||
let (variant_type_metadata, member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
|
@ -1124,9 +1124,9 @@ fn trans_const_adt<'a, 'tcx>(
|
||||
layout::Vector { .. } => {
|
||||
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
|
||||
}
|
||||
layout::NullablePointer { ref nonnull, nndiscr, .. } => {
|
||||
layout::NullablePointer { ref variants, nndiscr, .. } => {
|
||||
if variant_index as u64 == nndiscr {
|
||||
build_const_struct(ccx, l, &nonnull, vals, None)
|
||||
build_const_struct(ccx, l, &variants[variant_index], vals, None)
|
||||
} else {
|
||||
// Always use null even if it's not the `discrfield`th
|
||||
// field; see #8506.
|
||||
|
@ -273,7 +273,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||
// Check whether the variant being used is packed, if applicable.
|
||||
let is_packed = match (&*l, l.variant_index) {
|
||||
(&layout::Univariant(ref variant), _) => variant.packed,
|
||||
(&layout::NullablePointer { ref nonnull, .. }, _) => nonnull.packed,
|
||||
(&layout::NullablePointer { ref variants, .. }, Some(v)) |
|
||||
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
|
||||
_ => return simple()
|
||||
};
|
||||
@ -471,11 +471,15 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||
|
||||
// If this is an enum, cast to the appropriate variant struct type.
|
||||
let layout = bcx.ccx.layout_of(ty).for_variant(variant_index);
|
||||
if let layout::General { ref variants, .. } = *layout {
|
||||
let st = &variants[variant_index];
|
||||
let variant_ty = Type::struct_(bcx.ccx,
|
||||
&adt::struct_llfields(bcx.ccx, layout, st), st.packed);
|
||||
downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
|
||||
match *layout {
|
||||
layout::NullablePointer { ref variants, .. } |
|
||||
layout::General { ref variants, .. } => {
|
||||
let st = &variants[variant_index];
|
||||
let variant_ty = Type::struct_(bcx.ccx,
|
||||
&adt::struct_llfields(bcx.ccx, layout, st), st.packed);
|
||||
downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
downcast
|
||||
|
@ -259,6 +259,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
||||
adt::memory_index_to_gep(variant.memory_index[index] as u64)
|
||||
}
|
||||
|
||||
Layout::NullablePointer { ref variants, .. } |
|
||||
Layout::General { ref variants, .. } => {
|
||||
if let Some(v) = self.variant_index {
|
||||
adt::memory_index_to_gep(variants[v].memory_index[index] as u64)
|
||||
@ -266,14 +267,6 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
}
|
||||
|
||||
Layout::NullablePointer { nndiscr, ref nonnull, .. } => {
|
||||
if self.variant_index == Some(nndiscr as usize) {
|
||||
adt::memory_index_to_gep(nonnull.memory_index[index] as u64)
|
||||
} else {
|
||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ print-type-size field `.post`: 2 bytes
|
||||
print-type-size field `.pre`: 1 bytes
|
||||
print-type-size end padding: 1 bytes
|
||||
print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
|
||||
print-type-size variant `None`: 0 bytes
|
||||
print-type-size variant `Some`: 12 bytes
|
||||
print-type-size field `.0`: 12 bytes
|
||||
print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
|
||||
print-type-size variant `None`: 0 bytes
|
||||
print-type-size variant `Record`: 7 bytes
|
||||
print-type-size field `.val`: 4 bytes
|
||||
print-type-size field `.post`: 2 bytes
|
||||
@ -18,6 +20,7 @@ print-type-size field `.post`: 2 bytes
|
||||
print-type-size field `.pre`: 1 bytes
|
||||
print-type-size end padding: 1 bytes
|
||||
print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size variant `None`: 0 bytes
|
||||
print-type-size variant `Some`: 4 bytes
|
||||
print-type-size field `.0`: 4 bytes
|
||||
print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes
|
||||
|
Loading…
Reference in New Issue
Block a user