rustc: store CachedLayout for each variant of enum Layout's instead of Struct.
This commit is contained in:
parent
bd51a2bc19
commit
ed788a62f6
8 changed files with 131 additions and 175 deletions
|
@ -78,7 +78,7 @@ use hir;
|
|||
/// Internal storage
|
||||
pub struct GlobalArenas<'tcx> {
|
||||
// internings
|
||||
layout: TypedArena<Layout>,
|
||||
layout: TypedArena<Layout<'tcx>>,
|
||||
|
||||
// references
|
||||
generics: TypedArena<ty::Generics>,
|
||||
|
@ -918,7 +918,7 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
|
||||
|
||||
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
|
||||
layout_interner: RefCell<FxHashSet<&'tcx Layout<'tcx>>>,
|
||||
|
||||
/// A vector of every trait accessible in the whole crate
|
||||
/// (i.e. including those from subcrates). This is used only for
|
||||
|
@ -1016,7 +1016,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
interned
|
||||
}
|
||||
|
||||
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
|
||||
pub fn intern_layout(self, layout: Layout<'gcx>) -> &'gcx Layout<'gcx> {
|
||||
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
|
||||
return layout;
|
||||
}
|
||||
|
|
|
@ -1004,7 +1004,7 @@ pub const FAT_PTR_ADDR: usize = 0;
|
|||
pub const FAT_PTR_EXTRA: usize = 1;
|
||||
|
||||
/// Describes how the fields of a type are located in memory.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum FieldPlacement<'a> {
|
||||
/// Array-like placement. Can also express
|
||||
/// unions, by using a stride of zero bytes.
|
||||
|
@ -1058,7 +1058,7 @@ impl<'a> FieldPlacement<'a> {
|
|||
|
||||
/// Describes how values of the type are passed by target ABIs,
|
||||
/// in terms of categories of C types there are ABI rules for.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Abi {
|
||||
Scalar(Primitive),
|
||||
Vector {
|
||||
|
@ -1141,8 +1141,8 @@ impl Abi {
|
|||
/// 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(Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Layout {
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Layout<'a> {
|
||||
/// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr.
|
||||
Scalar(Primitive),
|
||||
|
||||
|
@ -1184,7 +1184,7 @@ pub enum Layout {
|
|||
// the largest space between two consecutive discriminants and
|
||||
// taking everything else as the (shortest) discriminant range.
|
||||
discr_range: RangeInclusive<u64>,
|
||||
variants: Vec<Struct>,
|
||||
variants: Vec<CachedLayout<'a>>,
|
||||
size: Size,
|
||||
align: Align,
|
||||
primitive_align: Align,
|
||||
|
@ -1202,7 +1202,7 @@ pub enum Layout {
|
|||
nndiscr: u64,
|
||||
discr: Primitive,
|
||||
discr_offset: Size,
|
||||
variants: Vec<Struct>,
|
||||
variants: Vec<CachedLayout<'a>>,
|
||||
size: Size,
|
||||
align: Align,
|
||||
primitive_align: Align,
|
||||
|
@ -1228,9 +1228,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct CachedLayout<'tcx> {
|
||||
pub layout: &'tcx Layout,
|
||||
pub layout: &'tcx Layout<'tcx>,
|
||||
pub fields: FieldPlacement<'tcx>,
|
||||
pub abi: Abi,
|
||||
}
|
||||
|
@ -1262,7 +1262,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
|
|||
};
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Layout {
|
||||
impl<'a, 'tcx> Layout<'tcx> {
|
||||
fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>)
|
||||
|
@ -1624,7 +1624,9 @@ impl<'a, 'tcx> Layout {
|
|||
size: st[discr].stride(),
|
||||
align,
|
||||
primitive_align,
|
||||
variants: st,
|
||||
variants: st.into_iter().map(|variant| {
|
||||
success(Univariant(variant))
|
||||
}).collect::<Result<Vec<_>, _>>()?,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1730,7 +1732,9 @@ impl<'a, 'tcx> Layout {
|
|||
|
||||
// FIXME: should be u128?
|
||||
discr_range: (min as u64)..=(max as u64),
|
||||
variants,
|
||||
variants: variants.into_iter().map(|variant| {
|
||||
success(Univariant(variant))
|
||||
}).collect::<Result<Vec<_>, _>>()?,
|
||||
size,
|
||||
align,
|
||||
primitive_align,
|
||||
|
@ -1897,6 +1901,10 @@ impl<'a, 'tcx> Layout {
|
|||
.iter()
|
||||
.map(|f| (f.name, f.ty(tcx, substs)))
|
||||
.collect();
|
||||
let variant_layout = match *variant_layout.layout {
|
||||
Univariant(ref variant) => variant,
|
||||
_ => bug!()
|
||||
};
|
||||
build_variant_info(Some(variant_def.name),
|
||||
&fields,
|
||||
variant_layout)
|
||||
|
@ -2084,7 +2092,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
|
|||
pub struct FullLayout<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub variant_index: Option<usize>,
|
||||
pub layout: &'tcx Layout,
|
||||
pub layout: &'tcx Layout<'tcx>,
|
||||
pub fields: FieldPlacement<'tcx>,
|
||||
pub abi: Abi,
|
||||
}
|
||||
|
@ -2198,27 +2206,22 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
|||
variants[variant_index].fields.len()
|
||||
};
|
||||
|
||||
let (fields, abi) = match *self.layout {
|
||||
Univariant(_) => (self.fields, self.abi),
|
||||
let (layout, fields, abi) = match *self.layout {
|
||||
Univariant(_) => (self.layout, self.fields, self.abi),
|
||||
|
||||
NullablePointer { ref variants, .. } |
|
||||
General { ref variants, .. } => {
|
||||
let variant = &variants[variant_index];
|
||||
(FieldPlacement::Arbitrary {
|
||||
offsets: &variant.offsets
|
||||
}, Abi::Aggregate {
|
||||
sized: true,
|
||||
align: variant.align,
|
||||
primitive_align: variant.primitive_align,
|
||||
size: variant.stride(),
|
||||
})
|
||||
let variant = variants[variant_index];
|
||||
(variant.layout, variant.fields, variant.abi)
|
||||
}
|
||||
|
||||
_ => (FieldPlacement::union(count), self.abi)
|
||||
_ => bug!()
|
||||
};
|
||||
assert_eq!(fields.count(), count);
|
||||
|
||||
FullLayout {
|
||||
variant_index: Some(variant_index),
|
||||
layout,
|
||||
fields,
|
||||
abi,
|
||||
..*self
|
||||
|
@ -2348,8 +2351,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
|
||||
{
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout<'gcx> {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'gcx>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
|
|
|
@ -764,7 +764,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||
.zip(variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// Subtract the size of the enum discriminant
|
||||
let bytes = variant_layout.min_size
|
||||
let bytes = variant_layout.abi.size(cx.tcx)
|
||||
.bytes()
|
||||
.saturating_sub(discr_size);
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
} else {
|
||||
l
|
||||
};
|
||||
llty.set_struct_body(&struct_llfields(cx, variant_layout, variant), variant.packed)
|
||||
llty.set_struct_body(&struct_llfields(cx, variant_layout), variant.packed)
|
||||
},
|
||||
_ => bug!("This function cannot handle {} with layout {:#?}", t, l)
|
||||
}
|
||||
|
@ -105,8 +105,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
layout::Univariant(ref variant) => {
|
||||
match name {
|
||||
None => {
|
||||
Type::struct_(cx, &struct_llfields(cx, l, &variant),
|
||||
variant.packed)
|
||||
Type::struct_(cx, &struct_llfields(cx, l), variant.packed)
|
||||
}
|
||||
Some(name) => {
|
||||
Type::named_struct(cx, name)
|
||||
|
@ -166,8 +165,11 @@ pub fn memory_index_to_gep(index: u64) -> u64 {
|
|||
}
|
||||
|
||||
pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
layout: FullLayout<'tcx>,
|
||||
variant: &layout::Struct) -> Vec<Type> {
|
||||
layout: FullLayout<'tcx>) -> Vec<Type> {
|
||||
let variant = match *layout.layout {
|
||||
layout::Univariant(ref variant) => variant,
|
||||
_ => bug!("unexpected {:#?}", layout)
|
||||
};
|
||||
let field_count = layout.fields.count();
|
||||
debug!("struct_llfields: variant: {:?}", variant);
|
||||
let mut offset = Size::from_bytes(0);
|
||||
|
|
|
@ -1153,37 +1153,33 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
layout::General { ref variants, .. } => {
|
||||
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
|
||||
.expect(""));
|
||||
variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, struct_def)| {
|
||||
let (variant_type_metadata, member_desc_factory) =
|
||||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
i,
|
||||
&adt.variants[i],
|
||||
discriminant_info,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
(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);
|
||||
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: struct_def.stride(),
|
||||
align: struct_def.align,
|
||||
flags: DIFlags::FlagZero
|
||||
}
|
||||
}).collect()
|
||||
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(cx),
|
||||
align: variant.align(cx),
|
||||
flags: DIFlags::FlagZero
|
||||
}
|
||||
}).collect()
|
||||
},
|
||||
layout::Univariant(ref variant) => {
|
||||
layout::Univariant(_) => {
|
||||
assert!(adt.variants.len() <= 1);
|
||||
|
||||
if adt.variants.is_empty() {
|
||||
|
@ -1191,9 +1187,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
} else {
|
||||
let (variant_type_metadata, member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
variant,
|
||||
0,
|
||||
self.type_rep,
|
||||
&adt.variants[0],
|
||||
NoDiscriminant,
|
||||
self.containing_scope,
|
||||
|
@ -1210,8 +1204,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
name: "".to_string(),
|
||||
type_metadata: variant_type_metadata,
|
||||
offset: Size::from_bytes(0),
|
||||
size: variant.stride(),
|
||||
align: variant.align,
|
||||
size: self.type_rep.size(cx),
|
||||
align: self.type_rep.align(cx),
|
||||
flags: DIFlags::FlagZero
|
||||
}
|
||||
]
|
||||
|
@ -1221,16 +1215,13 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
nndiscr,
|
||||
discr,
|
||||
discr_offset,
|
||||
ref variants,
|
||||
..
|
||||
} => {
|
||||
let struct_def = &variants[nndiscr as usize];
|
||||
let variant = self.type_rep.for_variant(nndiscr as usize);
|
||||
// Create a description of the non-null variant
|
||||
let (variant_type_metadata, member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
nndiscr as usize,
|
||||
variant,
|
||||
&adt.variants[nndiscr as usize],
|
||||
OptimizedDiscriminant,
|
||||
self.containing_scope,
|
||||
|
@ -1278,8 +1269,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
name,
|
||||
type_metadata: variant_type_metadata,
|
||||
offset: Size::from_bytes(0),
|
||||
size: struct_def.stride(),
|
||||
align: struct_def.align,
|
||||
size: variant.size(cx),
|
||||
align: variant.align(cx),
|
||||
flags: DIFlags::FlagZero
|
||||
}
|
||||
]
|
||||
|
@ -1330,78 +1321,48 @@ enum EnumDiscriminantInfo {
|
|||
// descriptions of the fields of the variant. This is a rudimentary version of a
|
||||
// full RecursiveTypeDescription.
|
||||
fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
enum_type: Ty<'tcx>,
|
||||
struct_def: &'tcx layout::Struct,
|
||||
variant_index: usize,
|
||||
layout: layout::FullLayout<'tcx>,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
discriminant_info: EnumDiscriminantInfo,
|
||||
containing_scope: DIScope,
|
||||
span: Span)
|
||||
-> (DICompositeType, MemberDescriptionFactory<'tcx>) {
|
||||
let layout = cx.layout_of(enum_type);
|
||||
let maybe_discr = match *layout.layout {
|
||||
layout::General { .. } => Some(layout.field(cx, 0).ty),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let layout = layout.for_variant(variant_index);
|
||||
let mut field_tys = (0..layout.fields.count()).map(|i| {
|
||||
layout.field(cx, i).ty
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
if let Some(discr) = maybe_discr {
|
||||
field_tys.insert(0, discr);
|
||||
}
|
||||
|
||||
// Could do some consistency checks here: size, align, field count, discr type
|
||||
|
||||
let variant_name = variant.name.as_str();
|
||||
let unique_type_id = debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_enum_variant(
|
||||
cx,
|
||||
enum_type,
|
||||
layout.ty,
|
||||
&variant_name);
|
||||
|
||||
let metadata_stub = create_struct_stub(cx,
|
||||
enum_type,
|
||||
layout.ty,
|
||||
&variant_name,
|
||||
unique_type_id,
|
||||
containing_scope);
|
||||
|
||||
// Get the argument names from the enum variant info
|
||||
let mut arg_names: Vec<_> = match variant.ctor_kind {
|
||||
CtorKind::Const => vec![],
|
||||
CtorKind::Fn => {
|
||||
variant.fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| format!("__{}", i))
|
||||
.collect()
|
||||
}
|
||||
CtorKind::Fictive => {
|
||||
variant.fields
|
||||
.iter()
|
||||
.map(|f| f.name.to_string())
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
// If this is not a univariant enum, there is also the discriminant field.
|
||||
let mut offsets = struct_def.offsets.clone();
|
||||
match discriminant_info {
|
||||
let (discr_offset, discr_arg) = match discriminant_info {
|
||||
RegularDiscriminant(_) => {
|
||||
arg_names.insert(0, "RUST$ENUM$DISR".to_string());
|
||||
offsets.insert(0, Size::from_bytes(0));
|
||||
let enum_layout = cx.layout_of(layout.ty);
|
||||
(Some(enum_layout.fields.offset(0)),
|
||||
Some(("RUST$ENUM$DISR".to_string(), enum_layout.field(cx, 0).ty)))
|
||||
}
|
||||
_ => { /* do nothing */ }
|
||||
_ => (None, None),
|
||||
};
|
||||
let offsets = discr_offset.into_iter().chain((0..layout.fields.count()).map(|i| {
|
||||
layout.fields.offset(i)
|
||||
})).collect();
|
||||
|
||||
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
||||
let args: Vec<(String, Ty)> = arg_names.iter()
|
||||
.zip(field_tys.iter())
|
||||
.map(|(s, &t)| (s.to_string(), t))
|
||||
.collect();
|
||||
let args = discr_arg.into_iter().chain((0..layout.fields.count()).map(|i| {
|
||||
let name = if variant.ctor_kind == CtorKind::Fn {
|
||||
format!("__{}", i)
|
||||
} else {
|
||||
variant.fields[i].name.to_string()
|
||||
};
|
||||
(name, layout.field(cx, i).ty)
|
||||
})).collect();
|
||||
|
||||
let member_description_factory =
|
||||
VariantMDF(VariantMemberDescriptionFactory {
|
||||
|
|
|
@ -1091,7 +1091,7 @@ fn trans_const_adt<'a, 'tcx>(
|
|||
_ => 0,
|
||||
};
|
||||
match *l.layout {
|
||||
layout::General { ref variants, .. } => {
|
||||
layout::General { .. } => {
|
||||
let discr = match *kind {
|
||||
mir::AggregateKind::Adt(adt_def, _, _, _) => {
|
||||
adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
|
||||
|
@ -1105,7 +1105,7 @@ fn trans_const_adt<'a, 'tcx>(
|
|||
if let layout::Abi::Scalar(_) = l.abi {
|
||||
discr
|
||||
} else {
|
||||
build_const_struct(ccx, l, &variants[variant_index], vals, Some(discr))
|
||||
build_const_struct(ccx, l.for_variant(variant_index), vals, Some(discr))
|
||||
}
|
||||
}
|
||||
layout::UntaggedUnion(ref un) => {
|
||||
|
@ -1117,16 +1117,16 @@ fn trans_const_adt<'a, 'tcx>(
|
|||
|
||||
Const::new(C_struct(ccx, &contents, un.packed), t)
|
||||
}
|
||||
layout::Univariant(ref variant) => {
|
||||
layout::Univariant(_) => {
|
||||
assert_eq!(variant_index, 0);
|
||||
build_const_struct(ccx, l, &variant, vals, None)
|
||||
build_const_struct(ccx, l, vals, None)
|
||||
}
|
||||
layout::Vector { .. } => {
|
||||
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
|
||||
}
|
||||
layout::NullablePointer { ref variants, nndiscr, .. } => {
|
||||
layout::NullablePointer { nndiscr, .. } => {
|
||||
if variant_index as u64 == nndiscr {
|
||||
build_const_struct(ccx, l, &variants[variant_index], vals, None)
|
||||
build_const_struct(ccx, l.for_variant(variant_index), vals, None)
|
||||
} else {
|
||||
// Always use null even if it's not the `discrfield`th
|
||||
// field; see #8506.
|
||||
|
@ -1147,24 +1147,27 @@ fn trans_const_adt<'a, 'tcx>(
|
|||
/// will read the wrong memory.
|
||||
fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
layout: layout::FullLayout<'tcx>,
|
||||
st: &layout::Struct,
|
||||
vals: &[Const<'tcx>],
|
||||
discr: Option<Const<'tcx>>)
|
||||
-> Const<'tcx> {
|
||||
assert_eq!(vals.len(), st.offsets.len());
|
||||
assert_eq!(vals.len(), layout.fields.count());
|
||||
|
||||
// offset of current value
|
||||
let mut offset = Size::from_bytes(0);
|
||||
let mut cfields = Vec::new();
|
||||
cfields.reserve(discr.is_some() as usize + 1 + st.offsets.len() * 2);
|
||||
cfields.reserve(discr.is_some() as usize + 1 + layout.fields.count() * 2);
|
||||
|
||||
if let Some(discr) = discr {
|
||||
cfields.push(discr.llval);
|
||||
offset = ccx.size_of(discr.ty);
|
||||
}
|
||||
|
||||
let st = match *layout.layout {
|
||||
layout::Univariant(ref variant) => variant,
|
||||
_ => bug!("unexpected {:#?}", layout)
|
||||
};
|
||||
let parts = st.field_index_by_increasing_offset().map(|i| {
|
||||
(vals[i], st.offsets[i])
|
||||
(vals[i], layout.fields.offset(i))
|
||||
});
|
||||
for (val, target_offset) in parts {
|
||||
cfields.push(padding(ccx, target_offset - offset));
|
||||
|
@ -1172,8 +1175,8 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
offset = target_offset + ccx.size_of(val.ty);
|
||||
}
|
||||
|
||||
let size = layout.size(ccx);
|
||||
cfields.push(padding(ccx, size - offset));
|
||||
// Pad to the size of the whole type, not e.g. the variant.
|
||||
cfields.push(padding(ccx, ccx.size_of(layout.ty) - offset));
|
||||
|
||||
Const::new(C_struct(ccx, &cfields, st.packed), layout.ty)
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ impl ops::BitOr for Alignment {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Layout> for Alignment {
|
||||
impl<'a> From<&'a Layout<'a>> for Alignment {
|
||||
fn from(layout: &Layout) -> Self {
|
||||
let (packed, align) = match *layout {
|
||||
Layout::UntaggedUnion(ref un) => (un.packed, un.align),
|
||||
|
@ -234,27 +234,24 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||
}
|
||||
|
||||
// Discriminant field of enums.
|
||||
match *l.layout {
|
||||
layout::NullablePointer { .. } if l.variant_index.is_none() => {
|
||||
let ty = ccx.llvm_type_of(field.ty);
|
||||
let size = field.size(ccx).bytes();
|
||||
if let layout::NullablePointer { .. } = *l.layout {
|
||||
let ty = ccx.llvm_type_of(field.ty);
|
||||
let size = field.size(ccx).bytes();
|
||||
|
||||
// If the discriminant is not on a multiple of the primitive's size,
|
||||
// we need to go through i8*. Also assume the worst alignment.
|
||||
if offset % size != 0 {
|
||||
let byte_ptr = bcx.pointercast(self.llval, Type::i8p(ccx));
|
||||
let byte_ptr = bcx.inbounds_gep(byte_ptr, &[C_usize(ccx, offset)]);
|
||||
let byte_align = Alignment::Packed(Align::from_bytes(1, 1).unwrap());
|
||||
return LvalueRef::new_sized(
|
||||
bcx.pointercast(byte_ptr, ty.ptr_to()), field.ty, byte_align);
|
||||
}
|
||||
|
||||
let discr_ptr = bcx.pointercast(self.llval, ty.ptr_to());
|
||||
// If the discriminant is not on a multiple of the primitive's size,
|
||||
// we need to go through i8*. Also assume the worst alignment.
|
||||
if offset % size != 0 {
|
||||
let byte_ptr = bcx.pointercast(self.llval, Type::i8p(ccx));
|
||||
let byte_ptr = bcx.inbounds_gep(byte_ptr, &[C_usize(ccx, offset)]);
|
||||
let byte_align = Alignment::Packed(Align::from_bytes(1, 1).unwrap());
|
||||
return LvalueRef::new_sized(
|
||||
bcx.inbounds_gep(discr_ptr, &[C_usize(ccx, offset / size)]),
|
||||
field.ty, alignment);
|
||||
bcx.pointercast(byte_ptr, ty.ptr_to()), field.ty, byte_align);
|
||||
}
|
||||
_ => {}
|
||||
|
||||
let discr_ptr = bcx.pointercast(self.llval, ty.ptr_to());
|
||||
return LvalueRef::new_sized(
|
||||
bcx.inbounds_gep(discr_ptr, &[C_usize(ccx, offset / size)]),
|
||||
field.ty, alignment);
|
||||
}
|
||||
|
||||
let simple = || {
|
||||
|
@ -271,10 +268,8 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
|||
};
|
||||
|
||||
// Check whether the variant being used is packed, if applicable.
|
||||
let is_packed = match (l.layout, l.variant_index) {
|
||||
(&layout::Univariant(ref variant), _) => variant.packed,
|
||||
(&layout::NullablePointer { ref variants, .. }, Some(v)) |
|
||||
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
|
||||
let is_packed = match *l.layout {
|
||||
layout::Univariant(ref variant) => variant.packed,
|
||||
_ => return simple()
|
||||
};
|
||||
|
||||
|
@ -470,13 +465,13 @@ 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);
|
||||
match *layout.layout {
|
||||
layout::NullablePointer { ref variants, .. } |
|
||||
layout::General { ref variants, .. } => {
|
||||
let st = &variants[variant_index];
|
||||
let layout = bcx.ccx.layout_of(ty);
|
||||
let variant_layout = layout.for_variant(variant_index);
|
||||
match (layout.layout, variant_layout.layout) {
|
||||
(&layout::NullablePointer { .. }, &layout::Univariant(ref st)) |
|
||||
(&layout::General { .. }, &layout::Univariant(ref st)) => {
|
||||
let variant_ty = Type::struct_(bcx.ccx,
|
||||
&adt::struct_llfields(bcx.ccx, layout, st), st.packed);
|
||||
&adt::struct_llfields(bcx.ccx, variant_layout), st.packed);
|
||||
downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -242,7 +242,9 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
|||
}
|
||||
match *self.layout {
|
||||
Layout::Scalar { .. } |
|
||||
Layout::UntaggedUnion { .. } => {
|
||||
Layout::UntaggedUnion { .. } |
|
||||
Layout::NullablePointer { .. } |
|
||||
Layout::General { .. } => {
|
||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
|
@ -258,15 +260,6 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
|||
Layout::Univariant(ref variant) => {
|
||||
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)
|
||||
} else {
|
||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue