Skip to content

Commit

Permalink
Rollup merge of rust-lang#59519 - eddyb:layout-variants-refactor, r=o…
Browse files Browse the repository at this point in the history
…li-obk

rustc_target: factor out common fields of non-Single Variants.

@tmandry and I were discussing ways to generalize the current variants/discriminant layout to allow more fields in the "`enum`" (or another multi-variant types, such as potentially generator state, in the future), shared by all variants, than just the tag/niche discriminant.

This refactor should make it easier to extend multi-variant layouts, as nothing is duplicating anymore between "tagged enums" and "niche-filling enums".

r? @oli-obk
  • Loading branch information
Centril committed Mar 31, 2019
2 parents 245a0af + 5b7f4e9 commit 0171fe5
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 134 deletions.
57 changes: 34 additions & 23 deletions src/librustc/ty/layout.rs
Expand Up @@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}

return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::NicheFilling {
dataful_variant: i,
niche_variants,
niche: niche_scalar,
niche_start,
variants: Variants::Multiple {
discr: niche_scalar,
discr_kind: DiscriminantKind::Niche {
dataful_variant: i,
niche_variants,
niche_start,
},
variants: st,
},
fields: FieldPlacement::Arbitrary {
Expand Down Expand Up @@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}

tcx.intern_layout(LayoutDetails {
variants: Variants::Tagged {
tag,
variants: Variants::Multiple {
discr: tag,
discr_kind: DiscriminantKind::Tag,
variants: layout_variants,
},
fields: FieldPlacement::Arbitrary {
Expand Down Expand Up @@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}
}

Variants::NicheFilling { .. } |
Variants::Tagged { .. } => {
Variants::Multiple { ref discr, ref discr_kind, .. } => {
debug!("print-type-size `{:#?}` adt general variants def {}",
layout.ty, adt_def.variants.len());
let variant_infos: Vec<_> =
Expand All @@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
layout.for_variant(self, i))
})
.collect();
record(adt_kind.into(), adt_packed, match layout.variants {
Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
record(adt_kind.into(), adt_packed, match discr_kind {
DiscriminantKind::Tag => Some(discr.value.size(self)),
_ => None
}, variant_infos);
}
Expand Down Expand Up @@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
})
}

Variants::NicheFilling { ref variants, .. } |
Variants::Tagged { ref variants, .. } => {
Variants::Multiple { ref variants, .. } => {
&variants[variant_index]
}
};
Expand Down Expand Up @@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
}

