1
Fork 0

Change name of "dataful" variant to "untagged"

This is in anticipation of a new enum layout, in which the niche
optimization may be applied even when multiple variants have data.
This commit is contained in:
Michael Benfield 2022-08-25 01:14:23 +00:00
parent f91ca2878a
commit 1a08b96a0b
12 changed files with 46 additions and 45 deletions

View file

@ -42,10 +42,10 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
Variants::Multiple { Variants::Multiple {
tag: _, tag: _,
tag_field, tag_field,
tag_encoding: TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, tag_encoding: TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
variants: _, variants: _,
} => { } => {
if variant_index != dataful_variant { if variant_index != untagged_variant {
let niche = place.place_field(fx, mir::Field::new(tag_field)); let niche = place.place_field(fx, mir::Field::new(tag_field));
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
let niche_value = ty::ScalarInt::try_from_uint( let niche_value = ty::ScalarInt::try_from_uint(
@ -113,7 +113,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
let res = CValue::by_val(val, dest_layout); let res = CValue::by_val(val, dest_layout);
dest.write_cvalue(fx, res); dest.write_cvalue(fx, res);
} }
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
// Rebase from niche values to discriminants, and check // Rebase from niche values to discriminants, and check
// whether the result is in range for the niche variants. // whether the result is in range for the niche variants.
@ -169,8 +169,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32())) fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
}; };
let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32())); let untagged_variant =
let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant); fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
let res = CValue::by_val(discr, dest_layout); let res = CValue::by_val(discr, dest_layout);
dest.write_cvalue(fx, res); dest.write_cvalue(fx, res);
} }

View file

