Update directly tagged enums to visualize the same as niche-layout enums
Previously, directly tagged enums had a `variant$` field which would show the name of the active variant. We now show the variant using a `[variant]` synthetic item just like we do for niche-layout enums.
This commit is contained in:
parent
798baebde1
commit
3780684f5a
4 changed files with 61 additions and 95 deletions
|
@ -1,4 +1,3 @@
|
||||||
use self::EnumTagInfo::*;
|
|
||||||
use self::MemberDescriptionFactory::*;
|
use self::MemberDescriptionFactory::*;
|
||||||
use self::RecursiveTypeDescription::*;
|
use self::RecursiveTypeDescription::*;
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::ich::NodeIdHashingMode;
|
use rustc_middle::ich::NodeIdHashingMode;
|
||||||
use rustc_middle::mir::{self, Field, GeneratorLayout};
|
use rustc_middle::mir::{self, GeneratorLayout};
|
||||||
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
|
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
|
@ -1188,7 +1187,7 @@ enum MemberDescriptionFactory<'ll, 'tcx> {
|
||||||
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
||||||
EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
|
EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
|
||||||
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
||||||
VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>),
|
VariantMDF(VariantMemberDescriptionFactory<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemberDescriptionFactory<'ll, 'tcx> {
|
impl MemberDescriptionFactory<'ll, 'tcx> {
|
||||||
|
@ -1505,14 +1504,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let variant_info = variant_info_for(index);
|
let variant_info = variant_info_for(index);
|
||||||
let (variant_type_metadata, member_description_factory) = describe_enum_variant(
|
let (variant_type_metadata, member_description_factory) =
|
||||||
cx,
|
describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span);
|
||||||
self.layout,
|
|
||||||
variant_info,
|
|
||||||
None,
|
|
||||||
self_metadata,
|
|
||||||
self.span,
|
|
||||||
);
|
|
||||||
|
|
||||||
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
||||||
|
|
||||||
|
@ -1540,28 +1533,38 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
ref variants,
|
ref variants,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let tag_info = if fallback {
|
let fallback_discr_variant = if fallback {
|
||||||
// For MSVC, we generate a union of structs for each variant with an explicit
|
// For MSVC, we generate a union of structs for each variant and an
|
||||||
// discriminant field roughly equivalent to the following C:
|
// explicit discriminant field roughly equivalent to the following C:
|
||||||
// ```c
|
// ```c
|
||||||
// union enum$<{name}> {
|
// union enum$<{name}> {
|
||||||
// struct {variant 0 name} {
|
// struct {variant 0 name} {
|
||||||
// tag$ variant$;
|
|
||||||
// <variant 0 fields>
|
// <variant 0 fields>
|
||||||
// } variant0;
|
// } variant0;
|
||||||
// <other variant structs>
|
// <other variant structs>
|
||||||
|
// {name} discriminant;
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
// The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to
|
// The natvis in `intrinsic.nativs` then matches on `this.discriminant` to
|
||||||
// determine which variant is active and then displays it.
|
// determine which variant is active and then displays it.
|
||||||
Some(DirectTag {
|
let enum_layout = self.layout;
|
||||||
tag_field: Field::from(tag_field),
|
let offset = enum_layout.fields.offset(tag_field);
|
||||||
tag_type_metadata: self.tag_type_metadata.unwrap(),
|
let discr_ty = enum_layout.field(cx, tag_field).ty;
|
||||||
|
let (size, align) = cx.size_and_align_of(discr_ty);
|
||||||
|
Some(MemberDescription {
|
||||||
|
name: "discriminant".into(),
|
||||||
|
type_metadata: self.tag_type_metadata.unwrap(),
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
align,
|
||||||
|
flags: DIFlags::FlagZero,
|
||||||
|
discriminant: None,
|
||||||
|
source_info: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// This doesn't matter in this case.
|
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
variants
|
variants
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.map(|(i, _)| {
|
.map(|(i, _)| {
|
||||||
|
@ -1571,7 +1574,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
cx,
|
cx,
|
||||||
variant,
|
variant,
|
||||||
variant_info,
|
variant_info,
|
||||||
tag_info,
|
|
||||||
self_metadata,
|
self_metadata,
|
||||||
self.span,
|
self.span,
|
||||||
);
|
);
|
||||||
|
@ -1605,6 +1607,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
source_info: variant_info.source_info(cx),
|
source_info: variant_info.source_info(cx),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.chain(fallback_discr_variant.into_iter())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
Variants::Multiple {
|
Variants::Multiple {
|
||||||
|
@ -1702,7 +1705,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
cx,
|
cx,
|
||||||
dataful_variant_layout,
|
dataful_variant_layout,
|
||||||
variant_info,
|
variant_info,
|
||||||
Some(NicheTag),
|
|
||||||
self_metadata,
|
self_metadata,
|
||||||
self.span,
|
self.span,
|
||||||
);
|
);
|
||||||
|
@ -1754,7 +1756,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
cx,
|
cx,
|
||||||
variant,
|
variant,
|
||||||
variant_info,
|
variant_info,
|
||||||
Some(NicheTag),
|
|
||||||
self_metadata,
|
self_metadata,
|
||||||
self.span,
|
self.span,
|
||||||
);
|
);
|
||||||
|
@ -1791,39 +1792,27 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates `MemberDescription`s for the fields of a single enum variant.
|
// Creates `MemberDescription`s for the fields of a single enum variant.
|
||||||
struct VariantMemberDescriptionFactory<'ll, 'tcx> {
|
struct VariantMemberDescriptionFactory<'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>)>,
|
||||||
tag_type_metadata: Option<&'ll DIType>,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
impl VariantMemberDescriptionFactory<'tcx> {
|
||||||
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
||||||
self.args
|
self.args
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, &(ref name, ty))| {
|
.map(|(i, &(ref name, ty))| {
|
||||||
// Discriminant is always the first field of our variant
|
|
||||||
// when using the enum fallback.
|
|
||||||
let is_artificial_discr = use_enum_fallback(cx) && i == 0;
|
|
||||||
let (size, align) = cx.size_and_align_of(ty);
|
let (size, align) = cx.size_and_align_of(ty);
|
||||||
MemberDescription {
|
MemberDescription {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
type_metadata: if is_artificial_discr {
|
type_metadata: type_metadata(cx, ty, self.span),
|
||||||
self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span))
|
|
||||||
} else {
|
|
||||||
type_metadata(cx, ty, self.span)
|
|
||||||
},
|
|
||||||
offset: self.offsets[i],
|
offset: self.offsets[i],
|
||||||
size,
|
size,
|
||||||
align,
|
align,
|
||||||
flags: if is_artificial_discr {
|
flags: DIFlags::FlagZero,
|
||||||
DIFlags::FlagArtificial
|
|
||||||
} else {
|
|
||||||
DIFlags::FlagZero
|
|
||||||
},
|
|
||||||
discriminant: None,
|
discriminant: None,
|
||||||
source_info: None,
|
source_info: None,
|
||||||
}
|
}
|
||||||
|
@ -1832,12 +1821,6 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum EnumTagInfo<'ll> {
|
|
||||||
DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType },
|
|
||||||
NicheTag,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum VariantInfo<'a, 'tcx> {
|
enum VariantInfo<'a, 'tcx> {
|
||||||
Adt(&'tcx ty::VariantDef),
|
Adt(&'tcx ty::VariantDef),
|
||||||
|
@ -1916,7 +1899,6 @@ 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: Option<EnumTagInfo<'ll>>,
|
|
||||||
containing_scope: &'ll DIScope,
|
containing_scope: &'ll DIScope,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
||||||
|
@ -1935,50 +1917,13 @@ fn describe_enum_variant(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
let offsets = (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect();
|
||||||
let (offsets, args) = if use_enum_fallback(cx) {
|
let args = (0..layout.fields.count())
|
||||||
// If this is not a univariant enum, there is also the discriminant field.
|
.map(|i| (variant.field_name(i), layout.field(cx, i).ty))
|
||||||
let (discr_offset, discr_arg) = match discriminant_info {
|
.collect();
|
||||||
Some(DirectTag { 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(tag_field.as_usize());
|
|
||||||
let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
|
|
||||||
(Some(offset), Some(args))
|
|
||||||
}
|
|
||||||
_ => (None, None),
|
|
||||||
};
|
|
||||||
(
|
|
||||||
discr_offset
|
|
||||||
.into_iter()
|
|
||||||
.chain((0..layout.fields.count()).map(|i| layout.fields.offset(i)))
|
|
||||||
.collect(),
|
|
||||||
discr_arg
|
|
||||||
.into_iter()
|
|
||||||
.chain(
|
|
||||||
(0..layout.fields.count())
|
|
||||||
.map(|i| (variant.field_name(i), layout.field(cx, i).ty)),
|
|
||||||
)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
(0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(),
|
|
||||||
(0..layout.fields.count())
|
|
||||||
.map(|i| (variant.field_name(i), layout.field(cx, i).ty))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
|
let member_description_factory =
|
||||||
offsets,
|
VariantMDF(VariantMemberDescriptionFactory { offsets, args, span });
|
||||||
args,
|
|
||||||
tag_type_metadata: match discriminant_info {
|
|
||||||
Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
|
|
||||||
(metadata_stub, member_description_factory)
|
(metadata_stub, member_description_factory)
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
<Type Name="enum$<*>">
|
<Type Name="enum$<*>">
|
||||||
<Intrinsic Name="tag" Expression="variant0.variant$" />
|
<Intrinsic Name="tag" Expression="discriminant" />
|
||||||
<DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
|
<DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
|
||||||
<DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
|
<DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
|
||||||
<DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
|
<DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
|
||||||
|
@ -169,6 +169,9 @@
|
||||||
<DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
|
<DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
|
||||||
|
|
||||||
<Expand>
|
<Expand>
|
||||||
|
<Synthetic Name="[variant]">
|
||||||
|
<DisplayString>{tag(),en}</DisplayString>
|
||||||
|
</Synthetic>
|
||||||
<ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
|
<ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
|
||||||
<ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
|
<ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
|
||||||
<ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
|
<ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
|
||||||
|
|
|
@ -48,14 +48,30 @@
|
||||||
// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
|
// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
|
||||||
// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
|
// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
|
||||||
|
|
||||||
|
// cdb-command: dx -r2 h,!
|
||||||
|
// cdb-check:h,! : Some [Type: enum$<core::option::Option<u32> >]
|
||||||
|
// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
|
||||||
|
// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
|
||||||
|
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
|
||||||
|
// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option]
|
||||||
|
|
||||||
// cdb-command: dx h
|
// cdb-command: dx h
|
||||||
// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
|
// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
|
||||||
// cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option]
|
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
|
||||||
|
// cdb-check: [variant] : Some
|
||||||
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
|
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
|
||||||
|
|
||||||
|
// cdb-command: dx -r2 i,!
|
||||||
|
// cdb-check:i,! : None [Type: enum$<core::option::Option<u32> >]
|
||||||
|
// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
|
||||||
|
// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
|
||||||
|
// cdb-check: [+0x004] __0 : 0x5c0065 [Type: unsigned int]
|
||||||
|
// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option]
|
||||||
|
|
||||||
// cdb-command: dx i
|
// cdb-command: dx i
|
||||||
// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
|
// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
|
||||||
// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option]
|
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
|
||||||
|
// cdb-check: [variant] : None
|
||||||
|
|
||||||
// cdb-command: dx j
|
// cdb-command: dx j
|
||||||
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
||||||
|
|
|
@ -116,12 +116,14 @@
|
||||||
|
|
||||||
// cdb-command: dx some
|
// cdb-command: dx some
|
||||||
// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
|
// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
|
||||||
// cdb-check: [...] variant$ : Some (0x1) [Type: core::option::Option]
|
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i16> >]
|
||||||
// cdb-check: [...] __0 : 8 [Type: short]
|
// cdb-check: [variant] : Some
|
||||||
|
// cdb-check: [+0x002] __0 : 8 [Type: short]
|
||||||
|
|
||||||
// cdb-command: dx none
|
// cdb-command: dx none
|
||||||
// cdb-check:none : None [Type: enum$<core::option::Option<i64> >]
|
// cdb-check:none : None [Type: enum$<core::option::Option<i64> >]
|
||||||
// cdb-check: [...] variant$ : None (0x0) [Type: core::option::Option]
|
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i64> >]
|
||||||
|
// cdb-check: [variant] : None
|
||||||
|
|
||||||
// cdb-command: dx some_string
|
// cdb-command: dx some_string
|
||||||
// NOTE: cdb fails to interpret debug info of Option enums on i686.
|
// NOTE: cdb fails to interpret debug info of Option enums on i686.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue