提交 018323ff 编写于 作者: E Eduard-Mihai Burtescu

rustc: collapse the remains of Layout into Variants (enums vs everything else).

上级 b28f668e
......@@ -769,33 +769,17 @@ pub fn is_packed(&self) -> bool {
}
}
/// Type layout, from which size and alignment can be cheaply computed.
/// For ADTs, it also includes field placement and enum optimizations.
/// NOTE: Because Layout is interned, redundant information should be
/// kept to a minimum, e.g. it includes no sub-component Ty or Layout.
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Layout {
/// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr.
Scalar,
/// SIMD vectors, from structs marked with #[repr(simd)].
Vector,
/// TyArray, TySlice or TyStr.
Array,
// Remaining variants are all ADTs such as structs, enums or tuples.
/// Single-case enums, and structs/tuples.
Univariant,
/// Untagged unions.
UntaggedUnion,
pub enum Variants {
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single {
index: usize
},
/// General-case enums: for each case there is a struct, and they all have
/// all space reserved for the discriminant, and their first field starts
/// at a non-0 offset, after where the discriminant would go.
General {
Tagged {
discr: Primitive,
/// Inclusive wrap-around range of discriminant values, that is,
/// if min > max, it represents min..=u64::MAX followed by 0..=max.
......@@ -806,7 +790,7 @@ pub enum Layout {
variants: Vec<CachedLayout>,
},
/// Two cases distinguished by a nullable pointer: the case with discriminant
/// Two cases distinguished by a niche: the case with discriminant
/// `nndiscr` is represented by the struct `nonnull`, where field `0`
/// is known to be nonnull due to its type; if that field is null, then
/// it represents the other case, which is known to be zero sized.
......@@ -814,7 +798,7 @@ pub enum Layout {
/// For example, `std::option::Option` instantiated at a safe pointer type
/// is represented such that `None` is a null pointer and `Some` is the
/// identity function.
NullablePointer {
NicheFilling {
nndiscr: u64,
discr: Primitive,
variants: Vec<CachedLayout>,
......@@ -842,8 +826,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct CachedLayout {
pub variant_index: Option<usize>,
pub layout: Layout,
pub variants: Variants,
pub fields: FieldPlacement,
pub abi: Abi,
pub align: Align,
......@@ -865,7 +848,7 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
tcx.layout_depth.set(depth+1);
let layout = Layout::compute_uncached(tcx, param_env, ty);
let layout = CachedLayout::compute_uncached(tcx, param_env, ty);
tcx.layout_depth.set(depth);
layout
......@@ -878,18 +861,17 @@ pub fn provide(providers: &mut ty::maps::Providers) {
};
}
impl<'a, 'tcx> Layout {
impl<'a, 'tcx> CachedLayout {
fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>)
-> Result<&'tcx CachedLayout, LayoutError<'tcx>> {
-> Result<&'tcx Self, LayoutError<'tcx>> {
let cx = (tcx, param_env);
let dl = cx.data_layout();
let scalar = |value: Primitive| {
let align = value.align(dl);
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Scalar,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Union(0),
abi: Abi::Scalar(value),
size: value.size(dl),
......@@ -1028,8 +1010,7 @@ enum StructKind {
}
Ok(CachedLayout {
variant_index: None,
layout: Layout::Univariant,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Arbitrary {
offsets,
memory_index
......@@ -1073,8 +1054,7 @@ enum StructKind {
memory_index: vec![0, 1]
};
Ok(tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Univariant,
variants: Variants::Single { index: 0 },
fields,
abi: Abi::Aggregate {
sized: true,
......@@ -1129,8 +1109,7 @@ enum StructKind {
.ok_or(LayoutError::SizeOverflow(ty))?;
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Array,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Array {
stride: element.size,
count
......@@ -1147,8 +1126,7 @@ enum StructKind {
ty::TySlice(element) => {
let element = cx.layout_of(element)?;
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Array,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Array {
stride: element.size,
count: 0
......@@ -1164,8 +1142,7 @@ enum StructKind {
}
ty::TyStr => {
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Array,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Array {
stride: Size::from_bytes(1),
count: 0
......@@ -1238,8 +1215,7 @@ enum StructKind {
let size = size.abi_align(align);
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::Vector,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Array {
stride: element.size,
count
......@@ -1302,8 +1278,7 @@ enum StructKind {
}
return Ok(tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::UntaggedUnion,
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Union(variants[0].len()),
abi: Abi::Aggregate {
sized: true,
......@@ -1332,11 +1307,7 @@ enum StructKind {
else { StructKind::AlwaysSized }
};
let mut cached = univariant_uninterned(&variants[0], &def.repr, kind)?;
if def.is_enum() {
cached.variant_index = Some(0);
}
return Ok(tcx.intern_layout(cached));
return univariant(&variants[0], &def.repr, kind);
}
let no_explicit_discriminants = def.variants.iter().enumerate()
......@@ -1359,8 +1330,9 @@ enum StructKind {
univariant_uninterned(&variants[1],
&def.repr, StructKind::AlwaysSized)?
];
st[0].variant_index = Some(0);
st[1].variant_index = Some(1);
for (i, v) in st.iter_mut().enumerate() {
v.variants = Variants::Single { index: i };
}
let offset = st[i].fields.offset(field_index) + offset;
let CachedLayout {
mut abi,
......@@ -1383,8 +1355,7 @@ enum StructKind {
primitive_align = primitive_align.max(discr_align);
return Ok(tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::NullablePointer {
variants: Variants::NicheFilling {
nndiscr: i as u64,
discr,
......@@ -1426,7 +1397,7 @@ enum StructKind {
let mut variants = variants.into_iter().enumerate().map(|(i, field_layouts)| {
let mut st = univariant_uninterned(&field_layouts,
&def.repr, StructKind::EnumVariant(min_ity))?;
st.variant_index = Some(i);
st.variants = Variants::Single { index: i };
// Find the first field we can't move later
// to make room for a larger discriminant.
for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) {
......@@ -1506,8 +1477,7 @@ enum StructKind {
let discr = Int(ity, signed);
tcx.intern_layout(CachedLayout {
variant_index: None,
layout: Layout::General {
variants: Variants::Tagged {
discr,
// FIXME: should be u128?
......@@ -1544,7 +1514,7 @@ enum StructKind {
return Err(LayoutError::Unknown(ty));
}
ty::TyInfer(_) | ty::TyError => {
bug!("Layout::compute: unexpected type `{}`", ty)
bug!("CachedLayout::compute: unexpected type `{}`", ty)
}
})
}
......@@ -1650,8 +1620,8 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
};
match layout.layout {
Layout::Univariant => {
match layout.variants {
Variants::Single { .. } => {
let variant_names = || {
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
};
......@@ -1675,8 +1645,8 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
Layout::NullablePointer { .. } |
Layout::General { .. } => {
Variants::NicheFilling { .. } |
Variants::Tagged { .. } => {
debug!("print-type-size `{:#?}` adt general variants def {}",
ty, adt_def.variants.len());
let variant_infos: Vec<_> =
......@@ -1688,27 +1658,11 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
layout.for_variant(i))
})
.collect();
record(adt_kind.into(), match layout.layout {
Layout::General { discr, .. } => Some(discr.size(tcx)),
record(adt_kind.into(), match layout.variants {
Variants::Tagged { discr, .. } => Some(discr.size(tcx)),
_ => None
}, variant_infos);
}
Layout::UntaggedUnion => {
debug!("print-type-size t: `{:?}` adt union", ty);
// layout does not currently store info about each
// variant...
record(adt_kind.into(), None, Vec::new());
}
// other cases provide little interesting (i.e. adjustable
// via representation tweaks) size info beyond total size.
Layout::Scalar |
Layout::Vector |
Layout::Array => {
debug!("print-type-size t: `{:?}` adt other", ty);
record(adt_kind.into(), None, Vec::new())
}
}
}
}
......@@ -1950,7 +1904,7 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
// completed, to avoid problems around recursive structures
// and the like. (Admitedly, I wasn't able to reproduce a problem
// here, but it seems like the right thing to do. -nmatsakis)
Layout::record_layout_for_printing(tcx, ty, param_env, layout);
CachedLayout::record_layout_for_printing(tcx, ty, param_env, layout);
Ok(layout)
}
......@@ -1979,7 +1933,7 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
// completed, to avoid problems around recursive structures
// and the like. (Admitedly, I wasn't able to reproduce a problem
// here, but it seems like the right thing to do. -nmatsakis)
Layout::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
CachedLayout::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
Ok(layout)
}
......@@ -1987,15 +1941,15 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
impl<'a, 'tcx> TyLayout<'tcx> {
pub fn for_variant(&self, variant_index: usize) -> Self {
let cached = match self.layout {
Layout::NullablePointer { ref variants, .. } |
Layout::General { ref variants, .. } => {
let cached = match self.variants {
Variants::Single { .. } => self.cached,
Variants::NicheFilling { ref variants, .. } |
Variants::Tagged { ref variants, .. } => {
&variants[variant_index]
}
_ => self.cached
};
assert_eq!(cached.variant_index, Some(variant_index));
assert_eq!(cached.variants, Variants::Single { index: variant_index });
TyLayout {
ty: self.ty,
......@@ -2081,26 +2035,17 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
// ADTs.
ty::TyAdt(def, substs) => {
let v = if def.is_enum() {
match self.variant_index {
None => match self.layout {
// Discriminant field for enums (where applicable).
Layout::General { discr, .. } |
Layout::NullablePointer { discr, .. } => {
return cx.layout_of([discr.to_ty(tcx)][i]);
}
_ => {
bug!("TyLayout::field_type: enum `{}` has no discriminant",
self.ty)
}
},
Some(v) => v
match self.variants {
Variants::Single { index } => {
def.variants[index].fields[i].ty(tcx, substs)
}
} else {
0
};
def.variants[v].fields[i].ty(tcx, substs)
// Discriminant field for enums (where applicable).
Variants::Tagged { discr, .. } |
Variants::NicheFilling { discr, .. } => {
return cx.layout_of([discr.to_ty(tcx)][i]);
}
}
}
ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
......@@ -2143,18 +2088,18 @@ fn non_zero_field<C>(&self, cx: C)
HasTyCtxt<'tcx>
{
let tcx = cx.tcx();
match (&self.layout, self.abi, &self.ty.sty) {
match (&self.variants, self.abi, &self.ty.sty) {
// FIXME(eddyb) check this via value ranges on scalars.
(&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyRef(..)) |
(&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyFnPtr(..)) => {
(_, Abi::Scalar(Pointer), &ty::TyRef(..)) |
(_, Abi::Scalar(Pointer), &ty::TyFnPtr(..)) => {
Ok(Some((Size::from_bytes(0), Pointer)))
}
(&Layout::Scalar, Abi::Scalar(Pointer), &ty::TyAdt(def, _)) if def.is_box() => {
(_, Abi::Scalar(Pointer), &ty::TyAdt(def, _)) if def.is_box() => {
Ok(Some((Size::from_bytes(0), Pointer)))
}
// FIXME(eddyb) check this via value ranges on scalars.
(&Layout::General { discr, .. }, _, &ty::TyAdt(def, _)) => {
(&Variants::Tagged { discr, .. }, _, &ty::TyAdt(def, _)) => {
if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
Ok(Some((self.fields.offset(0), discr)))
} else {
......@@ -2196,20 +2141,18 @@ fn non_zero_field<C>(&self, cx: C)
}
}
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout {
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Variants {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
use ty::layout::Layout::*;
use ty::layout::Variants::*;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
Scalar => {}
Vector => {}
Array => {}
Univariant => {}
UntaggedUnion => {}
General {
Single { index } => {
index.hash_stable(hcx, hasher);
}
Tagged {
discr,
discr_range: RangeInclusive { start, end },
ref variants,
......@@ -2219,7 +2162,7 @@ fn hash_stable<W: StableHasherResult>(&self,
end.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
}
NullablePointer {
NicheFilling {
nndiscr,
ref variants,
ref discr,
......@@ -2279,8 +2222,7 @@ fn hash_stable<W: StableHasherResult>(&self,
}
impl_stable_hash_for!(struct ::ty::layout::CachedLayout {
variant_index,
layout,
variants,
fields,
abi,
size,
......
......@@ -13,7 +13,7 @@
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
use rustc::ty::layout::{Layout, LayoutOf};
use rustc::ty::layout::{self, LayoutOf};
use middle::const_val::ConstVal;
use rustc_const_eval::ConstContext;
use util::nodemap::FxHashSet;
......@@ -753,7 +753,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
bug!("failed to get layout for `{}`: {}", t, e)
});
if let Layout::General { ref variants, discr, .. } = layout.layout {
if let layout::Variants::Tagged { ref variants, discr, .. } = layout.variants {
let discr_size = discr.size(cx.tcx).bytes();
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
......
......@@ -14,7 +14,7 @@
use abi::{ArgType, ArgAttribute, CastTarget, FnType, LayoutExt, Reg, RegKind};
use context::CrateContext;
use rustc::ty::layout::{self, Layout, TyLayout, Size};
use rustc::ty::layout::{self, TyLayout, Size};
#[derive(Clone, Copy, PartialEq, Debug)]
enum Class {
......@@ -87,17 +87,15 @@ fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
layout::Abi::Aggregate { .. } => {
// FIXME(eddyb) have to work around Rust enums for now.
// Fix is either guarantee no data where there is no field,
// by putting variants in fields, or be more clever.
match layout.layout {
Layout::General { .. } |
Layout::NullablePointer { .. } => return Err(Memory),
_ => {}
}
for i in 0..layout.fields.count() {
let field_off = off + layout.fields.offset(i);
classify(ccx, layout.field(ccx, i), cls, field_off)?;
match layout.variants {
layout::Variants::Single { .. } => {
for i in 0..layout.fields.count() {
let field_off = off + layout.fields.offset(i);
classify(ccx, layout.field(ccx, i), cls, field_off)?;
}
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => return Err(Memory),
}
}
......
......@@ -1119,7 +1119,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// offset of zero bytes).
struct EnumMemberDescriptionFactory<'tcx> {
enum_type: Ty<'tcx>,
type_rep: TyLayout<'tcx>,
layout: TyLayout<'tcx>,
discriminant_type_metadata: Option<DIType>,
containing_scope: DIScope,
span: Span,
......@@ -1129,37 +1129,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-> Vec<MemberDescription> {
let adt = &self.enum_type.ty_adt_def().unwrap();
match self.type_rep.layout {
layout::Layout::General { ref variants, .. } => {
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
.expect(""));
(0..variants.len()).map(|i| {
let variant = self.type_rep.for_variant(i);
let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx,
variant,
&adt.variants[i],
discriminant_info,
self.containing_scope,
self.span);
let member_descriptions = member_desc_factory
.create_member_descriptions(cx);
set_members_of_composite_type(cx,
variant_type_metadata,
&member_descriptions);
MemberDescription {
name: "".to_string(),
type_metadata: variant_type_metadata,
offset: Size::from_bytes(0),
size: variant.size,
align: variant.align,
flags: DIFlags::FlagZero
}
}).collect()
},
layout::Layout::Univariant => {
match self.layout.variants {
layout::Variants::Single { .. } => {
assert!(adt.variants.len() <= 1);
if adt.variants.is_empty() {
......@@ -1167,7 +1138,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
} else {
let (variant_type_metadata, member_description_factory) =
describe_enum_variant(cx,
self.type_rep,
self.layout,
&adt.variants[0],
NoDiscriminant,
self.containing_scope,
......@@ -1184,19 +1155,48 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
name: "".to_string(),
type_metadata: variant_type_metadata,
offset: Size::from_bytes(0),
size: self.type_rep.size,
align: self.type_rep.align,
size: self.layout.size,
align: self.layout.align,
flags: DIFlags::FlagZero
}
]
}
}
layout::Layout::NullablePointer {
layout::Variants::Tagged { ref variants, .. } => {
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
.expect(""));
(0..variants.len()).map(|i| {
let variant = self.layout.for_variant(i);
let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx,
variant,
&adt.variants[i],
discriminant_info,
self.containing_scope,
self.span);
let member_descriptions = member_desc_factory
.create_member_descriptions(cx);
set_members_of_composite_type(cx,
variant_type_metadata,
&member_descriptions);
MemberDescription {
name: "".to_string(),
type_metadata: variant_type_metadata,
offset: Size::from_bytes(0),
size: variant.size,
align: variant.align,
flags: DIFlags::FlagZero
}
}).collect()
}
layout::Variants::NicheFilling {
nndiscr,
discr,
..
} => {
let variant = self.type_rep.for_variant(nndiscr as usize);
let variant = self.layout.for_variant(nndiscr as usize);
// Create a description of the non-null variant
let (variant_type_metadata, member_description_factory) =
describe_enum_variant(cx,
......@@ -1237,8 +1237,8 @@ fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
}
compute_field_path(cx, &mut name,
self.type_rep,
self.type_rep.fields.offset(0),
self.layout,
self.layout.fields.offset(0),
discr.size(cx));
name.push_str(&adt.variants[(1 - nndiscr) as usize].name.as_str());
......@@ -1253,8 +1253,7 @@ fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
flags: DIFlags::FlagZero
}
]
},
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
}
}
}
}
......@@ -1429,21 +1428,20 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
};
let type_rep = cx.layout_of(enum_type);
let layout = cx.layout_of(enum_type);
let discriminant_type_metadata = match type_rep.layout {
layout::Layout::NullablePointer { .. } |
layout::Layout::Univariant { .. } => None,
layout::Layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
let discriminant_type_metadata = match layout.variants {
layout::Variants::Single { .. } |
layout::Variants::NicheFilling { .. } => None,
layout::Variants::Tagged { discr, .. } => Some(discriminant_type_metadata(discr)),
};
match (type_rep.abi, discriminant_type_metadata) {
match (layout.abi, discriminant_type_metadata) {
(layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr),
_ => {}
}
let (enum_type_size, enum_type_align) = type_rep.size_and_align();
let (enum_type_size, enum_type_align) = layout.size_and_align();
let enum_name = CString::new(enum_name).unwrap();
let unique_type_id_str = CString::new(
......@@ -1471,7 +1469,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
enum_metadata,
EnumMDF(EnumMemberDescriptionFactory {
enum_type,
type_rep,
layout,
discriminant_type_metadata,
containing_scope,
span,
......
......@@ -394,12 +394,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
},
"discriminant_value" => {
match substs.type_at(0).sty {
ty::TyAdt(adt, ..) if adt.is_enum() => {
args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty)
}
_ => C_null(llret_ty)
}
args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty)
}
"align_offset" => {
......
......@@ -1094,8 +1094,26 @@ fn trans_const_adt<'a, 'tcx>(
mir::AggregateKind::Adt(_, index, _, _) => index,
_ => 0,
};
match l.layout {
layout::Layout::General { .. } => {
match l.variants {
layout::Variants::Single { index } => {
assert_eq!(variant_index, index);
if let layout::Abi::Vector { .. } = l.abi {
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
} else if let layout::FieldPlacement::Union(_) = l.fields {
assert_eq!(variant_index, 0);
assert_eq!(vals.len(), 1);
let contents = [
vals[0].llval,
padding(ccx, l.size - ccx.size_of(vals[0].ty))
];
Const::new(C_struct(ccx, &contents, l.is_packed()), t)
} else {
assert_eq!(variant_index, 0);
build_const_struct(ccx, l, vals, None)
}
}
layout::Variants::Tagged { .. } => {
let discr = match *kind {
mir::AggregateKind::Adt(adt_def, _, _, _) => {
adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
......@@ -1112,23 +1130,7 @@ fn trans_const_adt<'a, 'tcx>(
build_const_struct(ccx, l.for_variant(variant_index), vals, Some(discr))
}
}
layout::Layout::UntaggedUnion => {
assert_eq!(variant_index, 0);
let contents = [
vals[0].llval,
padding(ccx, l.size - ccx.size_of(vals[0].ty))
];
Const::new(C_struct(ccx, &contents, l.is_packed()), t)
}
layout::Layout::Univariant => {
assert_eq!(variant_index, 0);
build_const_struct(ccx, l, vals, None)
}
layout::Layout::Vector => {
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
}
layout::Layout::NullablePointer { nndiscr, .. } => {
layout::Variants::NicheFilling { nndiscr, .. } => {
if variant_index as u64 == nndiscr {
build_const_struct(ccx, l.for_variant(variant_index), vals, None)
} else {
......@@ -1137,7 +1139,6 @@ fn trans_const_adt<'a, 'tcx>(
Const::new(C_null(ccx.layout_of(t).llvm_type(ccx)), t)
}
}
_ => bug!("trans_const_adt: cannot handle type {} repreented as {:#?}", t, l)
}
}
......
......@@ -296,10 +296,13 @@ pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> LvalueRef<'tcx
/// Obtain the actual discriminant of a value.
pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
let cast_to = bcx.ccx.layout_of(cast_to).immediate_llvm_type(bcx.ccx);
match self.layout.layout {
layout::Layout::Univariant { .. } |
layout::Layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
_ => {}
match self.layout.variants {
layout::Variants::Single { index } => {
assert_eq!(index, 0);
return C_uint(cast_to, 0);
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {},
}
let discr = self.project_field(bcx, 0);
......@@ -307,8 +310,10 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
layout::Abi::Scalar(discr) => discr,
_ => bug!("discriminant not scalar: {:#?}", discr.layout)
};
let (min, max) = match self.layout.layout {
layout::Layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
let (min, max) = match self.layout.variants {
layout::Variants::Tagged { ref discr_range, .. } => {
(discr_range.start, discr_range.end)
}
_ => (0, u64::max_value()),
};
let max_next = max.wrapping_add(1);
......@@ -333,20 +338,20 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
bcx.load(discr.llval, discr.alignment.non_abi())
}
};
match self.layout.layout {
layout::Layout::General { .. } => {
match self.layout.variants {
layout::Variants::Single { .. } => bug!(),
layout::Variants::Tagged { .. } => {
let signed = match discr_scalar {
layout::Int(_, signed) => signed,
_ => false
};
bcx.intcast(lldiscr, cast_to, signed)
}
layout::Layout::NullablePointer { nndiscr, .. } => {
layout::Variants::NicheFilling { nndiscr, .. } => {
let cmp = if nndiscr == 0 { llvm::IntEQ } else { llvm::IntNE };
let zero = C_null(discr.layout.llvm_type(bcx.ccx));
bcx.intcast(bcx.icmp(cmp, lldiscr, zero), cast_to, false)
}
_ => bug!("{} is not an enum", self.layout.ty)
}
}
......@@ -356,13 +361,17 @@ pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
let to = self.layout.ty.ty_adt_def().unwrap()
.discriminant_for_variant(bcx.tcx(), variant_index)
.to_u128_unchecked() as u64;
match self.layout.layout {
layout::Layout::General { .. } => {
match self.layout.variants {
layout::Variants::Single { index } => {
assert_eq!(to, 0);
assert_eq!(variant_index, index);
}
layout::Variants::Tagged { .. } => {
let ptr = self.project_field(bcx, 0);
bcx.store(C_int(ptr.layout.llvm_type(bcx.ccx), to as i64),
ptr.llval, ptr.alignment.non_abi());
}
layout::Layout::NullablePointer { nndiscr, .. } => {
layout::Variants::NicheFilling { nndiscr, .. } => {
if to != nndiscr {
let use_memset = match self.layout.abi {
layout::Abi::Scalar(_) => false,
......@@ -385,9 +394,6 @@ pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
}
}
}
_ => {
assert_eq!(to, 0);
}
}
}
......
......@@ -11,7 +11,7 @@
use llvm::{self, ValueRef};
use rustc::ty::{self, Ty};
use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::layout::{self, Layout, LayoutOf};
use rustc::ty::layout::{self, LayoutOf};
use rustc::mir;
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
use rustc_apfloat::{ieee, Float, Status, Round};
......@@ -278,8 +278,10 @@ pub fn trans_rvalue_operand(&mut self,
let ll_t_out = cast.immediate_llvm_type(bcx.ccx);
let llval = operand.immediate();
if let Layout::General { ref discr_range, .. } = operand.layout.layout {
if discr_range.end > discr_range.start {
match operand.layout.variants {
layout::Variants::Tagged {
ref discr_range, ..
} if discr_range.end > discr_range.start => {
// We want `table[e as usize]` to not
// have bound checks, and this is the most
// convenient place to put the `assume`.
......@@ -290,6 +292,7 @@ pub fn trans_rvalue_operand(&mut self,
C_uint(ll_t_in, discr_range.end)
));
}
_ => {}
}
let signed = match operand.layout.abi {
......
......@@ -40,8 +40,13 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let mut name = String::with_capacity(32);
let printer = DefPathBasedNames::new(ccx.tcx(), true, true);
printer.push_type_name(layout.ty, &mut name);
if let (&ty::TyAdt(def, _), Some(v)) = (&layout.ty.sty, layout.variant_index) {
write!(&mut name, "::{}", def.variants[v].name).unwrap();
match (&layout.ty.sty, &layout.variants) {
(&ty::TyAdt(def, _), &layout::Variants::Single { index }) => {
if def.is_enum() && !def.variants.is_empty() {
write!(&mut name, "::{}", def.variants[index].name).unwrap();
}
}
_ => {}
}
Some(name)
}
......@@ -206,7 +211,11 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
// Check the cache.
if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, self.variant_index)) {
let variant_index = match self.variants {
layout::Variants::Single { index } => Some(index),
_ => None
};
if let Some(&llty) = ccx.lltypes().borrow().get(&(self.ty, variant_index)) {
return llty;
}
......@@ -221,7 +230,7 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
let mut defer = None;
let llty = if self.ty != normal_ty {
let mut layout = ccx.layout_of(normal_ty);
if let Some(v) = self.variant_index {
if let Some(v) = variant_index {
layout = layout.for_variant(v);
}
layout.llvm_type(ccx)
......@@ -230,7 +239,7 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
};
debug!("--> mapped {:#?} to llty={:?}", self, llty);
ccx.lltypes().borrow_mut().insert((self.ty, self.variant_index), llty);
ccx.lltypes().borrow_mut().insert((self.ty, variant_index), llty);
if let Some((mut llty, layout)) = defer {
llty.set_struct_body(&struct_llfields(ccx, layout), layout.is_packed())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册