@ -99,7 +99,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
/// compiler versions. /// compiler versions.
/// ///
/// Niche-tag enums have one special variant, usually called the /// Niche-tag enums have one special variant, usually called the
/// "dataful variant". This variant has a field that /// "untagged variant". This variant has a field that
/// doubles as the tag of the enum. The variant is active when the value of /// doubles as the tag of the enum. The variant is active when the value of
/// that field is within a pre-defined range. Therefore the variant struct /// that field is within a pre-defined range. Therefore the variant struct
/// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in /// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in
@ -249,7 +249,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
None, None,
), ),
Variants::Multiple { Variants::Multiple {
tag_encoding: TagEncoding::Niche { dataful_variant, .. }, tag_encoding: TagEncoding::Niche { untagged_variant, .. },
ref variants, ref variants,
tag_field, tag_field,
.. ..
@ -260,7 +260,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
enum_type_di_node, enum_type_di_node,
variants.indices(), variants.indices(),
tag_field, tag_field,
Some(dataful_variant), Some(untagged_variant),
), ),
} }
}, },
@ -391,7 +391,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
enum_type_di_node: &'ll DIType, enum_type_di_node: &'ll DIType,
variant_indices: impl Iterator<Item = VariantIdx> + Clone, variant_indices: impl Iterator<Item = VariantIdx> + Clone,
tag_field: usize, tag_field: usize,
dataful_variant_index: Option<VariantIdx>, untagged_variant_index: Option<VariantIdx>,
) -> SmallVec<&'ll DIType> { ) -> SmallVec<&'ll DIType> {
let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); let tag_base_type = super::tag_base_type(cx, enum_type_and_layout);
@ -436,7 +436,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
variant_names_type_di_node, variant_names_type_di_node,
tag_base_type, tag_base_type,
tag_field, tag_field,
dataful_variant_index, untagged_variant_index,
) )
} }
@ -472,7 +472,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
enum_or_generator_type_and_layout: TyAndLayout<'tcx>, enum_or_generator_type_and_layout: TyAndLayout<'tcx>,
enum_or_generator_type_di_node: &'ll DIType, enum_or_generator_type_di_node: &'ll DIType,
variant_index: VariantIdx, variant_index: VariantIdx,
dataful_variant_index: Option<VariantIdx>, untagged_variant_index: Option<VariantIdx>,
variant_struct_type_di_node: &'ll DIType, variant_struct_type_di_node: &'ll DIType,
variant_names_type_di_node: &'ll DIType, variant_names_type_di_node: &'ll DIType,
tag_base_type_di_node: &'ll DIType, tag_base_type_di_node: &'ll DIType,
@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
} }
} }
DiscrResult::Range(min, max) => { DiscrResult::Range(min, max) => {
assert_eq!(Some(variant_index), dataful_variant_index); assert_eq!(Some(variant_index), untagged_variant_index);
if is_128_bits { if is_128_bits {
DiscrKind::Range128(min, max) DiscrKind::Range128(min, max)
} else { } else {
@ -757,7 +757,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
discr_type_di_node: &'ll DIType, discr_type_di_node: &'ll DIType,
tag_base_type: Ty<'tcx>, tag_base_type: Ty<'tcx>,
tag_field: usize, tag_field: usize,
dataful_variant_index: Option<VariantIdx>, untagged_variant_index: Option<VariantIdx>,
) -> SmallVec<&'ll DIType> { ) -> SmallVec<&'ll DIType> {
let tag_base_type_di_node = type_di_node(cx, tag_base_type); let tag_base_type_di_node = type_di_node(cx, tag_base_type);
let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1); let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
@ -776,7 +776,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
enum_type_and_layout, enum_type_and_layout,
enum_type_di_node, enum_type_di_node,
variant_member_info.variant_index, variant_member_info.variant_index,
dataful_variant_index, untagged_variant_index,
variant_member_info.variant_struct_type_di_node, variant_member_info.variant_struct_type_di_node,
discr_type_di_node, discr_type_di_node,
tag_base_type_di_node, tag_base_type_di_node,

View file

@ -417,7 +417,7 @@ impl DiscrResult {
/// Returns the discriminant value corresponding to the variant index. /// Returns the discriminant value corresponding to the variant index.
/// ///
/// Will return `None` if there is less than two variants (because then the enum won't have) /// Will return `None` if there is less than two variants (because then the enum won't have)
/// a tag, and if this is the dataful variant of a niche-layout enum (because then there is no /// a tag, and if this is the untagged variant of a niche-layout enum (because then there is no
/// single discriminant value). /// single discriminant value).
fn compute_discriminant_value<'ll, 'tcx>( fn compute_discriminant_value<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
@ -430,11 +430,11 @@ fn compute_discriminant_value<'ll, 'tcx>(
enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val, enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val,
), ),
&Variants::Multiple { &Variants::Multiple {
tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, untagged_variant },
tag, tag,
.. ..
} => { } => {
if variant_index == dataful_variant { if variant_index == untagged_variant {
let valid_range = enum_type_and_layout let valid_range = enum_type_and_layout
.for_variant(cx, variant_index) .for_variant(cx, variant_index)
.largest_niche .largest_niche

View file

@ -378,7 +378,7 @@ fn build_discr_member_di_node<'ll, 'tcx>(
/// ///
/// The DW_AT_discr_value is optional, and is omitted if /// The DW_AT_discr_value is optional, and is omitted if
/// - This is the only variant of a univariant enum (i.e. their is no discriminant) /// - This is the only variant of a univariant enum (i.e. their is no discriminant)
/// - This is the "dataful" variant of a niche-layout enum /// - This is the "untagged" variant of a niche-layout enum
/// (where only the other variants are identified by a single value) /// (where only the other variants are identified by a single value)
/// ///
/// There is only ever a single member, the type of which is a struct that describes the /// There is only ever a single member, the type of which is a struct that describes the

View file

@ -244,7 +244,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
}; };
bx.intcast(tag.immediate(), cast_to, signed) bx.intcast(tag.immediate(), cast_to, signed)
} }
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
// Rebase from niche values to discriminants, and check // Rebase from niche values to discriminants, and check
// whether the result is in range for the niche variants. // whether the result is in range for the niche variants.
let niche_llty = bx.cx().immediate_backend_type(tag.layout); let niche_llty = bx.cx().immediate_backend_type(tag.layout);
@ -302,7 +302,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
bx.select( bx.select(
is_niche, is_niche,
niche_discr, niche_discr,
bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64), bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64),
) )
} }
} }
@ -337,11 +337,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
} }
Variants::Multiple { Variants::Multiple {
tag_encoding: tag_encoding:
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
tag_field, tag_field,
.. ..
} => { } => {
if variant_index != dataful_variant { if variant_index != untagged_variant {
let niche = self.project_field(bx, tag_field); let niche = self.project_field(bx, tag_field);
let niche_llty = bx.cx().immediate_backend_type(niche.layout); let niche_llty = bx.cx().immediate_backend_type(niche.layout);
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();

View file

@ -718,7 +718,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Return the cast value, and the index. // Return the cast value, and the index.
(discr_val, index.0) (discr_val, index.0)
} }
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
let tag_val = tag_val.to_scalar(); let tag_val = tag_val.to_scalar();
// Compute the variant this niche value/"tag" corresponds to. With niche layout, // Compute the variant this niche value/"tag" corresponds to. With niche layout,
// discriminant (encoded in niche/tag) and variant index are the same. // discriminant (encoded in niche/tag) and variant index are the same.
@ -736,7 +736,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
if !ptr_valid { if !ptr_valid {
throw_ub!(InvalidTag(dbg_val)) throw_ub!(InvalidTag(dbg_val))
} }
dataful_variant untagged_variant
} }
Ok(tag_bits) => { Ok(tag_bits) => {
let tag_bits = tag_bits.assert_bits(tag_layout.size); let tag_bits = tag_bits.assert_bits(tag_layout.size);
@ -766,7 +766,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert!(usize::try_from(variant_index).unwrap() < variants_len); assert!(usize::try_from(variant_index).unwrap() < variants_len);
VariantIdx::from_u32(variant_index) VariantIdx::from_u32(variant_index)
} else { } else {
dataful_variant untagged_variant
} }
} }
}; };