// Discriminant field for enums (where applicable).
Variants::Tagged { tag: ref discr, .. } |
Variants::NicheFilling { niche: ref discr, .. } => {
Variants::Multiple { ref discr, .. } => {
assert_eq!(i, 0);
let layout = LayoutDetails::scalar(cx, discr.clone());
return MaybeResult::from_ok(TyLayout {
Expand Down Expand Up @@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
Single { index } => {
index.hash_stable(hcx, hasher);
}
Tagged {
ref tag,
Multiple {
ref discr,
ref discr_kind,
ref variants,
} => {
tag.hash_stable(hcx, hasher);
discr.hash_stable(hcx, hasher);
discr_kind.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
}
NicheFilling {
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
use crate::ty::layout::DiscriminantKind::*;
mem::discriminant(self).hash_stable(hcx, hasher);

match *self {
Tag => {}
Niche {
dataful_variant,
ref niche_variants,
ref niche,
niche_start,
ref variants,
} => {
dataful_variant.hash_stable(hcx, hasher);
niche_variants.start().hash_stable(hcx, hasher);
niche_variants.end().hash_stable(hcx, hasher);
niche.hash_stable(hcx, hasher);
niche_start.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
}
}
}
Expand Down
68 changes: 48 additions & 20 deletions src/librustc_codegen_llvm/debuginfo/metadata.rs
Expand Up @@ -1246,7 +1246,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
}
]
}
layout::Variants::Tagged { ref variants, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref variants,
..
} => {
let discriminant_info = if fallback {
RegularDiscriminant(self.discriminant_type_metadata
.expect(""))
Expand Down Expand Up @@ -1288,12 +1292,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
}
}).collect()
}
layout::Variants::NicheFilling {
ref niche_variants,
niche_start,
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
ref niche_variants,
niche_start,
dataful_variant,
},
ref discr,
ref variants,
dataful_variant,
ref niche,
} => {
if fallback {
let variant = self.layout.for_variant(cx, dataful_variant);
Expand Down Expand Up @@ -1380,7 +1386,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
let value = (i.as_u32() as u128)
.wrapping_sub(niche_variants.start().as_u32() as u128)
.wrapping_add(niche_start);
let value = truncate(value, niche.value.size(cx));
let value = truncate(value, discr.value.size(cx));
// NOTE(eddyb) do *NOT* remove this assert, until
// we pass the full 128-bit value to LLVM, otherwise
// truncation will be silent and remain undetected.
assert_eq!(value as u64 as u128, value);
Some(value as u64)
};

Expand Down Expand Up @@ -1597,8 +1607,11 @@ fn prepare_enum_metadata(
let layout = cx.layout_of(enum_type);

match (&layout.abi, &layout.variants) {
(&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
return FinalMetadata(discriminant_type_metadata(tag.value)),
(&layout::Abi::Scalar(_), &layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
}) => return FinalMetadata(discriminant_type_metadata(discr.value)),
_ => {}
}

Expand All @@ -1610,9 +1623,16 @@ fn prepare_enum_metadata(
if use_enum_fallback(cx) {
let discriminant_type_metadata = match layout.variants {
layout::Variants::Single { .. } |
layout::Variants::NicheFilling { .. } => None,
layout::Variants::Tagged { ref tag, .. } => {
Some(discriminant_type_metadata(tag.value))
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche { .. },
..
} => None,
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
} => {
Some(discriminant_type_metadata(discr.value))
}
};

Expand Down Expand Up @@ -1647,16 +1667,20 @@ fn prepare_enum_metadata(
);
}

let discriminator_metadata = match &layout.variants {
let discriminator_metadata = match layout.variants {
// A single-variant enum has no discriminant.
&layout::Variants::Single { .. } => None,
layout::Variants::Single { .. } => None,

&layout::Variants::NicheFilling { ref niche, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche { .. },
ref discr,
..
} => {
// Find the integer type of the correct size.
let size = niche.value.size(cx);
let align = niche.value.align(cx);
let size = discr.value.size(cx);
let align = discr.value.align(cx);

let discr_type = match niche.value {
let discr_type = match discr.value {
layout::Int(t, _) => t,
layout::Float(layout::FloatTy::F32) => Integer::I32,
layout::Float(layout::FloatTy::F64) => Integer::I64,
Expand All @@ -1679,8 +1703,12 @@ fn prepare_enum_metadata(
}
},

&layout::Variants::Tagged { ref tag, .. } => {
let discr_type = tag.value.to_ty(cx.tcx);
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
} => {
let discr_type = discr.value.to_ty(cx.tcx);
let (size, align) = cx.size_and_align_of(discr_type);

let discr_metadata = basic_type_metadata(cx, discr_type);
Expand Down
8 changes: 7 additions & 1 deletion src/librustc_codegen_llvm/type_of.rs
Expand Up @@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {

_ => {
let mut data_variant = match self.variants {
layout::Variants::NicheFilling { dataful_variant, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
dataful_variant,
..
},
..
} => {
// Only the niche itself is always initialized,
// so only check for a pointer at its offset.
//
Expand Down
36 changes: 20 additions & 16 deletions src/librustc_codegen_ssa/mir/place.rs
Expand Up @@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
if self.layout.abi.is_uninhabited() {
return bx.cx().const_undef(cast_to);
}
match self.layout.variants {
let (discr_scalar, discr_kind) = match self.layout.variants {
layout::Variants::Single { index } => {
let discr_val = self.layout.ty.ty_adt_def().map_or(
index.as_u32() as u128,
|def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
return bx.cx().const_uint_big(cast_to, discr_val);
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {},
}
layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
(discr, discr_kind)
}
};

let discr = self.project_field(bx, 0);
let lldiscr = bx.load_operand(discr).immediate();
match self.layout.variants {
layout::Variants::Single { .. } => bug!(),
layout::Variants::Tagged { ref tag, .. } => {
let signed = match tag.value {
match *discr_kind {
layout::DiscriminantKind::Tag => {
let signed = match discr_scalar.value {
// We use `i1` for bytes that are always `0` or `1`,
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
// let LLVM interpret the `i1` as signed, because
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
layout::Int(_, signed) => !tag.is_bool() && signed,
layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
_ => false
};
bx.intcast(lldiscr, cast_to, signed)
}
layout::Variants::NicheFilling {
layout::DiscriminantKind::Niche {
dataful_variant,
ref niche_variants,
niche_start,
..
} => {
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
if niche_variants.start() == niche_variants.end() {
Expand Down Expand Up @@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
layout::Variants::Single { index } => {
assert_eq!(index, variant_index);
}
layout::Variants::Tagged { .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
..
} => {
let ptr = self.project_field(bx, 0);
let to = self.layout.ty.ty_adt_def().unwrap()
.discriminant_for_variant(bx.tcx(), variant_index)
Expand All @@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
ptr.llval,
ptr.align);
}
layout::Variants::NicheFilling {
dataful_variant,
ref niche_variants,
niche_start,
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
dataful_variant,
ref niche_variants,
niche_start,
},
..
} => {
if variant_index != dataful_variant {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_codegen_ssa/mir/rvalue.rs
Expand Up @@ -282,8 +282,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
});
}
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {},
layout::Variants::Multiple { .. } => {},
}
let llval = operand.immediate();

Expand Down

0 comments on commit 0171fe5

Please sign in to comment.