tag/niche terminology cleanup
This commit is contained in:
parent
91fb72a8a9
commit
f7d745f33d
10 changed files with 167 additions and 169 deletions
|
@ -1,4 +1,4 @@
|
|||
use self::EnumDiscriminantInfo::*;
|
||||
use self::EnumTagInfo::*;
|
||||
use self::MemberDescriptionFactory::*;
|
||||
use self::RecursiveTypeDescription::*;
|
||||
|
||||
|
@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug};
|
|||
use rustc_session::config::{self, DebugInfo};
|
||||
use rustc_span::symbol::{Interner, Symbol};
|
||||
use rustc_span::{self, SourceFile, SourceFileHash, Span};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf};
|
||||
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
|
||||
use rustc_target::abi::{Int, Pointer, F32, F64};
|
||||
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
|
||||
|
||||
|
@ -1335,7 +1335,7 @@ fn generator_layout_and_saved_local_names(
|
|||
struct EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
enum_type: Ty<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
discriminant_type_metadata: Option<&'ll DIType>,
|
||||
tag_type_metadata: Option<&'ll DIType>,
|
||||
containing_scope: &'ll DIScope,
|
||||
span: Span,
|
||||
}
|
||||
|
@ -1385,7 +1385,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
cx,
|
||||
self.layout,
|
||||
variant_info,
|
||||
NoDiscriminant,
|
||||
NoTag,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
|
@ -1409,19 +1409,19 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
}]
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field,
|
||||
ref variants,
|
||||
..
|
||||
} => {
|
||||
let discriminant_info = if fallback {
|
||||
RegularDiscriminant {
|
||||
discr_field: Field::from(discr_index),
|
||||
discr_type_metadata: self.discriminant_type_metadata.unwrap(),
|
||||
let tag_info = if fallback {
|
||||
RegularTag {
|
||||
tag_field: Field::from(tag_field),
|
||||
tag_type_metadata: self.tag_type_metadata.unwrap(),
|
||||
}
|
||||
} else {
|
||||
// This doesn't matter in this case.
|
||||
NoDiscriminant
|
||||
NoTag
|
||||
};
|
||||
variants
|
||||
.iter_enumerated()
|
||||
|
@ -1432,7 +1432,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
cx,
|
||||
variant,
|
||||
variant_info,
|
||||
discriminant_info,
|
||||
tag_info,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
|
@ -1467,11 +1467,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
.collect()
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { ref niche_variants, niche_start, dataful_variant },
|
||||
ref discr,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
|
||||
ref tag,
|
||||
ref variants,
|
||||
discr_index,
|
||||
tag_field,
|
||||
} => {
|
||||
if fallback {
|
||||
let variant = self.layout.for_variant(cx, dataful_variant);
|
||||
|
@ -1480,7 +1480,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
cx,
|
||||
variant,
|
||||
variant_info_for(dataful_variant),
|
||||
OptimizedDiscriminant,
|
||||
OptimizedTag,
|
||||
self.containing_scope,
|
||||
self.span,
|
||||
);
|
||||
|
@ -1524,8 +1524,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
cx,
|
||||
&mut name,
|
||||
self.layout,
|
||||
self.layout.fields.offset(discr_index),
|
||||
self.layout.field(cx, discr_index).size,
|
||||
self.layout.fields.offset(tag_field),
|
||||
self.layout.field(cx, tag_field).size,
|
||||
);
|
||||
variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| {
|
||||
name.push_str(variant_name);
|
||||
|
@ -1552,7 +1552,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||
cx,
|
||||
variant,
|
||||
variant_info,
|
||||
OptimizedDiscriminant,
|
||||
OptimizedTag,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
|
@ -1573,7 +1573,7 @@ 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, discr.value.size(cx));
|
||||
let value = truncate(value, tag.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.
|
||||
|
@ -1603,7 +1603,7 @@ struct VariantMemberDescriptionFactory<'ll, 'tcx> {
|
|||
/// Cloned from the `layout::Struct` describing the variant.
|
||||
offsets: Vec<Size>,
|
||||
args: Vec<(String, Ty<'tcx>)>,
|
||||
discriminant_type_metadata: Option<&'ll DIType>,
|
||||
tag_type_metadata: Option<&'ll DIType>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
|
@ -1617,7 +1617,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
|||
MemberDescription {
|
||||
name: name.to_string(),
|
||||
type_metadata: if use_enum_fallback(cx) {
|
||||
match self.discriminant_type_metadata {
|
||||
match self.tag_type_metadata {
|
||||
// Discriminant is always the first field of our variant
|
||||
// when using the enum fallback.
|
||||
Some(metadata) if i == 0 => metadata,
|
||||
|
@ -1638,10 +1638,10 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum EnumDiscriminantInfo<'ll> {
|
||||
RegularDiscriminant { discr_field: Field, discr_type_metadata: &'ll DIType },
|
||||
OptimizedDiscriminant,
|
||||
NoDiscriminant,
|
||||
enum EnumTagInfo<'ll> {
|
||||
RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType },
|
||||
OptimizedTag,
|
||||
NoTag,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -1706,7 +1706,7 @@ fn describe_enum_variant(
|
|||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
layout: layout::TyAndLayout<'tcx>,
|
||||
variant: VariantInfo<'_, 'tcx>,
|
||||
discriminant_info: EnumDiscriminantInfo<'ll>,
|
||||
discriminant_info: EnumTagInfo<'ll>,
|
||||
containing_scope: &'ll DIScope,
|
||||
span: Span,
|
||||
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
||||
|
@ -1722,12 +1722,12 @@ fn describe_enum_variant(
|
|||
let (offsets, args) = if use_enum_fallback(cx) {
|
||||
// If this is not a univariant enum, there is also the discriminant field.
|
||||
let (discr_offset, discr_arg) = match discriminant_info {
|
||||
RegularDiscriminant { discr_field, .. } => {
|
||||
RegularTag { tag_field, .. } => {
|
||||
// We have the layout of an enum variant, we need the layout of the outer enum
|
||||
let enum_layout = cx.layout_of(layout.ty);
|
||||
let offset = enum_layout.fields.offset(discr_field.as_usize());
|
||||
let offset = enum_layout.fields.offset(tag_field.as_usize());
|
||||
let args =
|
||||
("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, discr_field.as_usize()).ty);
|
||||
("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
|
||||
(Some(offset), Some(args))
|
||||
}
|
||||
_ => (None, None),
|
||||
|
@ -1757,8 +1757,8 @@ fn describe_enum_variant(
|
|||
let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
|
||||
offsets,
|
||||
args,
|
||||
discriminant_type_metadata: match discriminant_info {
|
||||
RegularDiscriminant { discr_type_metadata, .. } => Some(discr_type_metadata),
|
||||
tag_type_metadata: match discriminant_info {
|
||||
RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata),
|
||||
_ => None,
|
||||
},
|
||||
span,
|
||||
|
@ -1880,18 +1880,18 @@ fn prepare_enum_metadata(
|
|||
|
||||
if let (
|
||||
&Abi::Scalar(_),
|
||||
&Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. },
|
||||
&Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
|
||||
) = (&layout.abi, &layout.variants)
|
||||
{
|
||||
return FinalMetadata(discriminant_type_metadata(discr.value));
|
||||
return FinalMetadata(discriminant_type_metadata(tag.value));
|
||||
}
|
||||
|
||||
if use_enum_fallback(cx) {
|
||||
let discriminant_type_metadata = match layout.variants {
|
||||
Variants::Single { .. }
|
||||
| Variants::Multiple { discr_kind: DiscriminantKind::Niche { .. }, .. } => None,
|
||||
Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. } => {
|
||||
Some(discriminant_type_metadata(discr.value))
|
||||
| Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None,
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
|
||||
Some(discriminant_type_metadata(tag.value))
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1927,7 +1927,7 @@ fn prepare_enum_metadata(
|
|||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type,
|
||||
layout,
|
||||
discriminant_type_metadata,
|
||||
tag_type_metadata: discriminant_type_metadata,
|
||||
containing_scope,
|
||||
span,
|
||||
}),
|
||||
|
@ -1943,16 +1943,13 @@ fn prepare_enum_metadata(
|
|||
Variants::Single { .. } => None,
|
||||
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Niche { .. },
|
||||
ref discr,
|
||||
discr_index,
|
||||
..
|
||||
tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
|
||||
} => {
|
||||
// Find the integer type of the correct size.
|
||||
let size = discr.value.size(cx);
|
||||
let align = discr.value.align(cx);
|
||||
let size = tag.value.size(cx);
|
||||
let align = tag.value.align(cx);
|
||||
|
||||
let discr_type = match discr.value {
|
||||
let tag_type = match tag.value {
|
||||
Int(t, _) => t,
|
||||
F32 => Integer::I32,
|
||||
F64 => Integer::I64,
|
||||
|
@ -1960,7 +1957,7 @@ fn prepare_enum_metadata(
|
|||
}
|
||||
.to_ty(cx.tcx, false);
|
||||
|
||||
let discr_metadata = basic_type_metadata(cx, discr_type);
|
||||
let tag_metadata = basic_type_metadata(cx, tag_type);
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
|
@ -1971,17 +1968,15 @@ fn prepare_enum_metadata(
|
|||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
align.abi.bits() as u32,
|
||||
layout.fields.offset(discr_index).bits(),
|
||||
layout.fields.offset(tag_field).bits(),
|
||||
DIFlags::FlagArtificial,
|
||||
discr_metadata,
|
||||
tag_metadata,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag, ref discr, discr_index, ..
|
||||
} => {
|
||||
let discr_type = discr.value.to_ty(cx.tcx);
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
|
||||
let discr_type = tag.value.to_ty(cx.tcx);
|
||||
let (size, align) = cx.size_and_align_of(discr_type);
|
||||
|
||||
let discr_metadata = basic_type_metadata(cx, discr_type);
|
||||
|
@ -1995,7 +1990,7 @@ fn prepare_enum_metadata(
|
|||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
layout.fields.offset(discr_index).bits(),
|
||||
layout.fields.offset(tag_field).bits(),
|
||||
DIFlags::FlagArtificial,
|
||||
discr_metadata,
|
||||
))
|
||||
|
@ -2081,7 +2076,7 @@ fn prepare_enum_metadata(
|
|||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type,
|
||||
layout,
|
||||
discriminant_type_metadata: None,
|
||||
tag_type_metadata: None,
|
||||
containing_scope,
|
||||
span,
|
||||
}),
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_middle::mir;
|
|||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape, Int};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding};
|
||||
use rustc_target::abi::{LayoutOf, VariantIdx, Variants};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -199,7 +199,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
if self.layout.abi.is_uninhabited() {
|
||||
return bx.cx().const_undef(cast_to);
|
||||
}
|
||||
let (discr_scalar, discr_kind, discr_index) = match self.layout.variants {
|
||||
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let discr_val = self
|
||||
.layout
|
||||
|
@ -208,33 +208,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
.map_or(index.as_u32() as u128, |discr| discr.val);
|
||||
return bx.cx().const_uint_big(cast_to, discr_val);
|
||||
}
|
||||
Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
|
||||
(discr, discr_kind, discr_index)
|
||||
Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
|
||||
(tag, tag_encoding, tag_field)
|
||||
}
|
||||
};
|
||||
|
||||
// Read the tag/niche-encoded discriminant from memory.
|
||||
let encoded_discr = self.project_field(bx, discr_index);
|
||||
let encoded_discr = bx.load_operand(encoded_discr);
|
||||
let tag = self.project_field(bx, tag_field);
|
||||
let tag = bx.load_operand(tag);
|
||||
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
match *discr_kind {
|
||||
DiscriminantKind::Tag => {
|
||||
let signed = match discr_scalar.value {
|
||||
match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let signed = match tag_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`.
|
||||
Int(_, signed) => !discr_scalar.is_bool() && signed,
|
||||
Int(_, signed) => !tag_scalar.is_bool() && signed,
|
||||
_ => false,
|
||||
};
|
||||
bx.intcast(encoded_discr.immediate(), cast_to, signed)
|
||||
bx.intcast(tag.immediate(), cast_to, signed)
|
||||
}
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
// Rebase from niche values to discriminants, and check
|
||||
// whether the result is in range for the niche variants.
|
||||
let niche_llty = bx.cx().immediate_backend_type(encoded_discr.layout);
|
||||
let encoded_discr = encoded_discr.immediate();
|
||||
let niche_llty = bx.cx().immediate_backend_type(tag.layout);
|
||||
let tag = tag.immediate();
|
||||
|
||||
// We first compute the "relative discriminant" (wrt `niche_variants`),
|
||||
// that is, if `n = niche_variants.end() - niche_variants.start()`,
|
||||
|
@ -248,9 +248,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
let relative_discr = if niche_start == 0 {
|
||||
// Avoid subtracting `0`, which wouldn't work for pointers.
|
||||
// FIXME(eddyb) check the actual primitive type here.
|
||||
encoded_discr
|
||||
tag
|
||||
} else {
|
||||
bx.sub(encoded_discr, bx.cx().const_uint_big(niche_llty, niche_start))
|
||||
bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start))
|
||||
};
|
||||
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
|
||||
let is_niche = {
|
||||
|
@ -312,8 +312,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
Variants::Single { index } => {
|
||||
assert_eq!(index, variant_index);
|
||||
}
|
||||
Variants::Multiple { discr_kind: DiscriminantKind::Tag, discr_index, .. } => {
|
||||
let ptr = self.project_field(bx, discr_index);
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
|
||||
let ptr = self.project_field(bx, tag_field);
|
||||
let to =
|
||||
self.layout.ty.discriminant_for_variant(bx.tcx(), variant_index).unwrap().val;
|
||||
bx.store(
|
||||
|
@ -323,9 +323,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
);
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
discr_index,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
if variant_index != dataful_variant {
|
||||
|
@ -339,7 +339,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty());
|
||||
}
|
||||
|
||||
let niche = self.project_field(bx, discr_index);
|
||||
let niche = self.project_field(bx, tag_field);
|
||||
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 = (niche_value as u128).wrapping_add(niche_start);
|
||||
|
|
|
@ -16,7 +16,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
|||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{DiscriminantKind, Integer, LayoutOf, VariantIdx, Variants};
|
||||
use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use log::debug;
|
||||
|
@ -1036,15 +1036,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||
};
|
||||
let (variants, tag) = match layout.variants {
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
ref discr,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
ref tag,
|
||||
ref variants,
|
||||
..
|
||||
} => (variants, discr),
|
||||
} => (variants, tag),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let discr_size = tag.value.size(&cx.tcx).bytes();
|
||||
let tag_size = tag.value.size(&cx.tcx).bytes();
|
||||
|
||||
debug!(
|
||||
"enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||
|
@ -1058,8 +1058,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||
.iter()
|
||||
.zip(variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// Subtract the size of the enum discriminant.
|
||||
let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
|
||||
// Subtract the size of the enum tag.
|
||||
let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
|
||||
|
||||
debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
|
||||
bytes
|
||||
|
|
|
@ -975,13 +975,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
|
||||
return Ok(tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr: niche_scalar,
|
||||
discr_kind: DiscriminantKind::Niche {
|
||||
tag: niche_scalar,
|
||||
tag_encoding: TagEncoding::Niche {
|
||||
dataful_variant: i,
|
||||
niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
discr_index: 0,
|
||||
tag_field: 0,
|
||||
variants: st,
|
||||
},
|
||||
fields: FieldsShape::Arbitrary {
|
||||
|
@ -1217,9 +1217,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr: tag,
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index: 0,
|
||||
tag,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field: 0,
|
||||
variants: layout_variants,
|
||||
},
|
||||
fields: FieldsShape::Arbitrary {
|
||||
|
@ -1400,15 +1400,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
// Build a prefix layout, including "promoting" all ineligible
|
||||
// locals as part of the prefix. We compute the layout of all of
|
||||
// these fields at once to get optimal packing.
|
||||
let discr_index = substs.as_generator().prefix_tys().count();
|
||||
let tag_index = substs.as_generator().prefix_tys().count();
|
||||
|
||||
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
|
||||
let max_discr = (info.variant_fields.len() - 1) as u128;
|
||||
let discr_int = Integer::fit_unsigned(max_discr);
|
||||
let discr_int_ty = discr_int.to_ty(tcx, false);
|
||||
let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
|
||||
let discr_layout = self.tcx.intern_layout(Layout::scalar(self, discr.clone()));
|
||||
let discr_layout = TyAndLayout { ty: discr_int_ty, layout: discr_layout };
|
||||
let tag = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
|
||||
let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
|
||||
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
|
||||
|
||||
let promoted_layouts = ineligible_locals
|
||||
.iter()
|
||||
|
@ -1419,7 +1419,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
.as_generator()
|
||||
.prefix_tys()
|
||||
.map(|ty| self.layout_of(ty))
|
||||
.chain(iter::once(Ok(discr_layout)))
|
||||
.chain(iter::once(Ok(tag_layout)))
|
||||
.chain(promoted_layouts)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let prefix = self.univariant_uninterned(
|
||||
|
@ -1442,7 +1442,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
|
||||
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
|
||||
// "outer" and "promoted" fields respectively.
|
||||
let b_start = (discr_index + 1) as u32;
|
||||
let b_start = (tag_index + 1) as u32;
|
||||
let offsets_b = offsets.split_off(b_start as usize);
|
||||
let offsets_a = offsets;
|
||||
|
||||
|
@ -1559,9 +1559,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
|
||||
let layout = tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr,
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index,
|
||||
tag: tag,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field: tag_index,
|
||||
variants,
|
||||
},
|
||||
fields: outer_fields,
|
||||
|
@ -1681,7 +1681,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
Variants::Multiple { ref discr, ref discr_kind, .. } => {
|
||||
Variants::Multiple { ref tag, ref tag_encoding, .. } => {
|
||||
debug!(
|
||||
"print-type-size `{:#?}` adt general variants def {}",
|
||||
layout.ty,
|
||||
|
@ -1703,8 +1703,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
record(
|
||||
adt_kind.into(),
|
||||
adt_packed,
|
||||
match discr_kind {
|
||||
DiscriminantKind::Tag => Some(discr.value.size(self)),
|
||||
match tag_encoding {
|
||||
TagEncoding::Direct => Some(tag.value.size(self)),
|
||||
_ => None,
|
||||
},
|
||||
variant_infos,
|
||||
|
@ -2029,11 +2029,11 @@ where
|
|||
|
||||
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
|
||||
let tcx = cx.tcx();
|
||||
let discr_layout = |discr: &Scalar| -> C::TyAndLayout {
|
||||
let layout = Layout::scalar(cx, discr.clone());
|
||||
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
|
||||
let layout = Layout::scalar(cx, tag.clone());
|
||||
MaybeResult::from(Ok(TyAndLayout {
|
||||
layout: tcx.intern_layout(layout),
|
||||
ty: discr.value.to_ty(tcx),
|
||||
ty: tag.value.to_ty(tcx),
|
||||
}))
|
||||
};
|
||||
|
||||
|
@ -2110,9 +2110,9 @@ where
|
|||
.unwrap()
|
||||
.nth(i)
|
||||
.unwrap(),
|
||||
Variants::Multiple { ref discr, discr_index, .. } => {
|
||||
if i == discr_index {
|
||||
return discr_layout(discr);
|
||||
Variants::Multiple { ref tag, tag_field, .. } => {
|
||||
if i == tag_field {
|
||||
return tag_layout(tag);
|
||||
}
|
||||
substs.as_generator().prefix_tys().nth(i).unwrap()
|
||||
}
|
||||
|
@ -2129,9 +2129,9 @@ where
|
|||
Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs),
|
||||
|
||||
// Discriminant field for enums (where applicable).
|
||||
Variants::Multiple { ref discr, .. } => {
|
||||
Variants::Multiple { ref tag, .. } => {
|
||||
assert_eq!(i, 0);
|
||||
return discr_layout(discr);
|
||||
return tag_layout(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2208,10 +2208,10 @@ where
|
|||
// using more niches than just null (e.g., the first page of
|
||||
// the address space, or unaligned pointers).
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Niche { dataful_variant, .. },
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
|
||||
tag_field,
|
||||
..
|
||||
} if this.fields.offset(discr_index) == offset => {
|
||||
} if this.fields.offset(tag_field) == offset => {
|
||||
Some(this.for_variant(cx, dataful_variant))
|
||||
}
|
||||
_ => Some(this),
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
|
|||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, LayoutOf, Size};
|
||||
use rustc_target::abi::{Abi, TagEncoding, HasDataLayout, LayoutOf, Size};
|
||||
use rustc_target::abi::{VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
|
@ -587,7 +587,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
op: OpTy<'tcx, M::PointerTag>,
|
||||
) -> InterpResult<'tcx, (Scalar<M::PointerTag>, VariantIdx)> {
|
||||
trace!("read_discriminant_value {:#?}", op.layout);
|
||||
|
||||
// Get type and layout of the discriminant.
|
||||
let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
|
||||
trace!("discriminant type: {:?}", discr_layout.ty);
|
||||
|
@ -596,10 +595,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
// This is not to be confused with its "variant index", which is just determining its position in the
|
||||
// declared list of variants -- they can differ with explicitly assigned discriminants.
|
||||
// We use "tag" to refer to how the discriminant is encoded in memory, which can be either
|
||||
// straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`).
|
||||
// Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things
|
||||
// rather confusing.
|
||||
let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants {
|
||||
// straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
|
||||
let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
|
||||
Some(discr) => {
|
||||
|
@ -615,8 +612,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
};
|
||||
return Ok((discr, index));
|
||||
}
|
||||
Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
|
||||
(discr, discr_kind, discr_index)
|
||||
Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
|
||||
(tag, tag_encoding, tag_field)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -633,21 +630,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
|
||||
|
||||
// Read tag and sanity-check `tag_layout`.
|
||||
let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?;
|
||||
let tag_val = self.read_immediate(self.operand_field(op, tag_field)?)?;
|
||||
assert_eq!(tag_layout.size, tag_val.layout.size);
|
||||
assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
|
||||
let tag_val = tag_val.to_scalar()?;
|
||||
trace!("tag value: {:?}", tag_val);
|
||||
|
||||
// Figure out which discriminant and variant this corresponds to.
|
||||
Ok(match *tag_kind {
|
||||
DiscriminantKind::Tag => {
|
||||
Ok(match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let tag_bits = self
|
||||
.force_bits(tag_val, tag_layout.size)
|
||||
.map_err(|_| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
|
||||
// Cast bits from tag layout to discriminant layout.
|
||||
let discr_val_cast = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
|
||||
let discr_bits = discr_val_cast.assert_bits(discr_layout.size);
|
||||
let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
|
||||
let discr_bits = discr_val.assert_bits(discr_layout.size);
|
||||
// Convert discriminant to variant index, and catch invalid discriminants.
|
||||
let index = match op.layout.ty.kind {
|
||||
ty::Adt(adt, _) => {
|
||||
|
@ -663,9 +660,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
.ok_or_else(|| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
|
||||
// Return the cast value, and the index.
|
||||
(discr_val_cast, index.0)
|
||||
(discr_val, index.0)
|
||||
}
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
// Compute the variant this niche value/"tag" corresponds to. With niche layout,
|
||||
// discriminant (encoded in niche/tag) and variant index are the same.
|
||||
let variants_start = niche_variants.start().as_u32();
|
||||
|
|
|
@ -9,7 +9,7 @@ use rustc_macros::HashStable;
|
|||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
|
@ -1031,7 +1031,8 @@ where
|
|||
MPlaceTy { mplace, layout }
|
||||
}
|
||||
|
||||
pub fn write_discriminant_index(
|
||||
/// Writes the discriminant of the given variant.
|
||||
pub fn write_discriminant(
|
||||
&mut self,
|
||||
variant_index: VariantIdx,
|
||||
dest: PlaceTy<'tcx, M::PointerTag>,
|
||||
|
@ -1047,9 +1048,9 @@ where
|
|||
assert_eq!(index, variant_index);
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr: ref discr_layout,
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag: ref tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
// No need to validate that the discriminant here because the
|
||||
|
@ -1061,17 +1062,17 @@ where
|
|||
// raw discriminants for enums are isize or bigger during
|
||||
// their computation, but the in-memory tag is the smallest possible
|
||||
// representation
|
||||
let size = discr_layout.value.size(self);
|
||||
let discr_val = truncate(discr_val, size);
|
||||
let size = tag_layout.value.size(self);
|
||||
let tag_val = truncate(discr_val, size);
|
||||
|
||||
let discr_dest = self.place_field(dest, discr_index)?;
|
||||
self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
|
||||
let tag_dest = self.place_field(dest, tag_field)?;
|
||||
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
discr: ref discr_layout,
|
||||
discr_index,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
tag: ref tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
// No need to validate that the discriminant here because the
|
||||
|
@ -1084,19 +1085,19 @@ where
|
|||
.checked_sub(variants_start)
|
||||
.expect("overflow computing relative variant idx");
|
||||
// We need to use machine arithmetic when taking into account `niche_start`:
|
||||
// discr_val = variant_index_relative + niche_start_val
|
||||
let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?;
|
||||
let niche_start_val = ImmTy::from_uint(niche_start, discr_layout);
|
||||
// tag_val = variant_index_relative + niche_start_val
|
||||
let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?;
|
||||
let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
|
||||
let variant_index_relative_val =
|
||||
ImmTy::from_uint(variant_index_relative, discr_layout);
|
||||
let discr_val = self.binary_op(
|
||||
ImmTy::from_uint(variant_index_relative, tag_layout);
|
||||
let tag_val = self.binary_op(
|
||||
mir::BinOp::Add,
|
||||
variant_index_relative_val,
|
||||
niche_start_val,
|
||||
)?;
|
||||
// Write result.
|
||||
let niche_dest = self.place_field(dest, discr_index)?;
|
||||
self.write_immediate(*discr_val, niche_dest)?;
|
||||
let niche_dest = self.place_field(dest, tag_field)?;
|
||||
self.write_immediate(*tag_val, niche_dest)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
SetDiscriminant { place, variant_index } => {
|
||||
let dest = self.eval_place(**place)?;
|
||||
self.write_discriminant_index(*variant_index, dest)?;
|
||||
self.write_discriminant(*variant_index, dest)?;
|
||||
}
|
||||
|
||||
// Mark locals as alive
|
||||
|
@ -174,7 +174,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Aggregate(ref kind, ref operands) => {
|
||||
let (dest, active_field_index) = match **kind {
|
||||
mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
|
||||
self.write_discriminant_index(variant_index, dest)?;
|
||||
self.write_discriminant(variant_index, dest)?;
|
||||
if adt_def.is_enum() {
|
||||
(self.place_downcast(dest, variant_index)?, active_field_index)
|
||||
} else {
|
||||
|
|
|
@ -208,8 +208,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
|||
fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem {
|
||||
// First, check if we are projecting to a variant.
|
||||
match layout.variants {
|
||||
Variants::Multiple { discr_index, .. } => {
|
||||
if discr_index == field {
|
||||
Variants::Multiple { tag_field, .. } => {
|
||||
if tag_field == field {
|
||||
return match layout.ty.kind {
|
||||
ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag,
|
||||
ty::Generator(..) => PathElem::GeneratorTag,
|
||||
|
|
|
@ -809,25 +809,30 @@ pub enum Variants {
|
|||
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
||||
Single { index: VariantIdx },
|
||||
|
||||
/// Enum-likes with more than one inhabited variant: for each case there is
|
||||
/// a struct, and they all have space reserved for the discriminant.
|
||||
/// For enums this is the sole field of the layout.
|
||||
/// Enum-likes with more than one inhabited variant: each variant comes with
|
||||
/// a *discriminant* (usually the same as the variant index but the user can
|
||||
/// assign explicit discriminant values). That discriminant is encoded
|
||||
/// as a *tag* on the machine. The layout of each variant is
|
||||
/// a struct, and they all have space reserved for the tag.
|
||||
/// For enums, the tag is the sole field of the layout.
|
||||
Multiple {
|
||||
discr: Scalar,
|
||||
discr_kind: DiscriminantKind,
|
||||
discr_index: usize,
|
||||
tag: Scalar,
|
||||
tag_encoding: TagEncoding,
|
||||
tag_field: usize,
|
||||
variants: IndexVec<VariantIdx, Layout>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum DiscriminantKind {
|
||||
/// Integer tag holding the discriminant value itself.
|
||||
Tag,
|
||||
pub enum TagEncoding {
|
||||
/// The tag directly stores the discriminant, but possibly with a smaller layout
|
||||
/// (so converting the tag to the discriminant can require sign extension).
|
||||
Direct,
|
||||
|
||||
/// Niche (values invalid for a type) encoding the discriminant:
|
||||
/// the variant `dataful_variant` contains a niche at an arbitrary
|
||||
/// offset (field `discr_index` of the enum), which for a variant with
|
||||
/// Discriminant and variant index coincide.
|
||||
/// The variant `dataful_variant` contains a niche at an arbitrary
|
||||
/// offset (field `tag_field` of the enum), which for a variant with
|
||||
/// discriminant `d` is set to
|
||||
/// `(d - niche_variants.start).wrapping_add(niche_start)`.
|
||||
///
|
||||
|
|
|
@ -10,15 +10,15 @@ error: layout_of(E) = Layout {
|
|||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
discr: Scalar {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
discr_kind: Tag,
|
||||
discr_index: 0,
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
|
@ -202,15 +202,15 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
|
|||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
discr: Scalar {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=1,
|
||||
},
|
||||
discr_kind: Tag,
|
||||
discr_index: 0,
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue