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