mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 09:44:08 +00:00
rustc_trans: treat General enums like unions.
This commit is contained in:
parent
9a0efea4c2
commit
30710609c0
@ -148,36 +148,15 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
}
|
||||
layout::General { discr, size, align, primitive_align, .. } => {
|
||||
// We need a representation that has:
|
||||
// * The alignment of the most-aligned field
|
||||
// * The size of the largest variant (rounded up to that alignment)
|
||||
// * No alignment padding anywhere any variant has actual data
|
||||
// (currently matters only for enums small enough to be immediate)
|
||||
// * The discriminant in an obvious place.
|
||||
//
|
||||
// So we start with the discriminant, pad it up to the alignment with
|
||||
// more of its own type, then use alignment-sized ints to get the rest
|
||||
// of the size.
|
||||
let discr_ty = Type::from_integer(cx, discr);
|
||||
let discr_size = discr.size().bytes();
|
||||
let padded_discr_size = discr.size().abi_align(align);
|
||||
let variant_part_size = size - padded_discr_size;
|
||||
|
||||
// Ensure discr_ty can fill pad evenly
|
||||
assert_eq!(padded_discr_size.bytes() % discr_size, 0);
|
||||
let fields = [
|
||||
discr_ty,
|
||||
Type::array(&discr_ty, padded_discr_size.bytes() / discr_size - 1),
|
||||
union_fill(cx, variant_part_size, primitive_align)
|
||||
];
|
||||
layout::General { size, align, .. } => {
|
||||
let fill = union_fill(cx, size, align);
|
||||
match name {
|
||||
None => {
|
||||
Type::struct_(cx, &fields, false)
|
||||
Type::struct_(cx, &[fill], false)
|
||||
}
|
||||
Some(name) => {
|
||||
let mut llty = Type::named_struct(cx, name);
|
||||
llty.set_struct_body(&fields, false);
|
||||
llty.set_struct_body(&[fill], false);
|
||||
llty
|
||||
}
|
||||
}
|
||||
|
@ -216,6 +216,11 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||
return LvalueRef::new_sized(
|
||||
bcx.pointercast(self.llval, ty.ptr_to()), fty, alignment);
|
||||
}
|
||||
layout::General { .. } if l.variant_index.is_none() => {
|
||||
let ty = ccx.llvm_type_of(fty);
|
||||
return LvalueRef::new_sized(
|
||||
bcx.pointercast(self.llval, ty.ptr_to()), fty, alignment);
|
||||
}
|
||||
layout::RawNullablePointer { nndiscr, .. } |
|
||||
layout::StructWrappedNullablePointer { nndiscr, .. }
|
||||
if l.variant_index.unwrap() as u64 != nndiscr => {
|
||||
|
@ -262,8 +262,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
||||
if let Some(v) = self.variant_index {
|
||||
adt::memory_index_to_gep(variants[v].memory_index[index] as u64)
|
||||
} else {
|
||||
assert_eq!(index, 0);
|
||||
index as u64
|
||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user