diff options
| author | bors <bors@rust-lang.org> | 2022-08-15 12:59:53 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-15 12:59:53 +0000 |
| commit | 4916e2b9e6ef8cee6f9c6abb75bd01ba9dc07e5c (patch) | |
| tree | 7115ce81f5279dae264956cac3d4be4dcedc1c18 | |
| parent | 6ce76091c7cef21692a15dce1f0a4c415d245be4 (diff) | |
| parent | 03b93d008d16132dc644d811bef9e452c515ed75 (diff) | |
| download | rust-4916e2b9e6ef8cee6f9c6abb75bd01ba9dc07e5c.tar.gz rust-4916e2b9e6ef8cee6f9c6abb75bd01ba9dc07e5c.zip | |
Auto merge of #98393 - michaelwoerister:new-cpp-like-enum-debuginfo, r=wesleywiser
debuginfo: Generalize C++-like encoding for enums. The updated encoding should be able to handle niche layouts where more than one variant has fields (as introduced in https://github.com/rust-lang/rust/pull/94075). The new encoding is more uniform as there is no structural difference between direct-tag, niche-tag, and no-tag layouts anymore. The only difference between those cases is that the "dataful" variant in a niche-tag enum will have a `(start, end)` pair denoting the tag range instead of a single value. The new encoding now also supports 128-bit tags, which occur in at least some standard library types. These tags are represented as `u64` pairs so that debuggers (which don't always have support for 128-bit integers) can reliably deal with them. The downside is that this adds quite a bit of complexity to the encoding and especially to the corresponding NatVis. The new encoding seems to increase the size of (x86_64-pc-windows-msvc) debuginfo by 10-15%. The size of binaries is not affected (release builds were built with `-Cdebuginfo=2`, numbers are in kilobytes): EXE | before | after | relative -- | -- | -- | -- cargo (debug) | 40453 | 40450 | +0% ripgrep (debug) | 10275 | 10273 | +0% cargo (release) | 16186 | 16185 | +0% ripgrep (release) | 4727 | 4726 | +0% PDB | before | after | relative -- | -- | -- | -- cargo (debug) | 236524 | 261412 | +11% ripgrep (debug) | 53140 | 59060 | +11% cargo (release) | 148516 | 169620 | +14% ripgrep (release) | 10676 | 11804 | +11% Given that the new encoding is more general, this is to be expected. Only platforms using C++-like debuginfo are affected -- which currently is only `*-pc-windows-msvc`. *TODO* - [x] Properly update documentation - [x] Add regression tests for new optimized enum layouts as introduced by #94075. r? `@wesleywiser`
23 files changed, 1118 insertions, 424 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index bd84100e0e8..25a989bdf05 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -114,6 +114,7 @@ macro_rules! return_if_di_node_created_in_meantime { } /// Extract size and alignment from a TyAndLayout. +#[inline] fn size_and_align_of<'tcx>(ty_and_layout: TyAndLayout<'tcx>) -> (Size, Align) { (ty_and_layout.size, ty_and_layout.align.abi) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index d6e2c8ccdf4..daec9303b2c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -1,19 +1,21 @@ use std::borrow::Cow; use libc::c_uint; -use rustc_codegen_ssa::debuginfo::{ - type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo, +use rustc_codegen_ssa::{ + debuginfo::{type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo}, + traits::ConstMethods, }; + +use rustc_index::vec::IndexVec; use rustc_middle::{ bug, ty::{ self, layout::{LayoutOf, TyAndLayout}, - util::Discr, - AdtDef, GeneratorSubsts, + AdtDef, GeneratorSubsts, Ty, }, }; -use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants}; +use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use smallvec::smallvec; use crate::{ @@ -21,9 +23,9 @@ use crate::{ debuginfo::{ metadata::{ build_field_di_node, closure_saved_names_of_captured_variables, - enums::tag_base_type, - file_metadata, generator_layout_and_saved_local_names, size_and_align_of, - type_map::{self, UniqueTypeId}, + enums::{tag_base_type, DiscrResult}, + file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node, + type_map::{self, Stub, UniqueTypeId}, unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA, UNKNOWN_LINE_NUMBER, }, @@ -35,59 +37,161 @@ use crate::{ }, }; -/// In CPP-like mode, we generate a union of structs for each variant and an -/// explicit discriminant field roughly equivalent to the following C/C++ code: +// The names of the associated constants in each variant wrapper struct. +// These have to match up with the names being used in `intrinsic.natvis`. +const ASSOC_CONST_DISCR_NAME: &str = "NAME"; +const ASSOC_CONST_DISCR_EXACT: &str = "DISCR_EXACT"; +const ASSOC_CONST_DISCR_BEGIN: &str = "DISCR_BEGIN"; +const ASSOC_CONST_DISCR_END: &str = "DISCR_END"; + +const ASSOC_CONST_DISCR128_EXACT_LO: &str = "DISCR128_EXACT_LO"; +const ASSOC_CONST_DISCR128_EXACT_HI: &str = "DISCR128_EXACT_HI"; +const ASSOC_CONST_DISCR128_BEGIN_LO: &str = "DISCR128_BEGIN_LO"; +const ASSOC_CONST_DISCR128_BEGIN_HI: &str = "DISCR128_BEGIN_HI"; +const ASSOC_CONST_DISCR128_END_LO: &str = "DISCR128_END_LO"; +const ASSOC_CONST_DISCR128_END_HI: &str = "DISCR128_END_HI"; + +// The name of the tag field in the top-level union +const TAG_FIELD_NAME: &str = "tag"; +const TAG_FIELD_NAME_128_LO: &str = "tag128_lo"; +const TAG_FIELD_NAME_128_HI: &str = "tag128_hi"; + +// We assign a "virtual" discriminant value to the sole variant of +// a single-variant enum. +const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0; + +/// In CPP-like mode, we generate a union with a field for each variant and an +/// explicit tag field. The field of each variant has a struct type +/// that encodes the discrimiant of the variant and it's data layout. +/// The union also has a nested enumeration type that is only used for encoding +/// variant names in an efficient way. Its enumerator values do _not_ correspond +/// to the enum's discriminant values. +/// It's roughly equivalent to the following C/C++ code: /// /// ```c -/// union enum$<{fully-qualified-name}> { -/// struct {variant 0 name} { -/// <variant 0 fields> +/// union enum2$<{fully-qualified-name}> { +/// struct Variant0 { +/// struct {name-of-variant-0} { +/// <variant 0 fields> +/// } value; +/// +/// static VariantNames NAME = {name-of-variant-0}; +/// static int_type DISCR_EXACT = {discriminant-of-variant-0}; /// } variant0; +/// /// <other variant structs> -/// {name} discriminant; +/// +/// int_type tag; +/// +/// enum VariantNames { +/// <name-of-variant-0> = 0, // The numeric values are variant index, +/// <name-of-variant-1> = 1, // not discriminant values. +/// <name-of-variant-2> = 2, +/// ... +/// } /// } /// ``` /// -/// As you can see, the type name is wrapped `enum$`. This way we can have a -/// single NatVis rule for handling all enums. +/// As you can see, the type name is wrapped in `enum2$<_>`. This way we can +/// have a single NatVis rule for handling all enums. The `2` in `enum2$<_>` +/// is an encoding version tag, so that debuggers can decide to decode this +/// differently than the previous `enum$<_>` encoding emitted by earlier +/// compiler versions. /// -/// At the LLVM IR level this looks like +/// Niche-tag enums have one special variant, usually called the +/// "dataful variant". This variant has a field that +/// doubles as the tag of the enum. The variant is active when the value of +/// that field is within a pre-defined range. Therefore the variant struct +/// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in +/// that case. Both `DISCR_BEGIN` and `DISCR_END` are inclusive bounds. +/// Note that these ranges can wrap around, so that `DISCR_END < DISCR_BEGIN`. /// -/// ```txt -/// DW_TAG_union_type (top-level type for enum) -/// DW_TAG_member (member for variant 1) -/// DW_TAG_member (member for variant 2) -/// DW_TAG_member (member for variant 3) -/// DW_TAG_structure_type (type of variant 1) -/// DW_TAG_structure_type (type of variant 2) -/// DW_TAG_structure_type (type of variant 3) -/// DW_TAG_enumeration_type (type of tag) -/// ``` +/// Single-variant enums don't actually have a tag field. In this case we +/// emit a static tag field (that always has the value 0) so we can use the +/// same representation (and NatVis). /// -/// The above encoding applies for enums with a direct tag. For niche-tag we have to do things -/// differently in order to allow a NatVis visualizer to extract all the information needed: -/// We generate a union of two fields, one for the dataful variant -/// and one that just points to the discriminant (which is some field within the dataful variant). -/// We also create a DW_TAG_enumeration_type DIE that contains tag values for the non-dataful -/// variants and make the discriminant field that type. We then use NatVis to render the enum type -/// correctly in Windbg/VS. This will generate debuginfo roughly equivalent to the following C: +/// For niche-layout enums it's possible to have a 128-bit tag. NatVis, VS, and +/// WinDbg (the main targets for CPP-like debuginfo at the moment) don't support +/// 128-bit integers, so all values involved get split into two 64-bit fields. +/// Instead of the `tag` field, we generate two fields `tag128_lo` and `tag128_hi`, +/// Instead of `DISCR_EXACT`, we generate `DISCR128_EXACT_LO` and `DISCR128_EXACT_HI`, +/// and so on. /// -/// ```c -/// union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> { -/// struct <dataful variant name> { -/// <fields in dataful variant> -/// } dataful_variant; -/// enum Discriminant$ { -/// <non-dataful variants> -/// } discriminant; +/// +/// The following pseudocode shows how to decode an enum value in a debugger: +/// +/// ```text +/// +/// fn find_active_variant(enum_value) -> (VariantName, VariantValue) { +/// let is_128_bit = enum_value.has_field("tag128_lo"); +/// +/// if !is_128_bit { +/// // Note: `tag` can be a static field for enums with only one +/// // inhabited variant. +/// let tag = enum_value.field("tag").value; +/// +/// // For each variant, check if it is a match. Only one of them will match, +/// // so if we find it we can return it immediately. +/// for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) { +/// if variant_field.has_field("DISCR_EXACT") { +/// // This variant corresponds to a single tag value +/// if variant_field.field("DISCR_EXACT").value == tag { +/// return (variant_field.field("NAME"), variant_field.value); +/// } +/// } else { +/// // This is a range variant +/// let begin = variant_field.field("DISCR_BEGIN"); +/// let end = variant_field.field("DISCR_END"); +/// +/// if is_in_range(tag, begin, end) { +/// return (variant_field.field("NAME"), variant_field.value); +/// } +/// } +/// } +/// } else { +/// // Basically the same as with smaller tags, we just have to +/// // stitch the values together. +/// let tag: u128 = (enum_value.field("tag128_lo").value as u128) | +/// (enum_value.field("tag128_hi").value as u128 << 64); +/// +/// for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) { +/// if variant_field.has_field("DISCR128_EXACT_LO") { +/// let discr_exact = (variant_field.field("DISCR128_EXACT_LO" as u128) | +/// (variant_field.field("DISCR128_EXACT_HI") as u128 << 64); +/// +/// // This variant corresponds to a single tag value +/// if discr_exact.value == tag { +/// return (variant_field.field("NAME"), variant_field.value); +/// } +/// } else { +/// // This is a range variant +/// let begin = (variant_field.field("DISCR128_BEGIN_LO").value as u128) | +/// (variant_field.field("DISCR128_BEGIN_HI").value as u128 << 64); +/// let end = (variant_field.field("DISCR128_END_LO").value as u128) | +/// (variant_field.field("DISCR128_END_HI").value as u128 << 64); +/// +/// if is_in_range(tag, begin, end) { +/// return (variant_field.field("NAME"), variant_field.value); +/// } +/// } +/// } +/// } +/// +/// // We should have found an active variant at this point. +/// unreachable!(); /// } -/// ``` /// -/// The NatVis in `intrinsic.natvis` matches on the type name `enum$<*, *, *, *>` -/// and evaluates `this.discriminant`. If the value is between the min niche and max -/// niche, then the enum is in the dataful variant and `this.dataful_variant` is -/// rendered. Otherwise, the enum is in one of the non-dataful variants. In that -/// case, we just need to render the name of the `this.discriminant` enum. +/// // Check if a value is within the given range +/// // (where the range might wrap around the value space) +/// fn is_in_range(value, start, end) -> bool { +/// if start < end { +/// value >= start && value <= end +/// } else { +/// value >= start || value <= end +/// } +/// } +/// +/// ``` pub(super) fn build_enum_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId<'tcx>, @@ -135,27 +239,28 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( ref variants, tag_field, .. - } => build_union_fields_for_direct_tag_enum( + } => build_union_fields_for_enum( cx, enum_adt_def, enum_type_and_layout, enum_type_di_node, - &mut variants.indices(), + variants.indices(), tag_field, + None, ), Variants::Multiple { tag_encoding: TagEncoding::Niche { dataful_variant, .. }, ref variants, tag_field, .. - } => build_union_fields_for_niche_tag_enum( + } => build_union_fields_for_enum( cx, enum_adt_def, enum_type_and_layout, enum_type_di_node, - dataful_variant, - &mut variants.indices(), + variants.indices(), tag_field, + Some(dataful_variant), ), } }, @@ -217,137 +322,344 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let variant_layout = enum_type_and_layout.for_variant(cx, variant_index); let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node( cx, - enum_type_and_layout.ty, + enum_type_and_layout, enum_type_di_node, variant_index, enum_adt_def.variant(variant_index), variant_layout, ); - // NOTE: The field name of the union is the same as the variant name, not "variant0". - let variant_name = enum_adt_def.variant(variant_index).name.as_str(); + let tag_base_type = cx.tcx.types.u32; + let tag_base_type_di_node = type_di_node(cx, tag_base_type); + let tag_base_type_align = cx.align_of(tag_base_type); - smallvec![build_field_di_node( + let variant_names_type_di_node = build_variant_names_type_di_node( cx, enum_type_di_node, - variant_name, - // NOTE: We use the size and align of the entire type, not from variant_layout - // since the later is sometimes smaller (if it has fewer fields). - size_and_align_of(enum_type_and_layout), - Size::ZERO, - DIFlags::FlagZero, + std::iter::once(( + variant_index, + Cow::from(enum_adt_def.variant(variant_index).name.as_str()), + )), + ); + + let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( + cx, + enum_type_and_layout, + enum_type_di_node, + variant_index, + None, variant_struct_type_di_node, - )] + variant_names_type_di_node, + tag_base_type_di_node, + tag_base_type, + DiscrResult::NoDiscriminant, + ); + + smallvec![ + build_field_di_node( + cx, + enum_type_di_node, + &variant_union_field_name(variant_index), + // NOTE: We use the size and align of the entire type, not from variant_layout + // since the later is sometimes smaller (if it has fewer fields). + size_and_align_of(enum_type_and_layout), + Size::ZERO, + DIFlags::FlagZero, + variant_struct_type_wrapper_di_node, + ), + unsafe { + llvm::LLVMRustDIBuilderCreateStaticMemberType( + DIB(cx), + enum_type_di_node, + TAG_FIELD_NAME.as_ptr().cast(), + TAG_FIELD_NAME.len(), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, + variant_names_type_di_node, + DIFlags::FlagZero, + Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)), + tag_base_type_align.bits() as u32, + ) + } + ] } -fn build_union_fields_for_direct_tag_enum<'ll, 'tcx>( +fn build_union_fields_for_enum<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_adt_def: AdtDef<'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, enum_type_di_node: &'ll DIType, - variant_indices: &mut dyn Iterator<Item = VariantIdx>, + variant_indices: impl Iterator<Item = VariantIdx> + Clone, tag_field: usize, + dataful_variant_index: Option<VariantIdx>, ) -> SmallVec<&'ll DIType> { + let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); + + let variant_names_type_di_node = build_variant_names_type_di_node( + cx, + enum_type_di_node, + variant_indices.clone().map(|variant_index| { + let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); + (variant_index, variant_name) + }), + ); + let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices .map(|variant_index| { let variant_layout = enum_type_and_layout.for_variant(cx, variant_index); + let variant_def = enum_adt_def.variant(variant_index); + + let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node( + cx, + enum_type_and_layout, + enum_type_di_node, + variant_index, + variant_def, + variant_layout, + ); + VariantFieldInfo { variant_index, - variant_struct_type_di_node: super::build_enum_variant_struct_type_di_node( - cx, - enum_type_and_layout.ty, - enum_type_di_node, - variant_index, - enum_adt_def.variant(variant_index), - variant_layout, - ), + variant_struct_type_di_node, source_info: None, + discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index), } }) .collect(); - let discr_type_name = cx.tcx.item_name(enum_adt_def.did()); - let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); - let discr_type_di_node = super::build_enumeration_type_di_node( - cx, - discr_type_name.as_str(), - tag_base_type, - &mut enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| { - (discr, Cow::from(enum_adt_def.variant(variant_index).name.as_str())) - }), - enum_type_di_node, - ); - build_union_fields_for_direct_tag_enum_or_generator( cx, enum_type_and_layout, enum_type_di_node, &variant_field_infos, - discr_type_di_node, + variant_names_type_di_node, + tag_base_type, tag_field, + dataful_variant_index, ) } -fn build_union_fields_for_niche_tag_enum<'ll, 'tcx>( +// The base type of the VariantNames DW_AT_enumeration_type is always the same. +// It has nothing to do with the tag of the enum and just has to be big enough +// to hold all variant names. +fn variant_names_enum_base_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> Ty<'tcx> { + cx.tcx.types.u32 +} + +/// This function builds a DW_AT_enumeration_type that contains an entry for +/// each variant. Note that this has nothing to do with the discriminant. The +/// numeric value of each enumerator corresponds to the variant index. The +/// type is only used for efficiently encoding the name of each variant in +/// debuginfo. +fn build_variant_names_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - enum_adt_def: AdtDef<'tcx>, - enum_type_and_layout: TyAndLayout<'tcx>, - enum_type_di_node: &'ll DIType, - dataful_variant_index: VariantIdx, - variant_indices: &mut dyn Iterator<Item = VariantIdx>, - tag_field: usize, -) -> SmallVec<&'ll DIType> { - let dataful_variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node( + containing_scope: &'ll DIType, + variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>, +) -> &'ll DIType { + // Create an enumerator for each variant. + super::build_enumeration_type_di_node( cx, - enum_type_and_layout.ty, - enum_type_di_node, - dataful_variant_index, - &enum_adt_def.variant(dataful_variant_index), - enum_type_and_layout.for_variant(cx, dataful_variant_index), - ); + "VariantNames", + variant_names_enum_base_type(cx), + variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32() as u64)), + containing_scope, + ) +} - let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); - // Create an DW_TAG_enumerator for each variant except the dataful one. - let discr_type_di_node = super::build_enumeration_type_di_node( +fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + enum_or_generator_type_and_layout: TyAndLayout<'tcx>, + enum_or_generator_type_di_node: &'ll DIType, + variant_index: VariantIdx, + dataful_variant_index: Option<VariantIdx>, + variant_struct_type_di_node: &'ll DIType, + variant_names_type_di_node: &'ll DIType, + tag_base_type_di_node: &'ll DIType, + tag_base_type: Ty<'tcx>, + discr: DiscrResult, +) -> &'ll DIType { + type_map::build_type_with_children( cx, - "Discriminant$", - tag_base_type, - &mut variant_indices.filter_map(|variant_index| { - if let Some(discr_val) = - super::compute_discriminant_value(cx, enum_type_and_layout, variant_index) - { - let discr = Discr { val: discr_val as u128, ty: tag_base_type }; - let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); - Some((discr, variant_name)) - } else { - debug_assert_eq!(variant_index, dataful_variant_index); - None - } - }), - enum_type_di_node, - ); - - smallvec![ - build_field_di_node( - cx, - enum_type_di_node, - "dataful_variant", - size_and_align_of(enum_type_and_layout), - Size::ZERO, - DIFlags::FlagZero, - dataful_variant_struct_type_di_node, - ), - build_field_di_node( + type_map::stub( cx, - enum_type_di_node, - "discriminant", - cx.size_and_align_of(tag_base_type), - enum_type_and_layout.fields.offset(tag_field), + Stub::Struct, + UniqueTypeId::for_enum_variant_struct_type_wrapper( + cx.tcx, + enum_or_generator_type_and_layout.ty, + variant_index, + ), + &variant_struct_wrapper_type_name(variant_index), + // NOTE: We use size and align of enum_type, not from variant_layout: + size_and_align_of(enum_or_generator_type_and_layout), + Some(enum_or_generator_type_di_node), DIFlags::FlagZero, - discr_type_di_node, ), - ] + |cx, wrapper_struct_type_di_node| { + enum DiscrKind { + Exact(u64), + Exact128(u128), + Range(u64, u64), + Range128(u128, u128), + } + + let (tag_base_type_size, tag_base_type_align) = cx.size_and_align_of(tag_base_type); + let is_128_bits = tag_base_type_size.bits() > 64; + + let discr = match discr { + DiscrResult::NoDiscriminant => DiscrKind::Exact(SINGLE_VARIANT_VIRTUAL_DISR), + DiscrResult::Value(discr_val) => { + if is_128_bits { + DiscrKind::Exact128(discr_val) + } else { + debug_assert_eq!(discr_val, discr_val as u64 as u128); + DiscrKind::Exact(discr_val as u64) + } + } + DiscrResult::Range(min, max) => { + assert_eq!(Some(variant_index), dataful_variant_index); + if is_128_bits { + DiscrKind::Range128(min, max) + } else { + debug_assert_eq!(min, min as u64 as u128); + debug_assert_eq!(max, max as u64 as u128); + DiscrKind::Range(min as u64, max as u64) + } + } + }; + + let mut fields = SmallVec::new(); + + // We always have a field for the value + fields.push(build_field_di_node( + cx, + wrapper_struct_type_di_node, + "value", + size_and_align_of(enum_or_generator_type_and_layout), + Size::ZERO, + DIFlags::FlagZero, + variant_struct_type_di_node, + )); + + let build_assoc_const = + |name: &str, type_di_node: &'ll DIType, value: u64, align: Align| unsafe { + llvm::LLVMRustDIBuilderCreateStaticMemberType( + DIB(cx), + wrapper_struct_type_di_node, + name.as_ptr().cast(), + name.len(), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, + type_di_node, + DIFlags::FlagZero, + Some(cx.const_u64(value)), + align.bits() as u32, + ) + }; + + // We also always have an associated constant for the discriminant value + // of the variant. + fields.push(build_assoc_const( + ASSOC_CONST_DISCR_NAME, + variant_names_type_di_node, + variant_index.as_u32() as u64, + cx.align_of(variant_names_enum_base_type(cx)), + )); + + // Emit the discriminant value (or range) corresponding to the variant. + match discr { + DiscrKind::Exact(discr_val) => { + fields.push(build_assoc_const( + ASSOC_CONST_DISCR_EXACT, + tag_base_type_di_node, + discr_val, + tag_base_type_align, + )); + } + DiscrKind::Exact128(discr_val) => { + let align = cx.align_of(cx.tcx.types.u64); + let type_di_node = type_di_node(cx, cx.tcx.types.u64); + let Split128 { hi, lo } = split_128(discr_val); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_EXACT_LO, + type_di_node, + lo, + align, + )); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_EXACT_HI, + type_di_node, + hi, + align, + )); + } + DiscrKind::Range(begin, end) => { + fields.push(build_assoc_const( + ASSOC_CONST_DISCR_BEGIN, + tag_base_type_di_node, + begin, + tag_base_type_align, + )); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR_END, + tag_base_type_di_node, + end, + tag_base_type_align, + )); + } + DiscrKind::Range128(begin, end) => { + let align = cx.align_of(cx.tcx.types.u64); + let type_di_node = type_di_node(cx, cx.tcx.types.u64); + let Split128 { hi: begin_hi, lo: begin_lo } = split_128(begin); + let Split128 { hi: end_hi, lo: end_lo } = split_128(end); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_BEGIN_HI, + type_di_node, + begin_hi, + align, + )); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_BEGIN_LO, + type_di_node, + begin_lo, + align, + )); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_END_HI, + type_di_node, + end_hi, + align, + )); + + fields.push(build_assoc_const( + ASSOC_CONST_DISCR128_END_LO, + type_di_node, + end_lo, + align, + )); + } + } + + fields + }, + NO_GENERICS, + ) + .di_node +} + +struct Split128 { + hi: u64, + lo: u64, +} + +fn split_128(value: u128) -> Split128 { + Split128 { hi: (value >> 64) as u64, lo: value as u64 } } fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>( @@ -369,6 +681,29 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>( let common_upvar_names = closure_saved_names_of_captured_variables(cx.tcx, generator_def_id); let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx); + let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len(); + + let tag_base_type = tag_base_type(cx, generator_type_and_layout); + + let variant_names_type_di_node = build_variant_names_type_di_node( + cx, + generator_type_di_node, + variant_range + .clone() + .map(|variant_index| (variant_index, GeneratorSubsts::variant_name(variant_index))), + ); + + let discriminants: IndexVec<VariantIdx, DiscrResult> = { + let discriminants_iter = generator_substs.discriminants(generator_def_id, cx.tcx); + let mut discriminants: IndexVec<VariantIdx, DiscrResult> = + IndexVec::with_capacity(variant_count); + for (variant_index, discr) in discriminants_iter { + // Assert that the index in the IndexMap matches up with the given VariantIdx. + assert_eq!(variant_index, discriminants.next_index()); + discriminants.push(DiscrResult::Value(discr.val)); + } + discriminants + }; // Build the type node for each field. let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range @@ -391,29 +726,24 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>( None }; - VariantFieldInfo { variant_index, variant_struct_type_di_node, source_info } + VariantFieldInfo { + variant_index, + variant_struct_type_di_node, + source_info, + discr: discriminants[variant_index], + } }) .collect(); - let tag_base_type = tag_base_type(cx, generator_type_and_layout); - let discr_type_name = "Discriminant$"; - let discr_type_di_node = super::build_enumeration_type_di_node( - cx, - discr_type_name, - tag_base_type, - &mut generator_substs - .discriminants(generator_def_id, cx.tcx) - .map(|(variant_index, discr)| (discr, GeneratorSubsts::variant_name(variant_index))), - generator_type_di_node, - ); - build_union_fields_for_direct_tag_enum_or_generator( cx, generator_type_and_layout, generator_type_di_node, &variant_field_infos[..], - discr_type_di_node, + variant_names_type_di_node, + tag_base_type, tag_field, + None, ) } @@ -425,8 +755,11 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( enum_type_di_node: &'ll DIType, variant_field_infos: &[VariantFieldInfo<'ll>], discr_type_di_node: &'ll DIType, + tag_base_type: Ty<'tcx>, tag_field: usize, + dataful_variant_index: Option<VariantIdx>, ) -> SmallVec<&'ll DIType> { + let tag_base_type_di_node = type_di_node(cx, tag_base_type); let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1); // We create a field in the union for each variant ... @@ -438,6 +771,19 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( let field_name = variant_union_field_name(variant_member_info.variant_index); let (size, align) = size_and_align_of(enum_type_and_layout); + let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node( + cx, + enum_type_and_layout, + enum_type_di_node, + variant_member_info.variant_index, + dataful_variant_index, + variant_member_info.variant_struct_type_di_node, + discr_type_di_node, + tag_base_type_di_node, + tag_base_type, + variant_member_info.discr, + ); + // We use LLVMRustDIBuilderCreateMemberType() member type directly because // the build_field_di_node() function does not support specifying a source location, // which is something that we don't do anywhere else. @@ -456,7 +802,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( // Union fields are always at offset zero Size::ZERO.bits(), DIFlags::FlagZero, - variant_member_info.variant_struct_type_di_node, + variant_struct_type_wrapper, ) } })); @@ -466,16 +812,53 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout)) ); - // ... and a field for the discriminant. - unions_fields.push(build_field_di_node( - cx, - enum_type_di_node, - "discriminant", - cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), - enum_type_and_layout.fields.offset(tag_field), - DIFlags::FlagZero, - discr_type_di_node, - )); + // ... and a field for the tag. If the tag is 128 bits wide, this will actually + // be two 64-bit fields. + let is_128_bits = cx.size_of(tag_base_type).bits() > 64; + + if is_128_bits { + let type_di_node = type_di_node(cx, cx.tcx.types.u64); + let size_and_align = cx.size_and_align_of(cx.tcx.types.u64); + + let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian { + Endian::Little => (0, 8), + Endian::Big => (8, 0), + }; + + let tag_field_offset = enum_type_and_layout.fields.offset(tag_field).bytes(); + let lo_offset = Size::from_bytes(tag_field_offset + lo_offset); + let hi_offset = Size::from_bytes(tag_field_offset + hi_offset); + + unions_fields.push(build_field_di_node( + cx, + enum_type_di_node, + TAG_FIELD_NAME_128_LO, + size_and_align, + lo_offset, + DIFlags::FlagZero, + type_di_node, + )); + + unions_fields.push(build_field_di_node( + cx, + enum_type_di_node, + TAG_FIELD_NAME_128_HI, + size_and_align, + hi_offset, + DIFlags::FlagZero, + type_di_node, + )); + } else { + unions_fields.push(build_field_di_node( + cx, + enum_type_di_node, + TAG_FIELD_NAME, + cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), + enum_type_and_layout.fields.offset(tag_field), + DIFlags::FlagZero, + tag_base_type_di_node, + )); + } unions_fields } @@ -485,6 +868,7 @@ struct VariantFieldInfo<'ll> { variant_index: VariantIdx, variant_struct_type_di_node: &'ll DIType, source_info: Option<(&'ll DIFile, c_uint)>, + discr: DiscrResult, } fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> { @@ -512,3 +896,29 @@ fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> { .map(|&s| Cow::from(s)) .unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into()) } + +fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> { + const PRE_ALLOCATED: [&str; 16] = [ + "Variant0", + "Variant1", + "Variant2", + "Variant3", + "Variant4", + "Variant5", + "Variant6", + "Variant7", + "Variant8", + "Variant9", + "Variant10", + "Variant11", + "Variant12", + "Variant13", + "Variant14", + "Variant15", + ]; + + PRE_ALLOCATED + .get(variant_index.as_usize()) + .map(|&s| Cow::from(s)) + .unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into()) +} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 73e01d0453b..9b3d080bfd6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -10,7 +10,6 @@ use rustc_middle::{ ty::{ self, layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}, - util::Discr, AdtDef, GeneratorSubsts, Ty, VariantDef, }, }; @@ -90,8 +89,11 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( cx, &compute_debuginfo_type_name(cx.tcx, enum_type_and_layout.ty, false), tag_base_type(cx, enum_type_and_layout), - &mut enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| { - (discr, Cow::from(enum_adt_def.variant(variant_index).name.as_str())) + enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| { + let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); + // Is there anything we can do to support 128-bit C-Style enums? + let value = discr.val as u64; + (name, value) }), containing_scope, ), @@ -152,7 +154,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, type_name: &str, base_type: Ty<'tcx>, - variants: &mut dyn Iterator<Item = (Discr<'tcx>, Cow<'tcx, str>)>, + enumerators: impl Iterator<Item = (Cow<'tcx, str>, u64)>, containing_scope: &'ll DIType, ) -> &'ll DIType { let is_unsigned = match base_type.kind() { @@ -161,18 +163,15 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( _ => bug!("build_enumeration_type_di_node() called with non-integer tag type."), }; - let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = variants - .map(|(discr, variant_name)| { - unsafe { - Some(llvm::LLVMRustDIBuilderCreateEnumerator( - DIB(cx), - variant_name.as_ptr().cast(), - variant_name.len(), - // FIXME: what if enumeration has i128 discriminant? - discr.val as i64, - is_unsigned, - )) - } + let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = enumerators + .map(|(name, value)| unsafe { + Some(llvm::LLVMRustDIBuilderCreateEnumerator( + DIB(cx), + name.as_ptr().cast(), + name.len(), + value as i64, + is_unsigned, + )) }) .collect(); @@ -247,23 +246,27 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( /// and a DW_TAG_member for each field (but not the discriminant). fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - enum_type: Ty<'tcx>, + enum_type_and_layout: TyAndLayout<'tcx>, enum_type_di_node: &'ll DIType, variant_index: VariantIdx, variant_def: &VariantDef, variant_layout: TyAndLayout<'tcx>, ) -> &'ll DIType { - debug_assert_eq!(variant_layout.ty, enum_type); + debug_assert_eq!(variant_layout.ty, enum_type_and_layout.ty); type_map::build_type_with_children( cx, type_map::stub( cx, Stub::Struct, - UniqueTypeId::for_enum_variant_struct_type(cx.tcx, enum_type, variant_index), + UniqueTypeId::for_enum_variant_struct_type( + cx.tcx, + enum_type_and_layout.ty, + variant_index, + ), variant_def.name.as_str(), // NOTE: We use size and align of enum_type, not from variant_layout: - cx.size_and_align_of(enum_type), + size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), DIFlags::FlagZero, ), @@ -290,9 +293,9 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( type_di_node(cx, field_layout.ty), ) }) - .collect() + .collect::<SmallVec<_>>() }, - |cx| build_generic_type_param_di_nodes(cx, enum_type), + |cx| build_generic_type_param_di_nodes(cx, enum_type_and_layout.ty), ) .di_node } @@ -398,6 +401,19 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( .di_node } +#[derive(Copy, Clone)] +enum DiscrResult { + NoDiscriminant, + Value(u128), + Range(u128, u128), +} + +impl DiscrResult { + fn opt_single_val(&self) -> Option<u128> { + if let Self::Value(d) = *self { Some(d) } else { None } + } +} + /// Returns the discriminant value corresponding to the variant index. /// /// Will return `None` if there is less than two variants (because then the enum won't have) @@ -407,12 +423,11 @@ fn compute_discriminant_value<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, variant_index: VariantIdx, -) -> Option<u64> { +) -> DiscrResult { match enum_type_and_layout.layout.variants() { - &Variants::Single { .. } => None, - &Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => Some( - enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val - as u64, + &Variants::Single { .. } => DiscrResult::NoDiscriminant, + &Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value( + enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val, ), &Variants::Multiple { tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, @@ -420,17 +435,26 @@ fn compute_discriminant_value<'ll, 'tcx>( .. } => { if variant_index == dataful_variant { - None + let valid_range = enum_type_and_layout + .for_variant(cx, variant_index) + .largest_niche + .as_ref() + .unwrap() + .valid_range; + + let min = valid_range.start.min(valid_range.end); + let min = tag.size(cx).truncate(min); + + let max = valid_range.start.max(valid_range.end); + let max = tag.size(cx).truncate(max); + + DiscrResult::Range(min, max) } else { let value = (variant_index.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); let value = tag.size(cx).truncate(value); - // NOTE(eddyb) do *NOT* remove this assert, until - // we pass the full 128-bit value to LLVM, otherwise - // truncation will be silent and remain undetected. - assert_eq!(value as u64 as u128, value); - Some(value as u64) + DiscrResult::Value(value) } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index f1935e0ec31..dae90a43f26 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -88,7 +88,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( variant_name: Cow::from(enum_adt_def.variant(variant_index).name.as_str()), variant_struct_type_di_node: super::build_enum_variant_struct_type_di_node( cx, - enum_type, + enum_type_and_layout, enum_type_di_node, variant_index, enum_adt_def.variant(variant_index), @@ -413,7 +413,13 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( enum_type_and_layout.size.bits(), enum_type_and_layout.align.abi.bits() as u32, Size::ZERO.bits(), - discr_value.map(|v| cx.const_u64(v)), + discr_value.opt_single_val().map(|value| { + // NOTE(eddyb) do *NOT* remove this assert, until + // we pass the full 128-bit value to LLVM, otherwise + // truncation will be silent and remain undetected. + assert_eq!(value as u64 as u128, value); + cx.const_u64(value as u64) + }), DIFlags::FlagZero, variant_member_info.variant_struct_type_di_node, ) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index ce2f419c4ac..e30622cbdce 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -47,6 +47,8 @@ pub(super) enum UniqueTypeId<'tcx> { VariantPart(Ty<'tcx>, private::HiddenZst), /// The ID for the artificial struct type describing a single enum variant. VariantStructType(Ty<'tcx>, VariantIdx, private::HiddenZst), + /// The ID for the additional wrapper struct type describing an enum variant in CPP-like mode. + VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst), /// The ID of the artificial type we create for VTables. VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst), } @@ -71,6 +73,15 @@ impl<'tcx> UniqueTypeId<'tcx> { UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } + pub fn for_enum_variant_struct_type_wrapper( + tcx: TyCtxt<'tcx>, + enum_ty: Ty<'tcx>, + variant_idx: VariantIdx, + ) -> Self { + debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) + } + pub fn for_vtable_ty( tcx: TyCtxt<'tcx>, self_type: Ty<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3139f93bfef..89611fc0dee 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2079,6 +2079,19 @@ extern "C" { Ty: &'a DIType, ) -> &'a DIType; + pub fn LLVMRustDIBuilderCreateStaticMemberType<'a>( + Builder: &DIBuilder<'a>, + Scope: &'a DIDescriptor, + Name: *const c_char, + NameLen: size_t, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + Flags: DIFlags, + val: Option<&'a Value>, + AlignInBits: u32, + ) -> &'a DIDerivedType; + pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 8cd5a0fc247..135ed680da2 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -18,11 +18,10 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability}; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ExistentialProjection, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; -use rustc_target::abi::{Integer, TagEncoding, Variants}; +use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt}; +use rustc_target::abi::Integer; use smallvec::SmallVec; -use std::borrow::Cow; use std::fmt::Write; use crate::debuginfo::wants_c_like_enum_debuginfo; @@ -98,7 +97,6 @@ fn push_debuginfo_type_name<'tcx>( if let Some(ty_and_layout) = layout_for_cpp_like_fallback { msvc_enum_fallback( - tcx, ty_and_layout, &|output, visited| { push_item_name(tcx, def.did(), true, output); @@ -391,11 +389,10 @@ fn push_debuginfo_type_name<'tcx>( // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or // "{async_fn_env#0}<T1, T2, ...>", etc. // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of - // an artificial `enum$<>` type, as defined in msvc_enum_fallback(). + // an artificial `enum2$<>` type, as defined in msvc_enum_fallback(). if cpp_like_debuginfo && t.is_generator() { let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap(); msvc_enum_fallback( - tcx, ty_and_layout, &|output, visited| { push_closure_or_generator_name(tcx, def_id, substs, true, output, visited); @@ -428,58 +425,17 @@ fn push_debuginfo_type_name<'tcx>( /// MSVC names enums differently than other platforms so that the debugging visualization // format (natvis) is able to understand enums and render the active variant correctly in the - // debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and - // `EnumMemberDescriptionFactor::create_member_descriptions`. + // debugger. For more information, look in + // rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs. fn msvc_enum_fallback<'tcx>( - tcx: TyCtxt<'tcx>, ty_and_layout: TyAndLayout<'tcx>, push_inner: &dyn Fn(/*output*/ &mut String, /*visited*/ &mut FxHashSet<Ty<'tcx>>), output: &mut String, visited: &mut FxHashSet<Ty<'tcx>>, ) { debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout)); - let ty = ty_and_layout.ty; - - output.push_str("enum$<"); + output.push_str("enum2$<"); push_inner(output, visited); - - let variant_name = |variant_index| match ty.kind() { - ty::Adt(adt_def, _) => { - debug_assert!(adt_def.is_enum()); - Cow::from(adt_def.variant(variant_index).name.as_str()) - } - ty::Generator(..) => GeneratorSubsts::variant_name(variant_index), - _ => unreachable!(), - }; - - if let Variants::Multiple { - tag_encoding: TagEncoding::Niche { dataful_variant, .. }, - tag, - variants, - .. - } = &ty_and_layout.variants - { - let dataful_variant_layout = &variants[*dataful_variant]; - - // calculate the range of values for the dataful variant - let dataful_discriminant_range = - dataful_variant_layout.largest_niche().unwrap().valid_range; - - let min = dataful_discriminant_range.start; - let min = tag.size(&tcx).truncate(min); - - let max = dataful_discriminant_range.end; - let max = tag.size(&tcx).truncate(max); - - let dataful_variant_name = variant_name(*dataful_variant); - write!(output, ", {}, {}, {}", min, max, dataful_variant_name).unwrap(); - } else if let Variants::Single { index: variant_idx } = &ty_and_layout.variants { - // Uninhabited enums can't be constructed and should never need to be visualized so - // skip this step for them. - if !ty_and_layout.abi.is_uninhabited() { - write!(output, ", {}", variant_name(*variant_idx)).unwrap(); - } - } push_close_angle_bracket(true, output); } diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 30ff364210d..4172ce3bb30 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -172,7 +172,9 @@ impl<I: Idx, T> IndexVec<I, T> { } #[inline] - pub fn indices(&self) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + 'static { + pub fn indices( + &self, + ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static { (0..self.len()).map(|n| I::new(n)) } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 5f5b5de790e..f9bffe6d823 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -924,6 +924,30 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( fromRust(Flags), unwrapDI<DIType>(Ty))); } +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType( + LLVMRustDIBuilderRef Builder, + LLVMMetadataRef Scope, + const char *Name, + size_t NameLen, + LLVMMetadataRef File, + unsigned LineNo, + LLVMMetadataRef Ty, + LLVMRustDIFlags Flags, + LLVMValueRef val, + uint32_t AlignInBits +) { + return wrap(Builder->createStaticMemberType( + unwrapDI<DIDescriptor>(Scope), + StringRef(Name, NameLen), + unwrapDI<DIFile>(File), + LineNo, + unwrapDI<DIType>(Ty), + fromRust(Flags), + unwrap<llvm::ConstantInt>(val), + AlignInBits + )); +} + extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock( LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, unsigned Col) { diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 558536fa613..277e57aaf6f 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <Type Name="str"> <DisplayString>{(char*)data_ptr,[length]s8}</DisplayString> @@ -150,76 +150,189 @@ </Expand> </Type> - <!-- Directly tagged enums. $T1 is the type name --> - <Type Name="enum$<*>"> - <Intrinsic Name="tag" Expression="discriminant" /> - <DisplayString Condition="tag() == 0">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 3" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 4" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 5" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 6" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 7" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 8" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 9" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 10" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 11" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 12" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 13" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 14" Optional="true">{tag(),en}</DisplayString> - <DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString> + <!-- + This is the visualizer for all enums. It takes care of selecting the active variant. + See `compiler\rustc_codegen_llvm\src\debuginfo\metadata\enums\cpp_like.rs` for more information. + --> + <Type Name="enum2$<*>"> + <!-- NOTE: That tag ranges can wrap around, in which case `end` is less than `begin` and we + have to do a different check --> + <Intrinsic Name="in_range" Expression="(begin <= end) ? ((x >= begin) && (x <= end)) : ((x >= begin) || (x <= end))"> + <Parameter Name="x" Type="unsigned __int64" /> + <Parameter Name="begin" Type="unsigned __int64" /> + <Parameter Name="end" Type="unsigned __int64" /> + </Intrinsic> - <Expand> - <Synthetic Name="[variant]"> - <DisplayString>{tag(),en}</DisplayString> - </Synthetic> - <ExpandedItem Condition="tag() == 0">variant0</ExpandedItem> - <ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem> - <ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem> - <ExpandedItem Condition="tag() == 3" Optional="true">variant3</ExpandedItem> - <ExpandedItem Condition="tag() == 4" Optional="true">variant4</ExpandedItem> - <ExpandedItem Condition="tag() == 5" Optional="true">variant5</ExpandedItem> - <ExpandedItem Condition="tag() == 6" Optional="true">variant6</ExpandedItem> - <ExpandedItem Condition="tag() == 7" Optional="true">variant7</ExpandedItem> - <ExpandedItem Condition="tag() == 8" Optional="true">variant8</ExpandedItem> - <ExpandedItem Condition="tag() == 9" Optional="true">variant9</ExpandedItem> - <ExpandedItem Condition="tag() == 10" Optional="true">variant10</ExpandedItem> - <ExpandedItem Condition="tag() == 11" Optional="true">variant11</ExpandedItem> - <ExpandedItem Condition="tag() == 12" Optional="true">variant12</ExpandedItem> - <ExpandedItem Condition="tag() == 13" Optional="true">variant13</ExpandedItem> - <ExpandedItem Condition="tag() == 14" Optional="true">variant14</ExpandedItem> - <ExpandedItem Condition="tag() == 15" Optional="true">variant15</ExpandedItem> - </Expand> - </Type> + <Intrinsic Name="eq128" Expression="(x_hi == y_hi) && (x_lo == y_lo)"> + <Parameter Name="x_hi" Type="unsigned __int64" /> + <Parameter Name="x_lo" Type="unsigned __int64" /> + <Parameter Name="y_hi" Type="unsigned __int64" /> + <Parameter Name="y_lo" Type="unsigned __int64" /> + </Intrinsic> - <!-- Single variant enums. $T1 is the name of the enum, $T2 is the name of the variant --> - <Type Name="enum$<*, *>"> - <DisplayString>{"$T2",sb}</DisplayString> - <Expand> - <Synthetic Name="[variant]"> - <DisplayString>{"$T2",sb}</DisplayString> - </Synthetic> - <ExpandedItem>$T2</ExpandedItem> - </Expand> - </Type> + <Intrinsic Name="lt128" Expression="(x_hi < y_hi) || ((x_hi == y_hi) && (x_lo < y_lo))"> + <Parameter Name="x_hi" Type="unsigned __int64" /> + <Parameter Name="x_lo" Type="unsigned __int64" /> + <Parameter Name="y_hi" Type="unsigned __int64" /> + <Parameter Name="y_lo" Type="unsigned __int64" /> + </Intrinsic> - <!-- Niche-layout enums. $T1 is the name of the enum, $T2 is the low value of the dataful - variant tag, $T3 is the high value of the dataful variant tag, $T4 is the name of - the dataful variant --> - <Type Name="enum$<*, *, *, *>"> - <Intrinsic Name="tag" Expression="discriminant" /> - <Intrinsic Name="is_dataful" Expression="tag() >= $T2 && tag() <= $T3" /> - <DisplayString Condition="is_dataful()">{"$T4",sb}({dataful_variant})</DisplayString> - <DisplayString Condition="!is_dataful()">{discriminant,en}</DisplayString> - <Expand> - <ExpandedItem Condition="is_dataful()">dataful_variant</ExpandedItem> - <Synthetic Condition="is_dataful()" Name="[variant]"> - <DisplayString>{"$T4",sb}</DisplayString> - </Synthetic> - <Synthetic Condition="!is_dataful()" Name="[variant]"> - <DisplayString>{discriminant,en}</DisplayString> - </Synthetic> + <Intrinsic Name="lt_or_eq128" Expression="((x_hi == y_hi) && (x_lo == y_lo)) || lt128(x_hi, x_lo, y_hi, y_lo)"> + <Parameter Name="x_hi" Type="unsigned __int64" /> + <Parameter Name="x_lo" Type="unsigned __int64" /> + <Parameter Name="y_hi" Type="unsigned __int64" /> + <Parameter Name="y_lo" Type="unsigned __int64" /> + </Intrinsic> + + <!-- NOTE: That tag ranges can wrap around, in which case `end` is less than `begin` and we + have to do a different check --> + <Intrinsic Name="in_range128" Expression="(lt_or_eq128(begin_hi, begin_lo, end_hi, end_lo)) ? + (lt_or_eq128(begin_hi, begin_lo, x_hi, x_lo) && lt_or_eq128(x_hi, x_lo, end_hi, end_lo)) : + (lt_or_eq128(begin_hi, begin_lo, x_hi, x_lo) || lt_or_eq128(x_hi, x_lo, end_hi, end_lo))"> + <Parameter Name="x_hi" Type="unsigned __int64" /> + <Parameter Name="x_lo" Type="unsigned __int64" /> + <Parameter Name="begin_hi" Type="unsigned __int64" /> + <Parameter Name="begin_lo" Type="unsigned __int64" /> + <Parameter Name="end_hi" Type="unsigned __int64" /> + <Parameter Name="end_lo" Type="unsigned __int64" /> + </Intrinsic> + + <DisplayString Condition="tag == variant0.DISCR_EXACT" Optional="true">{variant0.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant1.DISCR_EXACT" Optional="true">{variant1.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant2.DISCR_EXACT" Optional="true">{variant2.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant3.DISCR_EXACT" Optional="true">{variant3.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant4.DISCR_EXACT" Optional="true">{variant4.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant5.DISCR_EXACT" Optional="true">{variant5.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant6.DISCR_EXACT" Optional="true">{variant6.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant7.DISCR_EXACT" Optional="true">{variant7.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant8.DISCR_EXACT" Optional="true">{variant8.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant9.DISCR_EXACT" Optional="true">{variant9.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant10.DISCR_EXACT" Optional="true">{variant10.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant11.DISCR_EXACT" Optional="true">{variant11.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant12.DISCR_EXACT" Optional="true">{variant12.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant13.DISCR_EXACT" Optional="true">{variant13.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant14.DISCR_EXACT" Optional="true">{variant14.NAME,en}</DisplayString> + <DisplayString Condition="tag == variant15.DISCR_EXACT" Optional="true">{variant15.NAME,en}</DisplayString> + + <DisplayString Condition="in_range(tag, variant0.DISCR_BEGIN, variant0.DISCR_END)" Optional="true">{variant0.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant1.DISCR_BEGIN, variant1.DISCR_END)" Optional="true">{variant1.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant2.DISCR_BEGIN, variant2.DISCR_END)" Optional="true">{variant2.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant3.DISCR_BEGIN, variant3.DISCR_END)" Optional="true">{variant3.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant4.DISCR_BEGIN, variant4.DISCR_END)" Optional="true">{variant4.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant5.DISCR_BEGIN, variant5.DISCR_END)" Optional="true">{variant5.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant6.DISCR_BEGIN, variant6.DISCR_END)" Optional="true">{variant6.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant7.DISCR_BEGIN, variant7.DISCR_END)" Optional="true">{variant7.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant8.DISCR_BEGIN, variant8.DISCR_END)" Optional="true">{variant8.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant9.DISCR_BEGIN, variant9.DISCR_END)" Optional="true">{variant9.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant10.DISCR_BEGIN, variant10.DISCR_END)" Optional="true">{variant10.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant11.DISCR_BEGIN, variant11.DISCR_END)" Optional="true">{variant11.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant12.DISCR_BEGIN, variant12.DISCR_END)" Optional="true">{variant12.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant13.DISCR_BEGIN, variant13.DISCR_END)" Optional="true">{variant13.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant14.DISCR_BEGIN, variant14.DISCR_END)" Optional="true">{variant14.NAME,en}</DisplayString> + <DisplayString Condition="in_range(tag, variant15.DISCR_BEGIN, variant15.DISCR_END)" Optional="true">{variant15.NAME,en}</DisplayString> + + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant0.DISCR128_EXACT_HI, variant0.DISCR128_EXACT_LO)" Optional="true">{variant0.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant1.DISCR128_EXACT_HI, variant1.DISCR128_EXACT_LO)" Optional="true">{variant1.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant2.DISCR128_EXACT_HI, variant2.DISCR128_EXACT_LO)" Optional="true">{variant2.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant3.DISCR128_EXACT_HI, variant3.DISCR128_EXACT_LO)" Optional="true">{variant3.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant4.DISCR128_EXACT_HI, variant4.DISCR128_EXACT_LO)" Optional="true">{variant4.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant5.DISCR128_EXACT_HI, variant5.DISCR128_EXACT_LO)" Optional="true">{variant5.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant6.DISCR128_EXACT_HI, variant6.DISCR128_EXACT_LO)" Optional="true">{variant6.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant7.DISCR128_EXACT_HI, variant7.DISCR128_EXACT_LO)" Optional="true">{variant7.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant8.DISCR128_EXACT_HI, variant8.DISCR128_EXACT_LO)" Optional="true">{variant8.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant9.DISCR128_EXACT_HI, variant9.DISCR128_EXACT_LO)" Optional="true">{variant9.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant10.DISCR128_EXACT_HI, variant10.DISCR128_EXACT_LO)" Optional="true">{variant10.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant11.DISCR128_EXACT_HI, variant11.DISCR128_EXACT_LO)" Optional="true">{variant11.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant12.DISCR128_EXACT_HI, variant12.DISCR128_EXACT_LO)" Optional="true">{variant12.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant13.DISCR128_EXACT_HI, variant13.DISCR128_EXACT_LO)" Optional="true">{variant13.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant14.DISCR128_EXACT_HI, variant14.DISCR128_EXACT_LO)" Optional="true">{variant14.NAME,en}</DisplayString> + <DisplayString Condition="eq128(tag128_hi, tag128_lo, variant15.DISCR128_EXACT_HI, variant15.DISCR128_EXACT_LO)" Optional="true">{variant15.NAME,en}</DisplayString> + + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant0.DISCR128_BEGIN_HI, variant0.DISCR128_BEGIN_LO, variant0.DISCR128_END_HI, variant0.DISCR128_END_LO)" Optional="true">{variant0.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant1.DISCR128_BEGIN_HI, variant1.DISCR128_BEGIN_LO, variant1.DISCR128_END_HI, variant1.DISCR128_END_LO)" Optional="true">{variant1.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant2.DISCR128_BEGIN_HI, variant2.DISCR128_BEGIN_LO, variant2.DISCR128_END_HI, variant2.DISCR128_END_LO)" Optional="true">{variant2.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant3.DISCR128_BEGIN_HI, variant3.DISCR128_BEGIN_LO, variant3.DISCR128_END_HI, variant3.DISCR128_END_LO)" Optional="true">{variant3.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant4.DISCR128_BEGIN_HI, variant4.DISCR128_BEGIN_LO, variant4.DISCR128_END_HI, variant4.DISCR128_END_LO)" Optional="true">{variant4.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant5.DISCR128_BEGIN_HI, variant5.DISCR128_BEGIN_LO, variant5.DISCR128_END_HI, variant5.DISCR128_END_LO)" Optional="true">{variant5.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant6.DISCR128_BEGIN_HI, variant6.DISCR128_BEGIN_LO, variant6.DISCR128_END_HI, variant6.DISCR128_END_LO)" Optional="true">{variant6.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant7.DISCR128_BEGIN_HI, variant7.DISCR128_BEGIN_LO, variant7.DISCR128_END_HI, variant7.DISCR128_END_LO)" Optional="true">{variant7.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant8.DISCR128_BEGIN_HI, variant8.DISCR128_BEGIN_LO, variant8.DISCR128_END_HI, variant8.DISCR128_END_LO)" Optional="true">{variant8.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant9.DISCR128_BEGIN_HI, variant9.DISCR128_BEGIN_LO, variant9.DISCR128_END_HI, variant9.DISCR128_END_LO)" Optional="true">{variant9.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant10.DISCR128_BEGIN_HI, variant10.DISCR128_BEGIN_LO, variant10.DISCR128_END_HI, variant10.DISCR128_END_LO)" Optional="true">{variant10.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant11.DISCR128_BEGIN_HI, variant11.DISCR128_BEGIN_LO, variant11.DISCR128_END_HI, variant11.DISCR128_END_LO)" Optional="true">{variant11.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant12.DISCR128_BEGIN_HI, variant12.DISCR128_BEGIN_LO, variant12.DISCR128_END_HI, variant12.DISCR128_END_LO)" Optional="true">{variant12.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant13.DISCR128_BEGIN_HI, variant13.DISCR128_BEGIN_LO, variant13.DISCR128_END_HI, variant13.DISCR128_END_LO)" Optional="true">{variant13.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant14.DISCR128_BEGIN_HI, variant14.DISCR128_BEGIN_LO, variant14.DISCR128_END_HI, variant14.DISCR128_END_LO)" Optional="true">{variant14.NAME,en}</DisplayString> + <DisplayString Condition="in_range128(tag128_hi, tag128_lo, variant15.DISCR128_BEGIN_HI, variant15.DISCR128_BEGIN_LO, variant15.DISCR128_END_HI, variant15.DISCR128_END_LO)" Optional="true">{variant15.NAME,en}</DisplayString> + + <Expand HideRawView="true"> + <ExpandedItem Condition="tag == variant0.DISCR_EXACT" Optional="true">variant0.value</ExpandedItem> + <ExpandedItem Condition="tag == variant1.DISCR_EXACT" Optional="true">variant1.value</ExpandedItem> + <ExpandedItem Condition="tag == variant2.DISCR_EXACT" Optional="true">variant2.value</ExpandedItem> + <ExpandedItem Condition="tag == variant3.DISCR_EXACT" Optional="true">variant3.value</ExpandedItem> + <ExpandedItem Condition="tag == variant4.DISCR_EXACT" Optional="true">variant4.value</ExpandedItem> + <ExpandedItem Condition="tag == variant5.DISCR_EXACT" Optional="true">variant5.value</ExpandedItem> + <ExpandedItem Condition="tag == variant6.DISCR_EXACT" Optional="true">variant6.value</ExpandedItem> + <ExpandedItem Condition="tag == variant7.DISCR_EXACT" Optional="true">variant7.value</ExpandedItem> + <ExpandedItem Condition="tag == variant8.DISCR_EXACT" Optional="true">variant8.value</ExpandedItem> + <ExpandedItem Condition="tag == variant9.DISCR_EXACT" Optional="true">variant9.value</ExpandedItem> + <ExpandedItem Condition="tag == variant10.DISCR_EXACT" Optional="true">variant10.value</ExpandedItem> + <ExpandedItem Condition="tag == variant11.DISCR_EXACT" Optional="true">variant11.value</ExpandedItem> + <ExpandedItem Condition="tag == variant12.DISCR_EXACT" Optional="true">variant12.value</ExpandedItem> + <ExpandedItem Condition="tag == variant13.DISCR_EXACT" Optional="true">variant13.value</ExpandedItem> + <ExpandedItem Condition="tag == variant14.DISCR_EXACT" Optional="true">variant14.value</ExpandedItem> + <ExpandedItem Condition="tag == variant15.DISCR_EXACT" Optional="true">variant15.value</ExpandedItem> + + <ExpandedItem Condition="in_range(tag, variant0.DISCR_BEGIN, variant0.DISCR_END)" Optional="true">variant0.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant1.DISCR_BEGIN, variant1.DISCR_END)" Optional="true">variant1.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant2.DISCR_BEGIN, variant2.DISCR_END)" Optional="true">variant2.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant3.DISCR_BEGIN, variant3.DISCR_END)" Optional="true">variant3.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant4.DISCR_BEGIN, variant4.DISCR_END)" Optional="true">variant4.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant5.DISCR_BEGIN, variant5.DISCR_END)" Optional="true">variant5.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant6.DISCR_BEGIN, variant6.DISCR_END)" Optional="true">variant6.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant7.DISCR_BEGIN, variant7.DISCR_END)" Optional="true">variant7.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant8.DISCR_BEGIN, variant8.DISCR_END)" Optional="true">variant8.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant9.DISCR_BEGIN, variant9.DISCR_END)" Optional="true">variant9.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant10.DISCR_BEGIN, variant10.DISCR_END)" Optional="true">variant10.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant11.DISCR_BEGIN, variant11.DISCR_END)" Optional="true">variant11.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant12.DISCR_BEGIN, variant12.DISCR_END)" Optional="true">variant12.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant13.DISCR_BEGIN, variant13.DISCR_END)" Optional="true">variant13.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant14.DISCR_BEGIN, variant14.DISCR_END)" Optional="true">variant14.value</ExpandedItem> + <ExpandedItem Condition="in_range(tag, variant15.DISCR_BEGIN, variant15.DISCR_END)" Optional="true">variant15.value</ExpandedItem> + + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant0.DISCR128_EXACT_HI, variant0.DISCR128_EXACT_LO)" Optional="true">variant0.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant1.DISCR128_EXACT_HI, variant1.DISCR128_EXACT_LO)" Optional="true">variant1.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant2.DISCR128_EXACT_HI, variant2.DISCR128_EXACT_LO)" Optional="true">variant2.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant3.DISCR128_EXACT_HI, variant3.DISCR128_EXACT_LO)" Optional="true">variant3.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant4.DISCR128_EXACT_HI, variant4.DISCR128_EXACT_LO)" Optional="true">variant4.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant5.DISCR128_EXACT_HI, variant5.DISCR128_EXACT_LO)" Optional="true">variant5.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant6.DISCR128_EXACT_HI, variant6.DISCR128_EXACT_LO)" Optional="true">variant6.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant7.DISCR128_EXACT_HI, variant7.DISCR128_EXACT_LO)" Optional="true">variant7.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant8.DISCR128_EXACT_HI, variant8.DISCR128_EXACT_LO)" Optional="true">variant8.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant9.DISCR128_EXACT_HI, variant9.DISCR128_EXACT_LO)" Optional="true">variant9.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant10.DISCR128_EXACT_HI, variant10.DISCR128_EXACT_LO)" Optional="true">variant10.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant11.DISCR128_EXACT_HI, variant11.DISCR128_EXACT_LO)" Optional="true">variant11.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant12.DISCR128_EXACT_HI, variant12.DISCR128_EXACT_LO)" Optional="true">variant12.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant13.DISCR128_EXACT_HI, variant13.DISCR128_EXACT_LO)" Optional="true">variant13.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant14.DISCR128_EXACT_HI, variant14.DISCR128_EXACT_LO)" Optional="true">variant14.value</ExpandedItem> + <ExpandedItem Condition="eq128(tag128_hi, tag128_lo, variant15.DISCR128_EXACT_HI, variant15.DISCR128_EXACT_LO)" Optional="true">variant15.value</ExpandedItem> + + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant0.DISCR128_BEGIN_HI, variant0.DISCR128_BEGIN_LO, variant0.DISCR128_END_HI, variant0.DISCR128_END_LO)" Optional="true">variant0.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant1.DISCR128_BEGIN_HI, variant1.DISCR128_BEGIN_LO, variant1.DISCR128_END_HI, variant1.DISCR128_END_LO)" Optional="true">variant1.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant2.DISCR128_BEGIN_HI, variant2.DISCR128_BEGIN_LO, variant2.DISCR128_END_HI, variant2.DISCR128_END_LO)" Optional="true">variant2.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant3.DISCR128_BEGIN_HI, variant3.DISCR128_BEGIN_LO, variant3.DISCR128_END_HI, variant3.DISCR128_END_LO)" Optional="true">variant3.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant4.DISCR128_BEGIN_HI, variant4.DISCR128_BEGIN_LO, variant4.DISCR128_END_HI, variant4.DISCR128_END_LO)" Optional="true">variant4.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant5.DISCR128_BEGIN_HI, variant5.DISCR128_BEGIN_LO, variant5.DISCR128_END_HI, variant5.DISCR128_END_LO)" Optional="true">variant5.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant6.DISCR128_BEGIN_HI, variant6.DISCR128_BEGIN_LO, variant6.DISCR128_END_HI, variant6.DISCR128_END_LO)" Optional="true">variant6.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant7.DISCR128_BEGIN_HI, variant7.DISCR128_BEGIN_LO, variant7.DISCR128_END_HI, variant7.DISCR128_END_LO)" Optional="true">variant7.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant8.DISCR128_BEGIN_HI, variant8.DISCR128_BEGIN_LO, variant8.DISCR128_END_HI, variant8.DISCR128_END_LO)" Optional="true">variant8.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant9.DISCR128_BEGIN_HI, variant9.DISCR128_BEGIN_LO, variant9.DISCR128_END_HI, variant9.DISCR128_END_LO)" Optional="true">variant9.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant10.DISCR128_BEGIN_HI, variant10.DISCR128_BEGIN_LO, variant10.DISCR128_END_HI, variant10.DISCR128_END_LO)" Optional="true">variant10.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant11.DISCR128_BEGIN_HI, variant11.DISCR128_BEGIN_LO, variant11.DISCR128_END_HI, variant11.DISCR128_END_LO)" Optional="true">variant11.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant12.DISCR128_BEGIN_HI, variant12.DISCR128_BEGIN_LO, variant12.DISCR128_END_HI, variant12.DISCR128_END_LO)" Optional="true">variant12.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant13.DISCR128_BEGIN_HI, variant13.DISCR128_BEGIN_LO, variant13.DISCR128_END_HI, variant13.DISCR128_END_LO)" Optional="true">variant13.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant14.DISCR128_BEGIN_HI, variant14.DISCR128_BEGIN_LO, variant14.DISCR128_END_HI, variant14.DISCR128_END_LO)" Optional="true">variant14.value</ExpandedItem> + <ExpandedItem Condition="in_range128(tag128_hi, tag128_lo, variant15.DISCR128_BEGIN_HI, variant15.DISCR128_BEGIN_LO, variant15.DISCR128_END_HI, variant15.DISCR128_END_LO)" Optional="true">variant15.value</ExpandedItem> </Expand> </Type> </AutoVisualizer> diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index 912418fa7d1..bf6c02b9146 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -185,12 +185,4 @@ </ArrayItems> </Expand> </Type> - - <Type Name="alloc::borrow::Cow<*>"> - <DisplayString Condition="RUST$ENUM$DISR == 0x0">Borrowed({__0})</DisplayString> - <DisplayString Condition="RUST$ENUM$DISR == 0x1">Owned({__0})</DisplayString> - <Expand> - <Item Name="[value]" ExcludeView="simple">__0</Item> - </Expand> - </Type> </AutoVisualizer> diff --git a/src/test/codegen/async-fn-debug-awaitee-field.rs b/src/test/codegen/async-fn-debug-awaitee-field.rs index efb345fa9f3..909cd0062a6 100644 --- a/src/test/codegen/async-fn-debug-awaitee-field.rs +++ b/src/test/codegen/async-fn-debug-awaitee-field.rs @@ -12,11 +12,11 @@ async fn async_fn_test() { } // NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", -// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>", +// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>", // CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]], // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]], // NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>", -// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >", +// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >", fn main() { let _fn = async_fn_test(); diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index 8995605e3dd..73c652c9dd1 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -16,7 +16,7 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$<async_fn_debug_msvc::async_fn_test::async_fn_env$0>", +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_msvc::async_fn_test::async_fn_env$0>", // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, @@ -36,16 +36,17 @@ async fn async_fn_test() { // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 14, -// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] +// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: [[VARIANT_WRAPPER]], file: !2, baseType: [[VARIANT:![0-9]*]], // CHECK: [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "tag", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial fn main() { diff --git a/src/test/codegen/debug-vtable.rs b/src/test/codegen/debug-vtable.rs index b9cb4f93d07..bdd312878ec 100644 --- a/src/test/codegen/debug-vtable.rs +++ b/src/test/codegen/debug-vtable.rs @@ -46,7 +46,7 @@ // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}}) // NONMSVC: !DIGlobalVariable(name: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}" -// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$" +// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum2$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > > > > > >::vtable$" // NONMSVC: !DIGlobalVariable(name: "<debug_vtable::generic_closure::{closure_env#0}<bool> as core::ops::function::FnOnce<()>>::{vtable}" // MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<bool>, core::ops::function::FnOnce<tuple$<> > >::vtable$ diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 033da80be16..b712068bf27 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -20,7 +20,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> { // FIXME: No way to reliably check the filename. -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$<generator_debug_msvc::generator_test::generator_env$0>" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<generator_debug_msvc::generator_test::generator_env$0>" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, @@ -40,16 +40,18 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> { // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 17, -// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] +// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) +// CHECK: [[VARIANT_WRAPPER]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Variant4", scope: [[GEN]], +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "value", scope: [[VARIANT_WRAPPER]], {{.*}}, baseType: [[VARIANT:![0-9]*]], // CHECK: [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "tag", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial fn main() { diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index d6d7e5b44aa..11c4ae2f659 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -41,31 +41,26 @@ // cdb-command: g // cdb-command: dx b -// cdb-check: b : Unresumed [Type: enum$<generator_objects::main::generator_env$0>] -// cdb-check: [variant] : Unresumed +// cdb-check: b : Unresumed [Type: enum2$<generator_objects::main::generator_env$0>] // cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *] // cdb-command: g // cdb-command: dx b -// cdb-check: b : Suspend0 [Type: enum$<generator_objects::main::generator_env$0>] -// cdb-check: [variant] : Suspend0 +// cdb-check: b : Suspend0 [Type: enum2$<generator_objects::main::generator_env$0>] // cdb-check: [+0x[...]] c : 6 [Type: int] // cdb-check: [+0x[...]] d : 7 [Type: int] // cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *] // cdb-command: g // cdb-command: dx b -// cdb-check: b : Suspend1 [Type: enum$<generator_objects::main::generator_env$0>] -// cdb-check: [variant] : Suspend1 +// cdb-check: b : Suspend1 [Type: enum2$<generator_objects::main::generator_env$0>] // cdb-check: [+0x[...]] c : 7 [Type: int] // cdb-check: [+0x[...]] d : 8 [Type: int] // cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *] // cdb-command: g // cdb-command: dx b -// cdb-check: b : Returned [Type: enum$<generator_objects::main::generator_env$0>] -// cdb-check: [<Raw View>] [Type: enum$<generator_objects::main::generator_env$0>] -// cdb-check: [variant] : Returned +// cdb-check: b : Returned [Type: enum2$<generator_objects::main::generator_env$0>] // cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *] #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index a153a9a4228..45d5ddf5c0e 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -4,69 +4,141 @@ // cdb-command: g // cdb-command: dx a -// cdb-check:a : Some({...}) [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>] -// cdb-check: [variant] : Some +// cdb-check:a : Some [Type: enum2$<core::option::Option<msvc_pretty_enums::CStyleEnum> >] // cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] // cdb-command: dx b -// cdb-check:b : None [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>] -// cdb-check: [variant] : None +// cdb-check:b : None [Type: enum2$<core::option::Option<msvc_pretty_enums::CStyleEnum> >] // cdb-command: dx c -// cdb-check:c : Tag1 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [variant] : Tag1 +// cdb-check:c : Tag1 [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>] // cdb-command: dx d -// cdb-check:d : Data({...}) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [variant] : Data +// cdb-check:d : Data [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>] // cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-command: dx e -// cdb-check:e : Tag2 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [variant] : Tag2 +// cdb-check:e : Tag2 [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>] // cdb-command: dx f -// cdb-check:f : Some({...}) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [variant] : Some +// cdb-check:f : Some [Type: enum2$<core::option::Option<ref$<u32> > >] // cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] // cdb-command: dx g -// cdb-check:g : None [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [variant] : None +// cdb-check:g : None [Type: enum2$<core::option::Option<ref$<u32> > >] // cdb-command: dx h -// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >] -// cdb-check: [variant] : Some +// cdb-check:h : Some [Type: enum2$<core::option::Option<u32> >] // cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] // cdb-command: dx i -// cdb-check:i : None [Type: enum$<core::option::Option<u32> >] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >] -// cdb-check: [variant] : None +// cdb-check:i : None [Type: enum2$<core::option::Option<u32> >] // cdb-command: dx j // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] // cdb-command: dx k -// cdb-check:k : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] -// cdb-check: [variant] : Some +// cdb-check:k : Some [Type: enum2$<core::option::Option<alloc::string::String> >] // cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx l -// cdb-check:l : Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>] -// cdb-check: [<Raw View>] [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>] -// cdb-check: [variant] : Ok +// cdb-check:l : Ok [Type: enum2$<core::result::Result<u32,enum2$<msvc_pretty_enums::Empty> > >] // cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] +// cdb-command: dx niche128_some +// cdb-check: niche128_some : Some [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >] +// Note: we can't actually read the value of the field because CDB cannot handle 128 bit integers. +// cdb-check: [+0x000] __0 [...] [Type: core::num::nonzero::NonZeroI128] + +// cdb-command: dx niche128_none +// cdb-check: niche128_none : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >] + +// cdb-command: dx wrapping_niche128_dataful +// cdb-check: wrapping_niche128_dataful : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] +// cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] + +// cdb-command: dx wrapping_niche128_none1 +// cdb-check: wrapping_niche128_none1 : Y [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] +// cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] + +// cdb-command: dx wrapping_niche128_none2 +// cdb-check: wrapping_niche128_none2 : Z [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] +// cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] + +// cdb-command: dx direct_tag_128_a,d +// cdb-check: direct_tag_128_a,d : A [Type: enum2$<msvc_pretty_enums::DirectTag128>] +// cdb-check: [+0x[...]] __0 : 42 [Type: unsigned int] + +// cdb-command: dx direct_tag_128_b,d +// cdb-check: direct_tag_128_b,d : B [Type: enum2$<msvc_pretty_enums::DirectTag128>] +// cdb-check: [+0x[...]] __0 : 137 [Type: unsigned int] + +// cdb-command: dx niche_w_fields_1_some,d +// cdb-check: niche_w_fields_1_some,d : A [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields1>] +// cdb-check: [+0x[...]] __0 : 0x[...] : 77 [Type: unsigned char *] +// cdb-check: [+0x[...]] __1 : 7 [Type: unsigned int] + +// cdb-command: dx niche_w_fields_1_none,d +// cdb-check: niche_w_fields_1_none,d : B [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields1>] +// cdb-check: [+0x[...]] __0 : 99 [Type: unsigned int] + +// cdb-command: dx niche_w_fields_2_some,d +// cdb-check: niche_w_fields_2_some,d : A [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields2>] +// cdb-check: [+0x[...]] __0 : 800 [Type: core::num::nonzero::NonZeroU32] +// cdb-check: [+0x[...]] __1 : 900 [Type: unsigned __int64] + +// cdb-command: dx niche_w_fields_2_none,d +// cdb-check: niche_w_fields_2_none,d : B [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields2>] +// cdb-check: [+0x[...]] __0 : 1000 [Type: unsigned __int64] + +// cdb-command: dx niche_w_fields_3_some,d +// cdb-check: niche_w_fields_3_some,d : A [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] +// cdb-check: [+0x[...]] __0 : 137 [Type: unsigned char] +// cdb-check: [+0x[...]] __1 : true [Type: bool] + +// cdb-command: dx niche_w_fields_3_niche1,d +// cdb-check: niche_w_fields_3_niche1,d : B [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] +// cdb-check: [+0x[...]] __0 : 12 [Type: unsigned char] + +// cdb-command: dx niche_w_fields_3_niche2,d +// cdb-check: niche_w_fields_3_niche2,d : C [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] +// cdb-check: [+0x[...]] __0 : false [Type: bool] + +// cdb-command: dx niche_w_fields_3_niche3,d +// cdb-check: niche_w_fields_3_niche3,d : D [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] +// cdb-check: [+0x[...]] __0 : 34 [Type: unsigned char] + +// cdb-command: dx niche_w_fields_3_niche4,d +// cdb-check: niche_w_fields_3_niche4,d : E [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] +// cdb-check: [+0x[...]] __0 : 56 [Type: unsigned char] + +// cdb-command: dx niche_w_fields_3_niche5,d +// cdb-check: niche_w_fields_3_niche5,d : F [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>] + +// cdb-command: dx -r3 niche_w_fields_std_result_ok,d +// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >] +// cdb-check: [+0x[...]] __0 [Type: alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>] +// cdb-check: [+0x[...]] data_ptr : [...] +// cdb-check: [+0x[...]] length : 3 [...] + +// cdb-command: dx -r3 niche_w_fields_std_result_err,d +// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >] +// cdb-check: [+0x[...]] __0 : 789 [Type: unsigned __int64] + +// cdb-command: dx -r2 arbitrary_discr1,d +// cdb-check: arbitrary_discr1,d : Abc [Type: enum2$<msvc_pretty_enums::ArbitraryDiscr>] +// cdb-check: [+0x[...]] __0 : 1234 [Type: unsigned int] + +// cdb-command: dx -r2 arbitrary_discr2,d +// cdb-check: arbitrary_discr2,d : Def [Type: enum2$<msvc_pretty_enums::ArbitraryDiscr>] +// cdb-check: [+0x[...]] __0 : 5678 [Type: unsigned int] + +#![feature(rustc_attrs)] +#![feature(repr128)] +#![feature(arbitrary_enum_discriminant)] + +use std::num::{NonZeroI128, NonZeroU32}; + pub enum CStyleEnum { Low = 2, High = 16, @@ -80,6 +152,51 @@ pub enum NicheLayoutEnum { pub enum Empty {} +// The following three types will use a niche layout once +// https://github.com/rust-lang/rust/pull/94075 is merged: +enum NicheLayoutWithFields1<'a> { + A(&'a u8, u32), + B(u32), +} + +enum NicheLayoutWithFields2 { + A(NonZeroU32, u64), + B(u64), +} + +enum NicheLayoutWithFields3 { + A(u8, bool), + B(u8), + C(bool), + D(u8), + E(u8), + F, +} + +#[rustc_layout_scalar_valid_range_start(340282366920938463463374607431768211454)] +#[rustc_layout_scalar_valid_range_end(1)] +#[repr(transparent)] +struct Wrapping128(u128); + +// #[rustc_layout(debug)] +enum Wrapping128Niche { + X(Wrapping128), + Y, + Z, +} + +#[repr(i128)] +enum DirectTag128 { + A(u32), + B(u32), +} + +#[repr(u32)] +enum ArbitraryDiscr { + Abc(u32) = 1000, + Def(u32) = 5000_000, +} + fn main() { let a = Some(CStyleEnum::Low); let b = Option::<CStyleEnum>::None; @@ -93,6 +210,35 @@ fn main() { let j = CStyleEnum::High; let k = Some("IAMA optional string!".to_string()); let l = Result::<u32, Empty>::Ok(42); + let niche128_some = Some(NonZeroI128::new(123456).unwrap()); + let niche128_none: Option<NonZeroI128> = None; + + let wrapping_niche128_dataful = + unsafe { Wrapping128Niche::X(Wrapping128(340282366920938463463374607431768211454)) }; + let wrapping_niche128_none1 = Wrapping128Niche::Y; + let wrapping_niche128_none2 = Wrapping128Niche::Z; + + let direct_tag_128_a = DirectTag128::A(42); + let direct_tag_128_b = DirectTag128::B(137); + + let niche_w_fields_1_some = NicheLayoutWithFields1::A(&77, 7); + let niche_w_fields_1_none = NicheLayoutWithFields1::B(99); + + let niche_w_fields_2_some = NicheLayoutWithFields2::A(NonZeroU32::new(800).unwrap(), 900); + let niche_w_fields_2_none = NicheLayoutWithFields2::B(1000); + + let niche_w_fields_3_some = NicheLayoutWithFields3::A(137, true); + let niche_w_fields_3_niche1 = NicheLayoutWithFields3::B(12); + let niche_w_fields_3_niche2 = NicheLayoutWithFields3::C(false); + let niche_w_fields_3_niche3 = NicheLayoutWithFields3::D(34); + let niche_w_fields_3_niche4 = NicheLayoutWithFields3::E(56); + let niche_w_fields_3_niche5 = NicheLayoutWithFields3::F; + + let niche_w_fields_std_result_ok: Result<Box<[u8]>, u64> = Ok(vec![1, 2, 3].into()); + let niche_w_fields_std_result_err: Result<Box<[u8]>, u64> = Err(789); + + let arbitrary_discr1 = ArbitraryDiscr::Abc(1234); + let arbitrary_discr2 = ArbitraryDiscr::Def(5678); zzz(); // #break } diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs index 3846fb42f81..9630952cbaa 100644 --- a/src/test/debuginfo/msvc-scalarpair-params.rs +++ b/src/test/debuginfo/msvc-scalarpair-params.rs @@ -18,12 +18,10 @@ // cdb-command: g // cdb-command: dx o1 -// cdb-check:o1 : Some [Type: enum$<core::option::Option<u32> >] -// cdb-check: [variant] : Some +// cdb-check:o1 : Some [Type: enum2$<core::option::Option<u32> >] // cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]] // cdb-command: dx o2 -// cdb-check:o2 : Some [Type: enum$<core::option::Option<u64> >] -// cdb-check: [variant] : Some +// cdb-check:o2 : Some [Type: enum2$<core::option::Option<u64> >] // cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64] // cdb-command: g @@ -89,7 +87,7 @@ fn slice(s: &[u8]) { zzz(); // #break } -fn zzz() { } +fn zzz() {} fn main() { range(10..12, 20..30); diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 00dccf5f906..314ba40b0e3 100644 --- a/src/test/debuginfo/mutex.rs +++ b/src/test/debuginfo/mutex.rs @@ -20,19 +20,20 @@ // cdb-check: [<Raw View>] [Type: core::cell::UnsafeCell<i32>] // -// cdb-command:dx lock,d -// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>,enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >] -// cdb-check: [variant] : Ok +// cdb-command:dx _lock,d +// cdb-check:_lock,d : Ok [Type: enum2$<core::result::Result<std::sync::mutex::MutexGuard<i32>,enum2$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> > > > >] // cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>] use std::sync::Mutex; -#[allow(unused_variables)] -fn main() -{ +fn main() { let m = Mutex::new(0); - let lock = m.try_lock(); + let _lock = m.try_lock(); + + println!("this line avoids an `Ambiguous symbol error` while setting the breakpoint"); + zzz(); // #break } +#[inline(never)] fn zzz() {} diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 55a4ecc1c1a..a51b37205e8 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -39,7 +39,6 @@ // gdb-command: print some_string // gdb-check:$8 = Some = {"IAMA "...} - // === LLDB TESTS ================================================================================== // lldb-command: run @@ -65,7 +64,6 @@ // lldb-command: print os_string // lldb-check:[...]$6 = "IAMA OS string 😃"[...] - // === CDB TESTS ================================================================================== // cdb-command: g @@ -118,20 +116,17 @@ // cdb-check: [chars] : "IAMA OS string [...]" // cdb-command: dx some -// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i16> >] -// cdb-check: [variant] : Some +// cdb-check:some : Some [Type: enum2$<core::option::Option<i16> >] +// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<i16> >] // cdb-check: [+0x002] __0 : 8 [Type: short] // cdb-command: dx none -// cdb-check:none : None [Type: enum$<core::option::Option<i64> >] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i64> >] -// cdb-check: [variant] : None +// cdb-check:none : None [Type: enum2$<core::option::Option<i64> >] +// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<i64> >] // cdb-command: dx some_string -// cdb-check:some_string : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] -// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] -// cdb-check: [variant] : Some +// cdb-check:some_string : Some [Type: enum2$<core::option::Option<alloc::string::String> >] +// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<alloc::string::String> >] // cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx linkedlist @@ -153,7 +148,6 @@ use std::collections::{LinkedList, VecDeque}; use std::ffi::OsString; fn main() { - // &[] let slice: &[i32] = &[0, 1, 2, 3]; @@ -188,4 +182,6 @@ fn main() { zzz(); // #break } -fn zzz() { () } +fn zzz() { + () +} diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs index c0d905a6acc..cdac47a784d 100644 --- a/src/test/debuginfo/result-types.rs +++ b/src/test/debuginfo/result-types.rs @@ -7,15 +7,14 @@ // cdb-command: g // cdb-command: dx x,d -// cdb-check:x,d : Ok [Type: enum$<core::result::Result<i32,str> >] +// cdb-check:x,d : Ok [Type: enum2$<core::result::Result<i32,str> >] // cdb-check: [...] __0 : -3 [Type: int] // cdb-command: dx y -// cdb-check:y : Err [Type: enum$<core::result::Result<i32,str> >] +// cdb-check:y : Err [Type: enum2$<core::result::Result<i32,str> >] // cdb-check: [...] __0 : "Some error message" [Type: str] -fn main() -{ +fn main() { let x: Result<i32, &str> = Ok(-3); assert_eq!(x.is_ok(), true); @@ -25,4 +24,6 @@ fn main() zzz(); // #break. } -fn zzz() { () } +fn zzz() { + () +} diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index b040a6e7494..9cc99d7767c 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -175,51 +175,51 @@ // 0-sized structs appear to be optimized away in some cases, so only check the structs that do // actually appear. // cdb-command:dv /t *_struct -// cdb-check:struct type_names::GenericStruct<enum$<type_names::mod1::Enum2>,f64> mut_generic_struct = [...] +// cdb-check:struct type_names::GenericStruct<enum2$<type_names::mod1::Enum2>,f64> mut_generic_struct = [...] // ENUMS // cdb-command:dv /t *_enum_* -// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...] -// cdb-check:union enum$<type_names::Enum1> simple_enum_2 = [...] -// cdb-check:union enum$<type_names::mod1::Enum2> simple_enum_3 = [...] -// cdb-check:union enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > generic_enum_1 = [...] -// cdb-check:union enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > generic_enum_2 = [...] +// cdb-check:union enum2$<type_names::Enum1> simple_enum_1 = [...] +// cdb-check:union enum2$<type_names::Enum1> simple_enum_2 = [...] +// cdb-check:union enum2$<type_names::mod1::Enum2> simple_enum_3 = [...] +// cdb-check:union enum2$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > generic_enum_1 = [...] +// cdb-check:union enum2$<type_names::mod1::mod2::Enum3<type_names::Struct1> > generic_enum_2 = [...] // TUPLES // cdb-command:dv /t tuple* -// cdb-check:struct tuple$<u32,type_names::Struct1,enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...] -// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...] +// cdb-check:struct tuple$<u32,type_names::Struct1,enum2$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...] +// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum2$<type_names::mod1::Enum2>,char> tuple2 = [...] // BOX // cdb-command:dv /t box* // cdb-check:struct tuple$<alloc::boxed::Box<f32,alloc::alloc::Global>,i32> box1 = [...] -// cdb-check:struct tuple$<alloc::boxed::Box<enum$<type_names::mod1::mod2::Enum3<f32> >,alloc::alloc::Global>,i32> box2 = [...] +// cdb-check:struct tuple$<alloc::boxed::Box<enum2$<type_names::mod1::mod2::Enum3<f32> >,alloc::alloc::Global>,i32> box2 = [...] // REFERENCES // cdb-command:dv /t *ref* // cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...] // cdb-check:struct tuple$<ref$<type_names::GenericStruct<char,type_names::Struct1> >,i32> ref2 = [...] // cdb-check:struct tuple$<ref_mut$<type_names::Struct1>,i32> mut_ref1 = [...] -// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum$<type_names::mod1::Enum2>,f64> >,i32> mut_ref2 = [...] +// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum2$<type_names::mod1::Enum2>,f64> >,i32> mut_ref2 = [...] // RAW POINTERS // cdb-command:dv /t *_ptr* // cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...] // cdb-check:struct tuple$<ptr_mut$<isize>,isize> mut_ptr2 = [...] -// cdb-check:struct tuple$<ptr_mut$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...] +// cdb-check:struct tuple$<ptr_mut$<enum2$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...] // cdb-check:struct tuple$<ptr_const$<type_names::Struct1>,isize> const_ptr1 = [...] // cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...] -// cdb-check:struct tuple$<ptr_const$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...] +// cdb-check:struct tuple$<ptr_const$<enum2$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...] // VECTORS // cdb-command:dv /t *vec* // cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...] // cdb-check:struct tuple$<array$<usize,3>,i16> fixed_size_vec2 = [...] // cdb-check:struct alloc::vec::Vec<usize,alloc::alloc::Global> vec1 = [...] -// cdb-check:struct alloc::vec::Vec<enum$<type_names::mod1::Enum2>,alloc::alloc::Global> vec2 = [...] +// cdb-check:struct alloc::vec::Vec<enum2$<type_names::mod1::Enum2>,alloc::alloc::Global> vec2 = [...] // cdb-command:dv /t slice* // cdb-check:struct slice$<usize> slice1 = [...] -// cdb-check:struct slice$<enum$<type_names::mod1::Enum2> > slice2 = [...] +// cdb-check:struct slice$<enum2$<type_names::mod1::Enum2> > slice2 = [...] // TRAITS // cdb-command:dv /t *_trait @@ -238,16 +238,16 @@ // cdb-check:struct tuple$<type_names::mod1::Struct2 (*)(type_names::GenericStruct<u16,u8>),usize> unsafe_fn_with_return_value = [...] // cdb-check:struct tuple$<type_names::Struct1 (*)(),usize> extern_c_fn_with_return_value = [...] // cdb-check:struct tuple$<usize (*)(f64),usize> rust_fn_with_return_value = [...] -// cdb-check:struct tuple$<void (*)(enum$<core::result::Result<char,f64> >),usize> unsafe_fn = [...] +// cdb-check:struct tuple$<void (*)(enum2$<core::result::Result<char,f64> >),usize> unsafe_fn = [...] // cdb-check:struct tuple$<void (*)(isize),usize> extern_c_fn = [...] -// cdb-check:struct tuple$<void (*)(enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>),usize> rust_fn = [...] +// cdb-check:struct tuple$<void (*)(enum2$<core::option::Option<isize> >,enum2$<core::option::Option<ref$<type_names::mod1::Struct2> > >),usize> rust_fn = [...] // cdb-command:dv /t *_function* // cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_function = [...] // cdb-check:struct tuple$<type_names::mod1::mod2::Struct3 (*)(type_names::mod1::mod2::Struct3),usize> generic_function_struct3 = [...] // cdb-check:struct tuple$<isize (*)(isize),usize> generic_function_int = [...] // cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn") // cdb-check:Return Type: void -// cdb-check:Parameter Types: enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some> +// cdb-check:Parameter Types: enum2$<core::option::Option<isize> >,enum2$<core::option::Option<ref$<type_names::mod1::Struct2> > > // cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value") // cdb-check:Return Type: usize // cdb-check:Parameter Types: f64 diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index ac6d80bb439..0e2cc52a645 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -545,6 +545,8 @@ fn common_inputs_stamp(config: &Config) -> Stamp { stamp.add_path(&path); } + stamp.add_dir(&rust_src_dir.join("src/etc/natvis")); + stamp.add_dir(&config.run_lib_path); if let Some(ref rustdoc_path) = config.rustdoc_path { |