View file

@ -817,7 +817,7 @@ where
} }
abi::Variants::Multiple { abi::Variants::Multiple {
tag_encoding: tag_encoding:
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
tag: tag_layout, tag: tag_layout,
tag_field, tag_field,
.. ..
@ -825,7 +825,7 @@ where
// No need to validate that the discriminant here because the // No need to validate that the discriminant here because the
// `TyAndLayout::for_variant()` call earlier already checks the variant is valid. // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
if variant_index != dataful_variant { if variant_index != untagged_variant {
let variants_start = niche_variants.start().as_u32(); let variants_start = niche_variants.start().as_u32();
let variant_index_relative = variant_index let variant_index_relative = variant_index
.as_u32() .as_u32()

View file

@ -1047,7 +1047,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
assert!(def.is_enum()); assert!(def.is_enum());
// The current code for niche-filling relies on variant indices // The current code for niche-filling relies on variant indices
// instead of actual discriminants, so dataful enums with // instead of actual discriminants, so untagged enums with
// explicit discriminants (RFC #2363) would misbehave. // explicit discriminants (RFC #2363) would misbehave.
let no_explicit_discriminants = def let no_explicit_discriminants = def
.variants() .variants()
@ -1058,7 +1058,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// Niche-filling enum optimization. // Niche-filling enum optimization.
if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants { if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants {
let mut dataful_variant = None; let mut untagged_variant = None;
let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
// Find one non-ZST variant. // Find one non-ZST variant.
@ -1068,11 +1068,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
} }
for f in fields { for f in fields {
if !f.is_zst() { if !f.is_zst() {
if dataful_variant.is_none() { if untagged_variant.is_none() {
dataful_variant = Some(v); untagged_variant = Some(v);
continue 'variants; continue 'variants;
} else { } else {
dataful_variant = None; untagged_variant = None;
break 'variants; break 'variants;
} }
} }
@ -1081,10 +1081,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
} }
if niche_variants.start() > niche_variants.end() { if niche_variants.start() > niche_variants.end() {
dataful_variant = None; untagged_variant = None;
} }
if let Some(i) = dataful_variant { if let Some(i) = untagged_variant {
let count = (niche_variants.end().as_u32() let count = (niche_variants.end().as_u32()
- niche_variants.start().as_u32() - niche_variants.start().as_u32()
+ 1) as u128; + 1) as u128;
@ -1152,7 +1152,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
variants: Variants::Multiple { variants: Variants::Multiple {
tag: niche_scalar, tag: niche_scalar,
tag_encoding: TagEncoding::Niche { tag_encoding: TagEncoding::Niche {
dataful_variant: i, untagged_variant: i,
niche_variants, niche_variants,
niche_start, niche_start,
}, },
@ -2559,11 +2559,11 @@ where
// using more niches than just null (e.g., the first page of // using more niches than just null (e.g., the first page of
// the address space, or unaligned pointers). // the address space, or unaligned pointers).
Variants::Multiple { Variants::Multiple {
tag_encoding: TagEncoding::Niche { dataful_variant, .. }, tag_encoding: TagEncoding::Niche { untagged_variant, .. },
tag_field, tag_field,
.. ..
} if this.fields.offset(tag_field) == offset => { } if this.fields.offset(tag_field) == offset => {
Some(this.for_variant(cx, dataful_variant)) Some(this.for_variant(cx, untagged_variant))
} }
_ => Some(this), _ => Some(this),
}; };

View file

@ -1130,7 +1130,7 @@ pub enum TagEncoding {
/// Niche (values invalid for a type) encoding the discriminant: /// Niche (values invalid for a type) encoding the discriminant:
/// Discriminant and variant index coincide. /// Discriminant and variant index coincide.
/// The variant `dataful_variant` contains a niche at an arbitrary /// The variant `untagged_variant` contains a niche at an arbitrary
/// offset (field `tag_field` of the enum), which for a variant with /// offset (field `tag_field` of the enum), which for a variant with
/// discriminant `d` is set to /// discriminant `d` is set to
/// `(d - niche_variants.start).wrapping_add(niche_start)`. /// `(d - niche_variants.start).wrapping_add(niche_start)`.
@ -1139,7 +1139,7 @@ pub enum TagEncoding {
/// `None` has a null pointer for the second tuple field, and /// `None` has a null pointer for the second tuple field, and
/// `Some` is the identity function (with a non-null reference). /// `Some` is the identity function (with a non-null reference).
Niche { Niche {
dataful_variant: VariantIdx, untagged_variant: VariantIdx,
niche_variants: RangeInclusive<VariantIdx>, niche_variants: RangeInclusive<VariantIdx>,
niche_start: u128, niche_start: u128,
}, },

View file

@ -53,8 +53,8 @@
// cdb-command: dx niche128_none // cdb-command: dx niche128_none
// cdb-check: niche128_none : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >] // cdb-check: niche128_none : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >]
// cdb-command: dx wrapping_niche128_dataful // cdb-command: dx wrapping_niche128_untagged
// cdb-check: wrapping_niche128_dataful : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] // cdb-check: wrapping_niche128_untagged : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>]
// cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] // cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128]
// cdb-command: dx wrapping_niche128_none1 // cdb-command: dx wrapping_niche128_none1
@ -213,7 +213,7 @@ fn main() {
let niche128_some = Some(NonZeroI128::new(123456).unwrap()); let niche128_some = Some(NonZeroI128::new(123456).unwrap());
let niche128_none: Option<NonZeroI128> = None; let niche128_none: Option<NonZeroI128> = None;
let wrapping_niche128_dataful = let wrapping_niche128_untagged =
unsafe { Wrapping128Niche::X(Wrapping128(340282366920938463463374607431768211454)) }; unsafe { Wrapping128Niche::X(Wrapping128(340282366920938463463374607431768211454)) };
let wrapping_niche128_none1 = Wrapping128Niche::Y; let wrapping_niche128_none1 = Wrapping128Niche::Y;
let wrapping_niche128_none2 = Wrapping128Niche::Z; let wrapping_niche128_none2 = Wrapping128Niche::Z;

View file

@ -411,7 +411,7 @@ error: layout_of(NicheFirst) = Layout {
valid_range: 0..=4, valid_range: 0..=4,
}, },
tag_encoding: Niche { tag_encoding: Niche {
dataful_variant: 0, untagged_variant: 0,
niche_variants: 1..=2, niche_variants: 1..=2,
niche_start: 3, niche_start: 3,
}, },
@ -555,7 +555,7 @@ error: layout_of(NicheSecond) = Layout {
valid_range: 0..=4, valid_range: 0..=4,
}, },
tag_encoding: Niche { tag_encoding: Niche {
dataful_variant: 0, untagged_variant: 0,
niche_variants: 1..=2, niche_variants: 1..=2,
niche_start: 3, niche_start: 3,
}, },

View file

@ -353,7 +353,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout {
valid_range: 0..=1, valid_range: 0..=1,
}, },
tag_encoding: Niche { tag_encoding: Niche {
dataful_variant: 1, untagged_variant: 1,
niche_variants: 0..=0, niche_variants: 0..=0,
niche_start: 1, niche_start: 1,
}, },