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`
This commit is contained in:
commit
4916e2b9e6
23 changed files with 1137 additions and 443 deletions
|
@ -114,6 +114,7 @@ macro_rules! return_if_di_node_created_in_meantime {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract size and alignment from a TyAndLayout.
|
/// Extract size and alignment from a TyAndLayout.
|
||||||
|
#[inline]
|
||||||
fn size_and_align_of<'tcx>(ty_and_layout: TyAndLayout<'tcx>) -> (Size, Align) {
|
fn size_and_align_of<'tcx>(ty_and_layout: TyAndLayout<'tcx>) -> (Size, Align) {
|
||||||
(ty_and_layout.size, ty_and_layout.align.abi)
|
(ty_and_layout.size, ty_and_layout.align.abi)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use rustc_codegen_ssa::debuginfo::{
|
use rustc_codegen_ssa::{
|
||||||
type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo,
|
debuginfo::{type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo},
|
||||||
|
traits::ConstMethods,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::{
|
use rustc_middle::{
|
||||||
bug,
|
bug,
|
||||||
ty::{
|
ty::{
|
||||||
self,
|
self,
|
||||||
layout::{LayoutOf, TyAndLayout},
|
layout::{LayoutOf, TyAndLayout},
|
||||||
util::Discr,
|
AdtDef, GeneratorSubsts, Ty,
|
||||||
AdtDef, GeneratorSubsts,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants};
|
use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -21,9 +23,9 @@ use crate::{
|
||||||
debuginfo::{
|
debuginfo::{
|
||||||
metadata::{
|
metadata::{
|
||||||
build_field_di_node, closure_saved_names_of_captured_variables,
|
build_field_di_node, closure_saved_names_of_captured_variables,
|
||||||
enums::tag_base_type,
|
enums::{tag_base_type, DiscrResult},
|
||||||
file_metadata, generator_layout_and_saved_local_names, size_and_align_of,
|
file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
|
||||||
type_map::{self, UniqueTypeId},
|
type_map::{self, Stub, UniqueTypeId},
|
||||||
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
|
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
},
|
},
|
||||||
|
@ -35,59 +37,161 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// In CPP-like mode, we generate a union of structs for each variant and an
|
// The names of the associated constants in each variant wrapper struct.
|
||||||
/// explicit discriminant field roughly equivalent to the following C/C++ code:
|
// 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
|
/// ```c
|
||||||
/// union enum$<{fully-qualified-name}> {
|
/// union enum2$<{fully-qualified-name}> {
|
||||||
/// struct {variant 0 name} {
|
/// struct Variant0 {
|
||||||
/// <variant 0 fields>
|
/// 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;
|
/// } variant0;
|
||||||
|
///
|
||||||
/// <other variant structs>
|
/// <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
|
/// As you can see, the type name is wrapped in `enum2$<_>`. This way we can
|
||||||
/// single NatVis rule for handling all enums.
|
/// 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
|
/// Single-variant enums don't actually have a tag field. In this case we
|
||||||
/// DW_TAG_union_type (top-level type for enum)
|
/// emit a static tag field (that always has the value 0) so we can use the
|
||||||
/// DW_TAG_member (member for variant 1)
|
/// same representation (and NatVis).
|
||||||
/// 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)
|
|
||||||
/// ```
|
|
||||||
///
|
///
|
||||||
/// The above encoding applies for enums with a direct tag. For niche-tag we have to do things
|
/// For niche-layout enums it's possible to have a 128-bit tag. NatVis, VS, and
|
||||||
/// differently in order to allow a NatVis visualizer to extract all the information needed:
|
/// WinDbg (the main targets for CPP-like debuginfo at the moment) don't support
|
||||||
/// We generate a union of two fields, one for the dataful variant
|
/// 128-bit integers, so all values involved get split into two 64-bit fields.
|
||||||
/// and one that just points to the discriminant (which is some field within the dataful variant).
|
/// Instead of the `tag` field, we generate two fields `tag128_lo` and `tag128_hi`,
|
||||||
/// We also create a DW_TAG_enumeration_type DIE that contains tag values for the non-dataful
|
/// Instead of `DISCR_EXACT`, we generate `DISCR128_EXACT_LO` and `DISCR128_EXACT_HI`,
|
||||||
/// variants and make the discriminant field that type. We then use NatVis to render the enum type
|
/// and so on.
|
||||||
/// correctly in Windbg/VS. This will generate debuginfo roughly equivalent to the following C:
|
|
||||||
///
|
///
|
||||||
/// ```c
|
///
|
||||||
/// union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> {
|
/// The following pseudocode shows how to decode an enum value in a debugger:
|
||||||
/// struct <dataful variant name> {
|
///
|
||||||
/// <fields in dataful variant>
|
/// ```text
|
||||||
/// } dataful_variant;
|
///
|
||||||
/// enum Discriminant$ {
|
/// fn find_active_variant(enum_value) -> (VariantName, VariantValue) {
|
||||||
/// <non-dataful variants>
|
/// let is_128_bit = enum_value.has_field("tag128_lo");
|
||||||
/// } discriminant;
|
///
|
||||||
|
/// 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$<*, *, *, *>`
|
/// // Check if a value is within the given range
|
||||||
/// and evaluates `this.discriminant`. If the value is between the min niche and max
|
/// // (where the range might wrap around the value space)
|
||||||
/// niche, then the enum is in the dataful variant and `this.dataful_variant` is
|
/// fn is_in_range(value, start, end) -> bool {
|
||||||
/// rendered. Otherwise, the enum is in one of the non-dataful variants. In that
|
/// if start < end {
|
||||||
/// case, we just need to render the name of the `this.discriminant` enum.
|
/// value >= start && value <= end
|
||||||
|
/// } else {
|
||||||
|
/// value >= start || value <= end
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
|
pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
unique_type_id: UniqueTypeId<'tcx>,
|
unique_type_id: UniqueTypeId<'tcx>,
|
||||||
|
@ -135,27 +239,28 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
|
||||||
ref variants,
|
ref variants,
|
||||||
tag_field,
|
tag_field,
|
||||||
..
|
..
|
||||||
} => build_union_fields_for_direct_tag_enum(
|
} => build_union_fields_for_enum(
|
||||||
cx,
|
cx,
|
||||||
enum_adt_def,
|
enum_adt_def,
|
||||||
enum_type_and_layout,
|
enum_type_and_layout,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
&mut variants.indices(),
|
variants.indices(),
|
||||||
tag_field,
|
tag_field,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
Variants::Multiple {
|
Variants::Multiple {
|
||||||
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
|
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
|
||||||
ref variants,
|
ref variants,
|
||||||
tag_field,
|
tag_field,
|
||||||
..
|
..
|
||||||
} => build_union_fields_for_niche_tag_enum(
|
} => build_union_fields_for_enum(
|
||||||
cx,
|
cx,
|
||||||
enum_adt_def,
|
enum_adt_def,
|
||||||
enum_type_and_layout,
|
enum_type_and_layout,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
dataful_variant,
|
variants.indices(),
|
||||||
&mut variants.indices(),
|
|
||||||
tag_field,
|
tag_field,
|
||||||
|
Some(dataful_variant),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -217,139 +322,346 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
|
||||||
let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
|
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(
|
let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
|
||||||
cx,
|
cx,
|
||||||
enum_type_and_layout.ty,
|
enum_type_and_layout,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
variant_index,
|
variant_index,
|
||||||
enum_adt_def.variant(variant_index),
|
enum_adt_def.variant(variant_index),
|
||||||
variant_layout,
|
variant_layout,
|
||||||
);
|
);
|
||||||
|
|
||||||
// NOTE: The field name of the union is the same as the variant name, not "variant0".
|
let tag_base_type = cx.tcx.types.u32;
|
||||||
let variant_name = enum_adt_def.variant(variant_index).name.as_str();
|
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,
|
cx,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
variant_name,
|
std::iter::once((
|
||||||
// NOTE: We use the size and align of the entire type, not from variant_layout
|
variant_index,
|
||||||
// since the later is sometimes smaller (if it has fewer fields).
|
Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
|
||||||
size_and_align_of(enum_type_and_layout),
|
)),
|
||||||
Size::ZERO,
|
|
||||||
DIFlags::FlagZero,
|
|
||||||
variant_struct_type_di_node,
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_union_fields_for_direct_tag_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>,
|
|
||||||
tag_field: usize,
|
|
||||||
) -> SmallVec<&'ll DIType> {
|
|
||||||
let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
|
|
||||||
.map(|variant_index| {
|
|
||||||
let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
|
|
||||||
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
source_info: None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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(
|
let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node(
|
||||||
cx,
|
cx,
|
||||||
enum_type_and_layout,
|
enum_type_and_layout,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
&variant_field_infos,
|
variant_index,
|
||||||
discr_type_di_node,
|
None,
|
||||||
tag_field,
|
variant_struct_type_di_node,
|
||||||
)
|
variant_names_type_di_node,
|
||||||
}
|
tag_base_type_di_node,
|
||||||
|
|
||||||
fn build_union_fields_for_niche_tag_enum<'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(
|
|
||||||
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),
|
|
||||||
);
|
|
||||||
|
|
||||||
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(
|
|
||||||
cx,
|
|
||||||
"Discriminant$",
|
|
||||||
tag_base_type,
|
tag_base_type,
|
||||||
&mut variant_indices.filter_map(|variant_index| {
|
DiscrResult::NoDiscriminant,
|
||||||
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![
|
smallvec![
|
||||||
build_field_di_node(
|
build_field_di_node(
|
||||||
cx,
|
cx,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
"dataful_variant",
|
&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_and_align_of(enum_type_and_layout),
|
||||||
Size::ZERO,
|
Size::ZERO,
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
dataful_variant_struct_type_di_node,
|
variant_struct_type_wrapper_di_node,
|
||||||
),
|
|
||||||
build_field_di_node(
|
|
||||||
cx,
|
|
||||||
enum_type_di_node,
|
|
||||||
"discriminant",
|
|
||||||
cx.size_and_align_of(tag_base_type),
|
|
||||||
enum_type_and_layout.fields.offset(tag_field),
|
|
||||||
DIFlags::FlagZero,
|
|
||||||
discr_type_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_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: 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,
|
||||||
|
source_info: None,
|
||||||
|
discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
build_union_fields_for_direct_tag_enum_or_generator(
|
||||||
|
cx,
|
||||||
|
enum_type_and_layout,
|
||||||
|
enum_type_di_node,
|
||||||
|
&variant_field_infos,
|
||||||
|
variant_names_type_di_node,
|
||||||
|
tag_base_type,
|
||||||
|
tag_field,
|
||||||
|
dataful_variant_index,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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>,
|
||||||
|
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,
|
||||||
|
"VariantNames",
|
||||||
|
variant_names_enum_base_type(cx),
|
||||||
|
variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32() as u64)),
|
||||||
|
containing_scope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
type_map::stub(
|
||||||
|
cx,
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
|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>(
|
fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
generator_type_and_layout: TyAndLayout<'tcx>,
|
generator_type_and_layout: TyAndLayout<'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 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_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.
|
// Build the type node for each field.
|
||||||
let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
|
let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
|
||||||
|
@ -391,29 +726,24 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
|
||||||
None
|
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();
|
.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(
|
build_union_fields_for_direct_tag_enum_or_generator(
|
||||||
cx,
|
cx,
|
||||||
generator_type_and_layout,
|
generator_type_and_layout,
|
||||||
generator_type_di_node,
|
generator_type_di_node,
|
||||||
&variant_field_infos[..],
|
&variant_field_infos[..],
|
||||||
discr_type_di_node,
|
variant_names_type_di_node,
|
||||||
|
tag_base_type,
|
||||||
tag_field,
|
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,
|
enum_type_di_node: &'ll DIType,
|
||||||
variant_field_infos: &[VariantFieldInfo<'ll>],
|
variant_field_infos: &[VariantFieldInfo<'ll>],
|
||||||
discr_type_di_node: &'ll DIType,
|
discr_type_di_node: &'ll DIType,
|
||||||
|
tag_base_type: Ty<'tcx>,
|
||||||
tag_field: usize,
|
tag_field: usize,
|
||||||
|
dataful_variant_index: Option<VariantIdx>,
|
||||||
) -> SmallVec<&'ll DIType> {
|
) -> 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);
|
let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
|
||||||
|
|
||||||
// We create a field in the union for each variant ...
|
// 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 field_name = variant_union_field_name(variant_member_info.variant_index);
|
||||||
let (size, align) = size_and_align_of(enum_type_and_layout);
|
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
|
// We use LLVMRustDIBuilderCreateMemberType() member type directly because
|
||||||
// the build_field_di_node() function does not support specifying a source location,
|
// the build_field_di_node() function does not support specifying a source location,
|
||||||
// which is something that we don't do anywhere else.
|
// 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
|
// Union fields are always at offset zero
|
||||||
Size::ZERO.bits(),
|
Size::ZERO.bits(),
|
||||||
DIFlags::FlagZero,
|
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))
|
cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout))
|
||||||
);
|
);
|
||||||
|
|
||||||
// ... and a field for the discriminant.
|
// ... and a field for the tag. If the tag is 128 bits wide, this will actually
|
||||||
unions_fields.push(build_field_di_node(
|
// be two 64-bit fields.
|
||||||
cx,
|
let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
|
||||||
enum_type_di_node,
|
|
||||||
"discriminant",
|
if is_128_bits {
|
||||||
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
|
let type_di_node = type_di_node(cx, cx.tcx.types.u64);
|
||||||
enum_type_and_layout.fields.offset(tag_field),
|
let size_and_align = cx.size_and_align_of(cx.tcx.types.u64);
|
||||||
DIFlags::FlagZero,
|
|
||||||
discr_type_di_node,
|
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
|
unions_fields
|
||||||
}
|
}
|
||||||
|
@ -485,6 +868,7 @@ struct VariantFieldInfo<'ll> {
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
variant_struct_type_di_node: &'ll DIType,
|
variant_struct_type_di_node: &'ll DIType,
|
||||||
source_info: Option<(&'ll DIFile, c_uint)>,
|
source_info: Option<(&'ll DIFile, c_uint)>,
|
||||||
|
discr: DiscrResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
|
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))
|
.map(|&s| Cow::from(s))
|
||||||
.unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into())
|
.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())
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use rustc_middle::{
|
||||||
ty::{
|
ty::{
|
||||||
self,
|
self,
|
||||||
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
|
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
|
||||||
util::Discr,
|
|
||||||
AdtDef, GeneratorSubsts, Ty, VariantDef,
|
AdtDef, GeneratorSubsts, Ty, VariantDef,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -90,8 +89,11 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
|
||||||
cx,
|
cx,
|
||||||
&compute_debuginfo_type_name(cx.tcx, enum_type_and_layout.ty, false),
|
&compute_debuginfo_type_name(cx.tcx, enum_type_and_layout.ty, false),
|
||||||
tag_base_type(cx, enum_type_and_layout),
|
tag_base_type(cx, enum_type_and_layout),
|
||||||
&mut enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| {
|
enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| {
|
||||||
(discr, Cow::from(enum_adt_def.variant(variant_index).name.as_str()))
|
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,
|
containing_scope,
|
||||||
),
|
),
|
||||||
|
@ -152,7 +154,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
base_type: Ty<'tcx>,
|
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,
|
containing_scope: &'ll DIType,
|
||||||
) -> &'ll DIType {
|
) -> &'ll DIType {
|
||||||
let is_unsigned = match base_type.kind() {
|
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."),
|
_ => bug!("build_enumeration_type_di_node() called with non-integer tag type."),
|
||||||
};
|
};
|
||||||
|
|
||||||
let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = variants
|
let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = enumerators
|
||||||
.map(|(discr, variant_name)| {
|
.map(|(name, value)| unsafe {
|
||||||
unsafe {
|
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
DIB(cx),
|
||||||
DIB(cx),
|
name.as_ptr().cast(),
|
||||||
variant_name.as_ptr().cast(),
|
name.len(),
|
||||||
variant_name.len(),
|
value as i64,
|
||||||
// FIXME: what if enumeration has i128 discriminant?
|
is_unsigned,
|
||||||
discr.val as i64,
|
))
|
||||||
is_unsigned,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.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).
|
/// and a DW_TAG_member for each field (but not the discriminant).
|
||||||
fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|
fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
enum_type: Ty<'tcx>,
|
enum_type_and_layout: TyAndLayout<'tcx>,
|
||||||
enum_type_di_node: &'ll DIType,
|
enum_type_di_node: &'ll DIType,
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
variant_def: &VariantDef,
|
variant_def: &VariantDef,
|
||||||
variant_layout: TyAndLayout<'tcx>,
|
variant_layout: TyAndLayout<'tcx>,
|
||||||
) -> &'ll DIType {
|
) -> &'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(
|
type_map::build_type_with_children(
|
||||||
cx,
|
cx,
|
||||||
type_map::stub(
|
type_map::stub(
|
||||||
cx,
|
cx,
|
||||||
Stub::Struct,
|
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(),
|
variant_def.name.as_str(),
|
||||||
// NOTE: We use size and align of enum_type, not from variant_layout:
|
// 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),
|
Some(enum_type_di_node),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
),
|
),
|
||||||
|
@ -290,9 +293,9 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|
||||||
type_di_node(cx, field_layout.ty),
|
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
|
.di_node
|
||||||
}
|
}
|
||||||
|
@ -398,6 +401,19 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
|
||||||
.di_node
|
.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.
|
/// Returns the discriminant value corresponding to the variant index.
|
||||||
///
|
///
|
||||||
/// Will return `None` if there is less than two variants (because then the enum won't have)
|
/// Will return `None` if there is less than two variants (because then the enum won't have)
|
||||||
|
@ -407,12 +423,11 @@ fn compute_discriminant_value<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
enum_type_and_layout: TyAndLayout<'tcx>,
|
enum_type_and_layout: TyAndLayout<'tcx>,
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
) -> Option<u64> {
|
) -> DiscrResult {
|
||||||
match enum_type_and_layout.layout.variants() {
|
match enum_type_and_layout.layout.variants() {
|
||||||
&Variants::Single { .. } => None,
|
&Variants::Single { .. } => DiscrResult::NoDiscriminant,
|
||||||
&Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => Some(
|
&Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value(
|
||||||
enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val
|
enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val,
|
||||||
as u64,
|
|
||||||
),
|
),
|
||||||
&Variants::Multiple {
|
&Variants::Multiple {
|
||||||
tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
|
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 {
|
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 {
|
} else {
|
||||||
let value = (variant_index.as_u32() as u128)
|
let value = (variant_index.as_u32() as u128)
|
||||||
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
||||||
.wrapping_add(niche_start);
|
.wrapping_add(niche_start);
|
||||||
let value = tag.size(cx).truncate(value);
|
let value = tag.size(cx).truncate(value);
|
||||||
// NOTE(eddyb) do *NOT* remove this assert, until
|
DiscrResult::Value(value)
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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(
|
variant_struct_type_di_node: super::build_enum_variant_struct_type_di_node(
|
||||||
cx,
|
cx,
|
||||||
enum_type,
|
enum_type_and_layout,
|
||||||
enum_type_di_node,
|
enum_type_di_node,
|
||||||
variant_index,
|
variant_index,
|
||||||
enum_adt_def.variant(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.size.bits(),
|
||||||
enum_type_and_layout.align.abi.bits() as u32,
|
enum_type_and_layout.align.abi.bits() as u32,
|
||||||
Size::ZERO.bits(),
|
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,
|
DIFlags::FlagZero,
|
||||||
variant_member_info.variant_struct_type_di_node,
|
variant_member_info.variant_struct_type_di_node,
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,6 +47,8 @@ pub(super) enum UniqueTypeId<'tcx> {
|
||||||
VariantPart(Ty<'tcx>, private::HiddenZst),
|
VariantPart(Ty<'tcx>, private::HiddenZst),
|
||||||
/// The ID for the artificial struct type describing a single enum variant.
|
/// The ID for the artificial struct type describing a single enum variant.
|
||||||
VariantStructType(Ty<'tcx>, VariantIdx, private::HiddenZst),
|
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.
|
/// The ID of the artificial type we create for VTables.
|
||||||
VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst),
|
VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst),
|
||||||
}
|
}
|
||||||
|
@ -71,6 +73,15 @@ impl<'tcx> UniqueTypeId<'tcx> {
|
||||||
UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
|
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(
|
pub fn for_vtable_ty(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
self_type: Ty<'tcx>,
|
self_type: Ty<'tcx>,
|
||||||
|
|
|
@ -2079,6 +2079,19 @@ extern "C" {
|
||||||
Ty: &'a DIType,
|
Ty: &'a DIType,
|
||||||
) -> &'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>(
|
pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
|
|
|
@ -18,11 +18,10 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
|
||||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
|
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
|
||||||
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
|
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, ExistentialProjection, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_target::abi::{Integer, TagEncoding, Variants};
|
use rustc_target::abi::Integer;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::debuginfo::wants_c_like_enum_debuginfo;
|
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 {
|
if let Some(ty_and_layout) = layout_for_cpp_like_fallback {
|
||||||
msvc_enum_fallback(
|
msvc_enum_fallback(
|
||||||
tcx,
|
|
||||||
ty_and_layout,
|
ty_and_layout,
|
||||||
&|output, visited| {
|
&|output, visited| {
|
||||||
push_item_name(tcx, def.did(), true, output);
|
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
|
// Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
|
||||||
// "{async_fn_env#0}<T1, T2, ...>", etc.
|
// "{async_fn_env#0}<T1, T2, ...>", etc.
|
||||||
// In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
|
// 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() {
|
if cpp_like_debuginfo && t.is_generator() {
|
||||||
let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap();
|
let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap();
|
||||||
msvc_enum_fallback(
|
msvc_enum_fallback(
|
||||||
tcx,
|
|
||||||
ty_and_layout,
|
ty_and_layout,
|
||||||
&|output, visited| {
|
&|output, visited| {
|
||||||
push_closure_or_generator_name(tcx, def_id, substs, true, 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
|
/// 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
|
// 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
|
// debugger. For more information, look in
|
||||||
// `EnumMemberDescriptionFactor::create_member_descriptions`.
|
// rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs.
|
||||||
fn msvc_enum_fallback<'tcx>(
|
fn msvc_enum_fallback<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
ty_and_layout: TyAndLayout<'tcx>,
|
ty_and_layout: TyAndLayout<'tcx>,
|
||||||
push_inner: &dyn Fn(/*output*/ &mut String, /*visited*/ &mut FxHashSet<Ty<'tcx>>),
|
push_inner: &dyn Fn(/*output*/ &mut String, /*visited*/ &mut FxHashSet<Ty<'tcx>>),
|
||||||
output: &mut String,
|
output: &mut String,
|
||||||
visited: &mut FxHashSet<Ty<'tcx>>,
|
visited: &mut FxHashSet<Ty<'tcx>>,
|
||||||
) {
|
) {
|
||||||
debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
|
debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
|
||||||
let ty = ty_and_layout.ty;
|
output.push_str("enum2$<");
|
||||||
|
|
||||||
output.push_str("enum$<");
|
|
||||||
push_inner(output, visited);
|
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);
|
push_close_angle_bracket(true, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,9 @@ impl<I: Idx, T> IndexVec<I, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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))
|
(0..self.len()).map(|n| I::new(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -924,6 +924,30 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
|
||||||
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
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(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||||
LLVMMetadataRef File, unsigned Line, unsigned Col) {
|
LLVMMetadataRef File, unsigned Line, unsigned Col) {
|
||||||
|
|
|
@ -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">
|
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||||
<Type Name="str">
|
<Type Name="str">
|
||||||
<DisplayString>{(char*)data_ptr,[length]s8}</DisplayString>
|
<DisplayString>{(char*)data_ptr,[length]s8}</DisplayString>
|
||||||
|
@ -150,76 +150,189 @@
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
<!-- Directly tagged enums. $T1 is the type name -->
|
<!--
|
||||||
<Type Name="enum$<*>">
|
This is the visualizer for all enums. It takes care of selecting the active variant.
|
||||||
<Intrinsic Name="tag" Expression="discriminant" />
|
See `compiler\rustc_codegen_llvm\src\debuginfo\metadata\enums\cpp_like.rs` for more information.
|
||||||
<DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
|
-->
|
||||||
<DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
|
<Type Name="enum2$<*>">
|
||||||
<DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
|
<!-- NOTE: That tag ranges can wrap around, in which case `end` is less than `begin` and we
|
||||||
<DisplayString Condition="tag() == 3" Optional="true">{tag(),en}</DisplayString>
|
have to do a different check -->
|
||||||
<DisplayString Condition="tag() == 4" Optional="true">{tag(),en}</DisplayString>
|
<Intrinsic Name="in_range" Expression="(begin <= end) ? ((x >= begin) && (x <= end)) : ((x >= begin) || (x <= end))">
|
||||||
<DisplayString Condition="tag() == 5" Optional="true">{tag(),en}</DisplayString>
|
<Parameter Name="x" Type="unsigned __int64" />
|
||||||
<DisplayString Condition="tag() == 6" Optional="true">{tag(),en}</DisplayString>
|
<Parameter Name="begin" Type="unsigned __int64" />
|
||||||
<DisplayString Condition="tag() == 7" Optional="true">{tag(),en}</DisplayString>
|
<Parameter Name="end" Type="unsigned __int64" />
|
||||||
<DisplayString Condition="tag() == 8" Optional="true">{tag(),en}</DisplayString>
|
</Intrinsic>
|
||||||
<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>
|
|
||||||
|
|
||||||
<Expand>
|
<Intrinsic Name="eq128" Expression="(x_hi == y_hi) && (x_lo == y_lo)">
|
||||||
<Synthetic Name="[variant]">
|
<Parameter Name="x_hi" Type="unsigned __int64" />
|
||||||
<DisplayString>{tag(),en}</DisplayString>
|
<Parameter Name="x_lo" Type="unsigned __int64" />
|
||||||
</Synthetic>
|
<Parameter Name="y_hi" Type="unsigned __int64" />
|
||||||
<ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
|
<Parameter Name="y_lo" Type="unsigned __int64" />
|
||||||
<ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
|
</Intrinsic>
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- Single variant enums. $T1 is the name of the enum, $T2 is the name of the variant -->
|
<Intrinsic Name="lt128" Expression="(x_hi < y_hi) || ((x_hi == y_hi) && (x_lo < y_lo))">
|
||||||
<Type Name="enum$<*, *>">
|
<Parameter Name="x_hi" Type="unsigned __int64" />
|
||||||
<DisplayString>{"$T2",sb}</DisplayString>
|
<Parameter Name="x_lo" Type="unsigned __int64" />
|
||||||
<Expand>
|
<Parameter Name="y_hi" Type="unsigned __int64" />
|
||||||
<Synthetic Name="[variant]">
|
<Parameter Name="y_lo" Type="unsigned __int64" />
|
||||||
<DisplayString>{"$T2",sb}</DisplayString>
|
</Intrinsic>
|
||||||
</Synthetic>
|
|
||||||
<ExpandedItem>$T2</ExpandedItem>
|
|
||||||
</Expand>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<!-- Niche-layout enums. $T1 is the name of the enum, $T2 is the low value of the dataful
|
<Intrinsic Name="lt_or_eq128" Expression="((x_hi == y_hi) && (x_lo == y_lo)) || lt128(x_hi, x_lo, y_hi, y_lo)">
|
||||||
variant tag, $T3 is the high value of the dataful variant tag, $T4 is the name of
|
<Parameter Name="x_hi" Type="unsigned __int64" />
|
||||||
the dataful variant -->
|
<Parameter Name="x_lo" Type="unsigned __int64" />
|
||||||
<Type Name="enum$<*, *, *, *>">
|
<Parameter Name="y_hi" Type="unsigned __int64" />
|
||||||
<Intrinsic Name="tag" Expression="discriminant" />
|
<Parameter Name="y_lo" Type="unsigned __int64" />
|
||||||
<Intrinsic Name="is_dataful" Expression="tag() >= $T2 && tag() <= $T3" />
|
</Intrinsic>
|
||||||
<DisplayString Condition="is_dataful()">{"$T4",sb}({dataful_variant})</DisplayString>
|
|
||||||
<DisplayString Condition="!is_dataful()">{discriminant,en}</DisplayString>
|
<!-- NOTE: That tag ranges can wrap around, in which case `end` is less than `begin` and we
|
||||||
<Expand>
|
have to do a different check -->
|
||||||
<ExpandedItem Condition="is_dataful()">dataful_variant</ExpandedItem>
|
<Intrinsic Name="in_range128" Expression="(lt_or_eq128(begin_hi, begin_lo, end_hi, end_lo)) ?
|
||||||
<Synthetic Condition="is_dataful()" Name="[variant]">
|
(lt_or_eq128(begin_hi, begin_lo, x_hi, x_lo) && lt_or_eq128(x_hi, x_lo, end_hi, end_lo)) :
|
||||||
<DisplayString>{"$T4",sb}</DisplayString>
|
(lt_or_eq128(begin_hi, begin_lo, x_hi, x_lo) || lt_or_eq128(x_hi, x_lo, end_hi, end_lo))">
|
||||||
</Synthetic>
|
<Parameter Name="x_hi" Type="unsigned __int64" />
|
||||||
<Synthetic Condition="!is_dataful()" Name="[variant]">
|
<Parameter Name="x_lo" Type="unsigned __int64" />
|
||||||
<DisplayString>{discriminant,en}</DisplayString>
|
<Parameter Name="begin_hi" Type="unsigned __int64" />
|
||||||
</Synthetic>
|
<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>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
||||||
|
|
|
@ -185,12 +185,4 @@
|
||||||
</ArrayItems>
|
</ArrayItems>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</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>
|
</AutoVisualizer>
|
||||||
|
|
|
@ -12,11 +12,11 @@ async fn async_fn_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
|
// 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: [[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]*]],
|
// 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}>",
|
// 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() {
|
fn main() {
|
||||||
let _fn = async_fn_test();
|
let _fn = async_fn_test();
|
||||||
|
|
|
@ -16,7 +16,7 @@ async fn async_fn_test() {
|
||||||
|
|
||||||
// FIXME: No way to reliably check the filename.
|
// 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]],
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
|
||||||
// For brevity, we only check the struct name and members of the last variant.
|
// For brevity, we only check the struct name and members of the last variant.
|
||||||
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
|
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
|
||||||
|
@ -36,16 +36,17 @@ async fn async_fn_test() {
|
||||||
// CHECK-SAME: )
|
// CHECK-SAME: )
|
||||||
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
|
||||||
// CHECK-SAME: file: [[FILE]], line: 14,
|
// CHECK-SAME: file: [[FILE]], line: 14,
|
||||||
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
|
// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]]
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// 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: [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// CHECK-SAME: )
|
||||||
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// 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
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -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}})
|
// 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}"
|
// 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}"
|
// 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$
|
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<bool>, core::ops::function::FnOnce<tuple$<> > >::vtable$
|
||||||
|
|
|
@ -20,7 +20,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
|
||||||
|
|
||||||
// FIXME: No way to reliably check the filename.
|
// 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]],
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
|
||||||
// For brevity, we only check the struct name and members of the last variant.
|
// For brevity, we only check the struct name and members of the last variant.
|
||||||
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
|
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
|
||||||
|
@ -40,16 +40,18 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
|
||||||
// CHECK-SAME: )
|
// CHECK-SAME: )
|
||||||
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
|
||||||
// CHECK-SAME: file: [[FILE]], line: 17,
|
// CHECK-SAME: file: [[FILE]], line: 17,
|
||||||
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
|
// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]]
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// 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: [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// CHECK-SAME: )
|
||||||
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: )
|
// 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
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -41,31 +41,26 @@
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
// cdb-command: dx b
|
// cdb-command: dx b
|
||||||
// cdb-check: b : Unresumed [Type: enum$<generator_objects::main::generator_env$0>]
|
// cdb-check: b : Unresumed [Type: enum2$<generator_objects::main::generator_env$0>]
|
||||||
// cdb-check: [variant] : Unresumed
|
|
||||||
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *]
|
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *]
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
// cdb-command: dx b
|
// cdb-command: dx b
|
||||||
// cdb-check: b : Suspend0 [Type: enum$<generator_objects::main::generator_env$0>]
|
// cdb-check: b : Suspend0 [Type: enum2$<generator_objects::main::generator_env$0>]
|
||||||
// cdb-check: [variant] : Suspend0
|
|
||||||
// cdb-check: [+0x[...]] c : 6 [Type: int]
|
// cdb-check: [+0x[...]] c : 6 [Type: int]
|
||||||
// cdb-check: [+0x[...]] d : 7 [Type: int]
|
// cdb-check: [+0x[...]] d : 7 [Type: int]
|
||||||
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *]
|
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 5 [Type: int *]
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
// cdb-command: dx b
|
// cdb-command: dx b
|
||||||
// cdb-check: b : Suspend1 [Type: enum$<generator_objects::main::generator_env$0>]
|
// cdb-check: b : Suspend1 [Type: enum2$<generator_objects::main::generator_env$0>]
|
||||||
// cdb-check: [variant] : Suspend1
|
|
||||||
// cdb-check: [+0x[...]] c : 7 [Type: int]
|
// cdb-check: [+0x[...]] c : 7 [Type: int]
|
||||||
// cdb-check: [+0x[...]] d : 8 [Type: int]
|
// cdb-check: [+0x[...]] d : 8 [Type: int]
|
||||||
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *]
|
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *]
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
// cdb-command: dx b
|
// cdb-command: dx b
|
||||||
// cdb-check: b : Returned [Type: enum$<generator_objects::main::generator_env$0>]
|
// cdb-check: b : Returned [Type: enum2$<generator_objects::main::generator_env$0>]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<generator_objects::main::generator_env$0>]
|
|
||||||
// cdb-check: [variant] : Returned
|
|
||||||
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *]
|
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *]
|
||||||
|
|
||||||
#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
|
#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
|
||||||
|
|
|
@ -4,69 +4,141 @@
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
|
|
||||||
// cdb-command: dx a
|
// cdb-command: dx a
|
||||||
// cdb-check:a : Some({...}) [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>]
|
// cdb-check:a : Some [Type: enum2$<core::option::Option<msvc_pretty_enums::CStyleEnum> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>]
|
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
|
// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
|
||||||
|
|
||||||
// cdb-command: dx b
|
// cdb-command: dx b
|
||||||
// cdb-check:b : None [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>]
|
// cdb-check:b : None [Type: enum2$<core::option::Option<msvc_pretty_enums::CStyleEnum> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<msvc_pretty_enums::CStyleEnum>, 2, 16, Some>]
|
|
||||||
// cdb-check: [variant] : None
|
|
||||||
|
|
||||||
// cdb-command: dx c
|
// cdb-command: dx c
|
||||||
// cdb-check:c : Tag1 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
// cdb-check:c : Tag1 [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
|
||||||
// cdb-check: [variant] : Tag1
|
|
||||||
|
|
||||||
// cdb-command: dx d
|
// cdb-command: dx d
|
||||||
// cdb-check:d : Data({...}) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
// cdb-check:d : Data [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
|
||||||
// cdb-check: [variant] : Data
|
|
||||||
// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
||||||
|
|
||||||
// cdb-command: dx e
|
// cdb-command: dx e
|
||||||
// cdb-check:e : Tag2 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
// cdb-check:e : Tag2 [Type: enum2$<msvc_pretty_enums::NicheLayoutEnum>]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
|
|
||||||
// cdb-check: [variant] : Tag2
|
|
||||||
|
|
||||||
// cdb-command: dx f
|
// cdb-command: dx f
|
||||||
// cdb-check:f : Some({...}) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
|
// cdb-check:f : Some [Type: enum2$<core::option::Option<ref$<u32> > >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
|
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
|
// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
|
||||||
|
|
||||||
// cdb-command: dx g
|
// cdb-command: dx g
|
||||||
// cdb-check:g : None [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
|
// cdb-check:g : None [Type: enum2$<core::option::Option<ref$<u32> > >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
|
|
||||||
// cdb-check: [variant] : None
|
|
||||||
|
|
||||||
// cdb-command: dx h
|
// cdb-command: dx h
|
||||||
// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
|
// cdb-check:h : Some [Type: enum2$<core::option::Option<u32> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
|
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
|
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
|
||||||
|
|
||||||
// cdb-command: dx i
|
// cdb-command: dx i
|
||||||
// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
|
// cdb-check:i : None [Type: enum2$<core::option::Option<u32> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
|
|
||||||
// cdb-check: [variant] : None
|
|
||||||
|
|
||||||
// cdb-command: dx j
|
// cdb-command: dx j
|
||||||
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
|
||||||
|
|
||||||
// cdb-command: dx k
|
// cdb-command: dx k
|
||||||
// cdb-check:k : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
|
// cdb-check:k : Some [Type: enum2$<core::option::Option<alloc::string::String> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
|
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
|
// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
|
||||||
|
|
||||||
// cdb-command: dx l
|
// cdb-command: dx l
|
||||||
// cdb-check:l : Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
|
// cdb-check:l : Ok [Type: enum2$<core::result::Result<u32,enum2$<msvc_pretty_enums::Empty> > >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
|
|
||||||
// cdb-check: [variant] : Ok
|
|
||||||
// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int]
|
// 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 {
|
pub enum CStyleEnum {
|
||||||
Low = 2,
|
Low = 2,
|
||||||
High = 16,
|
High = 16,
|
||||||
|
@ -80,6 +152,51 @@ pub enum NicheLayoutEnum {
|
||||||
|
|
||||||
pub enum Empty {}
|
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() {
|
fn main() {
|
||||||
let a = Some(CStyleEnum::Low);
|
let a = Some(CStyleEnum::Low);
|
||||||
let b = Option::<CStyleEnum>::None;
|
let b = Option::<CStyleEnum>::None;
|
||||||
|
@ -93,6 +210,35 @@ fn main() {
|
||||||
let j = CStyleEnum::High;
|
let j = CStyleEnum::High;
|
||||||
let k = Some("IAMA optional string!".to_string());
|
let k = Some("IAMA optional string!".to_string());
|
||||||
let l = Result::<u32, Empty>::Ok(42);
|
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
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,10 @@
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
|
|
||||||
// cdb-command: dx o1
|
// cdb-command: dx o1
|
||||||
// cdb-check:o1 : Some [Type: enum$<core::option::Option<u32> >]
|
// cdb-check:o1 : Some [Type: enum2$<core::option::Option<u32> >]
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]]
|
// cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]]
|
||||||
// cdb-command: dx o2
|
// cdb-command: dx o2
|
||||||
// cdb-check:o2 : Some [Type: enum$<core::option::Option<u64> >]
|
// cdb-check:o2 : Some [Type: enum2$<core::option::Option<u64> >]
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64]
|
// cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64]
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
|
@ -89,7 +87,7 @@ fn slice(s: &[u8]) {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zzz() { }
|
fn zzz() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
range(10..12, 20..30);
|
range(10..12, 20..30);
|
||||||
|
|
|
@ -20,19 +20,20 @@
|
||||||
// cdb-check: [<Raw View>] [Type: core::cell::UnsafeCell<i32>]
|
// cdb-check: [<Raw View>] [Type: core::cell::UnsafeCell<i32>]
|
||||||
|
|
||||||
//
|
//
|
||||||
// cdb-command:dx lock,d
|
// 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:_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: [variant] : Ok
|
|
||||||
// cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>]
|
// cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>]
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
fn main() {
|
||||||
fn main()
|
|
||||||
{
|
|
||||||
let m = Mutex::new(0);
|
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
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
fn zzz() {}
|
fn zzz() {}
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
// gdb-command: print some_string
|
// gdb-command: print some_string
|
||||||
// gdb-check:$8 = Some = {"IAMA "...}
|
// gdb-check:$8 = Some = {"IAMA "...}
|
||||||
|
|
||||||
|
|
||||||
// === LLDB TESTS ==================================================================================
|
// === LLDB TESTS ==================================================================================
|
||||||
|
|
||||||
// lldb-command: run
|
// lldb-command: run
|
||||||
|
@ -65,7 +64,6 @@
|
||||||
// lldb-command: print os_string
|
// lldb-command: print os_string
|
||||||
// lldb-check:[...]$6 = "IAMA OS string 😃"[...]
|
// lldb-check:[...]$6 = "IAMA OS string 😃"[...]
|
||||||
|
|
||||||
|
|
||||||
// === CDB TESTS ==================================================================================
|
// === CDB TESTS ==================================================================================
|
||||||
|
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
|
@ -118,20 +116,17 @@
|
||||||
// cdb-check: [chars] : "IAMA OS string [...]"
|
// cdb-check: [chars] : "IAMA OS string [...]"
|
||||||
|
|
||||||
// cdb-command: dx some
|
// cdb-command: dx some
|
||||||
// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
|
// cdb-check:some : Some [Type: enum2$<core::option::Option<i16> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i16> >]
|
// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<i16> >]
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x002] __0 : 8 [Type: short]
|
// cdb-check: [+0x002] __0 : 8 [Type: short]
|
||||||
|
|
||||||
// cdb-command: dx none
|
// cdb-command: dx none
|
||||||
// cdb-check:none : None [Type: enum$<core::option::Option<i64> >]
|
// cdb-check:none : None [Type: enum2$<core::option::Option<i64> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i64> >]
|
// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<i64> >]
|
||||||
// cdb-check: [variant] : None
|
|
||||||
|
|
||||||
// cdb-command: dx some_string
|
// cdb-command: dx some_string
|
||||||
// cdb-check:some_string : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
|
// cdb-check:some_string : Some [Type: enum2$<core::option::Option<alloc::string::String> >]
|
||||||
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
|
// cdb-check: [<Raw View>] [Type: enum2$<core::option::Option<alloc::string::String> >]
|
||||||
// cdb-check: [variant] : Some
|
|
||||||
// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
|
// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
|
||||||
|
|
||||||
// cdb-command: dx linkedlist
|
// cdb-command: dx linkedlist
|
||||||
|
@ -153,7 +148,6 @@ use std::collections::{LinkedList, VecDeque};
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
// &[]
|
// &[]
|
||||||
let slice: &[i32] = &[0, 1, 2, 3];
|
let slice: &[i32] = &[0, 1, 2, 3];
|
||||||
|
|
||||||
|
@ -188,4 +182,6 @@ fn main() {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zzz() { () }
|
fn zzz() {
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@
|
||||||
// cdb-command: g
|
// cdb-command: g
|
||||||
|
|
||||||
// cdb-command: dx x,d
|
// 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-check: [...] __0 : -3 [Type: int]
|
||||||
|
|
||||||
// cdb-command: dx y
|
// 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]
|
// cdb-check: [...] __0 : "Some error message" [Type: str]
|
||||||
|
|
||||||
fn main()
|
fn main() {
|
||||||
{
|
|
||||||
let x: Result<i32, &str> = Ok(-3);
|
let x: Result<i32, &str> = Ok(-3);
|
||||||
assert_eq!(x.is_ok(), true);
|
assert_eq!(x.is_ok(), true);
|
||||||
|
|
||||||
|
@ -25,4 +24,6 @@ fn main()
|
||||||
zzz(); // #break.
|
zzz(); // #break.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zzz() { () }
|
fn zzz() {
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
|
@ -175,51 +175,51 @@
|
||||||
// 0-sized structs appear to be optimized away in some cases, so only check the structs that do
|
// 0-sized structs appear to be optimized away in some cases, so only check the structs that do
|
||||||
// actually appear.
|
// actually appear.
|
||||||
// cdb-command:dv /t *_struct
|
// 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
|
// ENUMS
|
||||||
// cdb-command:dv /t *_enum_*
|
// cdb-command:dv /t *_enum_*
|
||||||
// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...]
|
// cdb-check:union enum2$<type_names::Enum1> simple_enum_1 = [...]
|
||||||
// cdb-check:union enum$<type_names::Enum1> simple_enum_2 = [...]
|
// cdb-check:union enum2$<type_names::Enum1> simple_enum_2 = [...]
|
||||||
// cdb-check:union enum$<type_names::mod1::Enum2> simple_enum_3 = [...]
|
// cdb-check:union enum2$<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 enum2$<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::mod1::mod2::Enum3<type_names::Struct1> > generic_enum_2 = [...]
|
||||||
|
|
||||||
// TUPLES
|
// TUPLES
|
||||||
// cdb-command:dv /t tuple*
|
// 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$<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>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...]
|
// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum2$<type_names::mod1::Enum2>,char> tuple2 = [...]
|
||||||
|
|
||||||
// BOX
|
// BOX
|
||||||
// cdb-command:dv /t 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<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
|
// REFERENCES
|
||||||
// cdb-command:dv /t *ref*
|
// cdb-command:dv /t *ref*
|
||||||
// cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...]
|
// 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$<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::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
|
// RAW POINTERS
|
||||||
// cdb-command:dv /t *_ptr*
|
// cdb-command:dv /t *_ptr*
|
||||||
// cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...]
|
// 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$<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$<type_names::Struct1>,isize> const_ptr1 = [...]
|
||||||
// cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...]
|
// 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
|
// VECTORS
|
||||||
// cdb-command:dv /t *vec*
|
// cdb-command:dv /t *vec*
|
||||||
// cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...]
|
// 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 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<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-command:dv /t slice*
|
||||||
// cdb-check:struct slice$<usize> slice1 = [...]
|
// 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
|
// TRAITS
|
||||||
// cdb-command:dv /t *_trait
|
// 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::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$<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$<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 (*)(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-command:dv /t *_function*
|
||||||
// cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_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$<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-check:struct tuple$<isize (*)(isize),usize> generic_function_int = [...]
|
||||||
// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn")
|
// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn")
|
||||||
// cdb-check:Return Type: void
|
// 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-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value")
|
||||||
// cdb-check:Return Type: usize
|
// cdb-check:Return Type: usize
|
||||||
// cdb-check:Parameter Types: f64
|
// cdb-check:Parameter Types: f64
|
||||||
|
|
|
@ -545,6 +545,8 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
|
||||||
stamp.add_path(&path);
|
stamp.add_path(&path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
|
||||||
|
|
||||||
stamp.add_dir(&config.run_lib_path);
|
stamp.add_dir(&config.run_lib_path);
|
||||||
|
|
||||||
if let Some(ref rustdoc_path) = config.rustdoc_path {
|
if let Some(ref rustdoc_path) = config.rustdoc_path {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue