mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Describe generator variants in debuginfo
This commit is contained in:
parent
5a7af5480c
commit
961ba95e5a
@ -11,6 +11,7 @@ use rustc_macros::HashStable;
|
||||
use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind};
|
||||
use crate::ty::{self, AdtDef, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
|
||||
use crate::ty::layout::VariantIdx;
|
||||
use crate::util::captures::Captures;
|
||||
use crate::mir::interpret::{Scalar, Pointer};
|
||||
|
||||
@ -466,7 +467,44 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
|
||||
/// Generator have not been resumed yet
|
||||
pub const UNRESUMED: usize = 0;
|
||||
/// Generator has returned / is completed
|
||||
pub const RETURNED: usize = 1;
|
||||
/// Generator has been poisoned
|
||||
pub const POISONED: usize = 2;
|
||||
|
||||
const UNRESUMED_NAME: &'static str = "Unresumed";
|
||||
const RETURNED_NAME: &'static str = "Returned";
|
||||
const POISONED_NAME: &'static str = "Panicked";
|
||||
|
||||
/// The variants of this Generator.
|
||||
#[inline]
|
||||
pub fn variants(&self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
|
||||
impl Iterator<Item = VariantIdx>
|
||||
{
|
||||
// FIXME requires optimized MIR
|
||||
let num_variants = self.state_tys(def_id, tcx).count();
|
||||
(0..num_variants).map(VariantIdx::new)
|
||||
}
|
||||
|
||||
/// Calls `f` with a reference to the name of the enumerator for the given
|
||||
/// variant `v`.
|
||||
#[inline]
|
||||
pub fn map_variant_name<R>(&self, v: VariantIdx, f: impl FnOnce(&str) -> R) -> R {
|
||||
let name = match v.as_usize() {
|
||||
Self::UNRESUMED => Self::UNRESUMED_NAME,
|
||||
Self::RETURNED => Self::RETURNED_NAME,
|
||||
Self::POISONED => Self::POISONED_NAME,
|
||||
_ => {
|
||||
return f(&format!("variant#{}", v.as_usize()));
|
||||
}
|
||||
};
|
||||
f(name)
|
||||
}
|
||||
|
||||
/// The type of the state "discriminant" used in the generator type.
|
||||
#[inline]
|
||||
pub fn discr_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
tcx.types.u32
|
||||
}
|
||||
@ -477,6 +515,7 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
|
||||
///
|
||||
/// The locals are grouped by their variant number. Note that some locals may
|
||||
/// be repeated in multiple variants.
|
||||
#[inline]
|
||||
pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
|
||||
impl Iterator<Item=impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a>
|
||||
{
|
||||
@ -487,6 +526,7 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
|
||||
|
||||
/// This is the types of the fields of a generator which are not stored in a
|
||||
/// variant.
|
||||
#[inline]
|
||||
pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
|
||||
impl Iterator<Item=Ty<'tcx>> + 'a
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc::ty::Instance;
|
||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf,
|
||||
PrimitiveExt, Size, TyLayout};
|
||||
PrimitiveExt, Size, TyLayout, VariantIdx};
|
||||
use rustc::ty::subst::UnpackedKind;
|
||||
use rustc::session::config;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
@ -691,17 +691,15 @@ pub fn type_metadata(
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
// TODO handle variant fields
|
||||
let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| {
|
||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
|
||||
}).collect();
|
||||
// TODO use prepare_enum_metadata and update it to handle multiple
|
||||
// fields in the outer layout.
|
||||
prepare_tuple_metadata(cx,
|
||||
t,
|
||||
&upvar_tys,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
prepare_enum_metadata(cx,
|
||||
t,
|
||||
def_id,
|
||||
unique_type_id,
|
||||
usage_site_span,
|
||||
upvar_tys).finalize(cx)
|
||||
}
|
||||
ty::Adt(def, ..) => match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
@ -721,7 +719,8 @@ pub fn type_metadata(
|
||||
t,
|
||||
def.did,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
usage_site_span,
|
||||
vec![]).finalize(cx)
|
||||
}
|
||||
},
|
||||
ty::Tuple(ref elements) => {
|
||||
@ -998,6 +997,31 @@ struct MemberDescription<'ll> {
|
||||
discriminant: Option<u64>,
|
||||
}
|
||||
|
||||
impl<'ll> MemberDescription<'ll> {
|
||||
fn into_metadata(self,
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
composite_type_metadata: &'ll DIScope) -> &'ll DIType {
|
||||
let member_name = CString::new(self.name).unwrap();
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
||||
DIB(cx),
|
||||
composite_type_metadata,
|
||||
member_name.as_ptr(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
self.size.bits(),
|
||||
self.align.bits() as u32,
|
||||
self.offset.bits(),
|
||||
match self.discriminant {
|
||||
None => None,
|
||||
Some(value) => Some(cx.const_u64(value)),
|
||||
},
|
||||
self.flags,
|
||||
self.type_metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A factory for MemberDescriptions. It produces a list of member descriptions
|
||||
// for some record-like type. MemberDescriptionFactories are used to defer the
|
||||
// creation of type member descriptions in order to break cycles arising from
|
||||
@ -1264,7 +1288,13 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
||||
-> Vec<MemberDescription<'ll>> {
|
||||
let adt = &self.enum_type.ty_adt_def().unwrap();
|
||||
let variant_info_for = |index: VariantIdx| {
|
||||
match &self.enum_type.sty {
|
||||
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
|
||||
ty::Generator(_, substs, _) => VariantInfo::Generator(*substs, index),
|
||||
_ => bug!(),
|
||||
}
|
||||
};
|
||||
|
||||
// This will always find the metadata in the type map.
|
||||
let fallback = use_enum_fallback(cx);
|
||||
@ -1275,12 +1305,18 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
};
|
||||
|
||||
match self.layout.variants {
|
||||
layout::Variants::Single { .. } if adt.variants.is_empty() => vec![],
|
||||
layout::Variants::Single { index } => {
|
||||
if let ty::Adt(adt, _) = &self.enum_type.sty {
|
||||
if adt.variants.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
}
|
||||
|
||||
let variant_info = variant_info_for(index);
|
||||
let (variant_type_metadata, member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
self.layout,
|
||||
&adt.variants[index],
|
||||
variant_info,
|
||||
NoDiscriminant,
|
||||
self_metadata,
|
||||
self.span);
|
||||
@ -1297,7 +1333,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
name: if fallback {
|
||||
String::new()
|
||||
} else {
|
||||
adt.variants[index].ident.as_str().to_string()
|
||||
variant_info.name_as_string()
|
||||
},
|
||||
type_metadata: variant_type_metadata,
|
||||
offset: Size::ZERO,
|
||||
@ -1325,10 +1361,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
};
|
||||
variants.iter_enumerated().map(|(i, _)| {
|
||||
let variant = self.layout.for_variant(cx, i);
|
||||
let variant_info = variant_info_for(i);
|
||||
let (variant_type_metadata, member_desc_factory) =
|
||||
describe_enum_variant(cx,
|
||||
variant,
|
||||
&adt.variants[i],
|
||||
variant_info,
|
||||
discriminant_info,
|
||||
self_metadata,
|
||||
self.span);
|
||||
@ -1340,20 +1377,25 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
self.enum_type,
|
||||
variant_type_metadata,
|
||||
member_descriptions);
|
||||
|
||||
// TODO make this into a helper
|
||||
let discriminant = match &self.layout.ty.sty {
|
||||
ty::Adt(adt, _) => adt.discriminant_for_variant(cx.tcx, i).val as u64,
|
||||
ty::Generator(..) => i.as_usize() as u64,
|
||||
_ => bug!(),
|
||||
}.into();
|
||||
MemberDescription {
|
||||
name: if fallback {
|
||||
String::new()
|
||||
} else {
|
||||
adt.variants[i].ident.as_str().to_string()
|
||||
variant_info.name_as_string()
|
||||
},
|
||||
type_metadata: variant_type_metadata,
|
||||
offset: Size::ZERO,
|
||||
size: self.layout.size,
|
||||
align: self.layout.align.abi,
|
||||
flags: DIFlags::FlagZero,
|
||||
discriminant: Some(self.layout.ty.ty_adt_def().unwrap()
|
||||
.discriminant_for_variant(cx.tcx, i)
|
||||
.val as u64),
|
||||
discriminant,
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
@ -1373,7 +1415,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
let (variant_type_metadata, member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
variant,
|
||||
&adt.variants[dataful_variant],
|
||||
variant_info_for(dataful_variant),
|
||||
OptimizedDiscriminant,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
@ -1413,7 +1455,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
self.layout,
|
||||
self.layout.fields.offset(discr_index),
|
||||
self.layout.field(cx, discr_index).size);
|
||||
name.push_str(&adt.variants[*niche_variants.start()].ident.as_str());
|
||||
variant_info_for(*niche_variants.start()).map_name(|variant_name| {
|
||||
name.push_str(variant_name);
|
||||
});
|
||||
|
||||
// Create the (singleton) list of descriptions of union members.
|
||||
vec![
|
||||
@ -1430,10 +1474,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
} else {
|
||||
variants.iter_enumerated().map(|(i, _)| {
|
||||
let variant = self.layout.for_variant(cx, i);
|
||||
let variant_info = variant_info_for(i);
|
||||
let (variant_type_metadata, member_desc_factory) =
|
||||
describe_enum_variant(cx,
|
||||
variant,
|
||||
&adt.variants[i],
|
||||
variant_info,
|
||||
OptimizedDiscriminant,
|
||||
self_metadata,
|
||||
self.span);
|
||||
@ -1461,7 +1506,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
};
|
||||
|
||||
MemberDescription {
|
||||
name: adt.variants[i].ident.as_str().to_string(),
|
||||
name: variant_info.name_as_string(),
|
||||
type_metadata: variant_type_metadata,
|
||||
offset: Size::ZERO,
|
||||
size: self.layout.size,
|
||||
@ -1519,6 +1564,34 @@ enum EnumDiscriminantInfo<'ll> {
|
||||
NoDiscriminant
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum VariantInfo<'tcx> {
|
||||
Adt(&'tcx ty::VariantDef),
|
||||
Generator(ty::GeneratorSubsts<'tcx>, VariantIdx),
|
||||
}
|
||||
|
||||
impl<'tcx> VariantInfo<'tcx> {
|
||||
fn map_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
||||
match self {
|
||||
VariantInfo::Adt(variant) => f(&variant.ident.as_str()),
|
||||
VariantInfo::Generator(substs, variant_index) =>
|
||||
substs.map_variant_name(*variant_index, f),
|
||||
}
|
||||
}
|
||||
|
||||
fn name_as_string(&self) -> String {
|
||||
self.map_name(|name| name.to_string())
|
||||
}
|
||||
|
||||
fn field_name(&self, i: usize) -> String {
|
||||
match self {
|
||||
VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn =>
|
||||
variant.fields[i].ident.to_string(),
|
||||
_ => format!("__{}", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a tuple of (1) type_metadata_stub of the variant, (2) a
|
||||
// MemberDescriptionFactory for producing the descriptions of the
|
||||
// fields of the variant. This is a rudimentary version of a full
|
||||
@ -1526,32 +1599,24 @@ enum EnumDiscriminantInfo<'ll> {
|
||||
fn describe_enum_variant(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
layout: layout::TyLayout<'tcx>,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
variant: VariantInfo<'tcx>,
|
||||
discriminant_info: EnumDiscriminantInfo<'ll>,
|
||||
containing_scope: &'ll DIScope,
|
||||
span: Span,
|
||||
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
||||
let variant_name = variant.ident.as_str();
|
||||
let unique_type_id = debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_enum_variant(
|
||||
cx,
|
||||
layout.ty,
|
||||
&variant_name);
|
||||
|
||||
let metadata_stub = create_struct_stub(cx,
|
||||
layout.ty,
|
||||
&variant_name,
|
||||
unique_type_id,
|
||||
Some(containing_scope));
|
||||
|
||||
let arg_name = |i: usize| {
|
||||
if variant.ctor_kind == CtorKind::Fn {
|
||||
format!("__{}", i)
|
||||
} else {
|
||||
variant.fields[i].ident.to_string()
|
||||
}
|
||||
};
|
||||
let metadata_stub = variant.map_name(|variant_name| {
|
||||
let unique_type_id = debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_enum_variant(
|
||||
cx,
|
||||
layout.ty,
|
||||
&variant_name);
|
||||
create_struct_stub(cx,
|
||||
layout.ty,
|
||||
&variant_name,
|
||||
unique_type_id,
|
||||
Some(containing_scope))
|
||||
});
|
||||
|
||||
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
||||
let (offsets, args) = if use_enum_fallback(cx) {
|
||||
@ -1573,7 +1638,7 @@ fn describe_enum_variant(
|
||||
layout.fields.offset(i)
|
||||
})).collect(),
|
||||
discr_arg.into_iter().chain((0..layout.fields.count()).map(|i| {
|
||||
(arg_name(i), layout.field(cx, i).ty)
|
||||
(variant.field_name(i), layout.field(cx, i).ty)
|
||||
})).collect()
|
||||
)
|
||||
} else {
|
||||
@ -1582,7 +1647,7 @@ fn describe_enum_variant(
|
||||
layout.fields.offset(i)
|
||||
}).collect(),
|
||||
(0..layout.fields.count()).map(|i| {
|
||||
(arg_name(i), layout.field(cx, i).ty)
|
||||
(variant.field_name(i), layout.field(cx, i).ty)
|
||||
}).collect()
|
||||
)
|
||||
};
|
||||
@ -1609,6 +1674,7 @@ fn prepare_enum_metadata(
|
||||
enum_def_id: DefId,
|
||||
unique_type_id: UniqueTypeId,
|
||||
span: Span,
|
||||
outer_field_tys: Vec<Ty<'tcx>>,
|
||||
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
||||
let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
|
||||
|
||||
@ -1622,20 +1688,36 @@ fn prepare_enum_metadata(
|
||||
let file_metadata = unknown_file_metadata(cx);
|
||||
|
||||
let discriminant_type_metadata = |discr: layout::Primitive| {
|
||||
let def = enum_type.ty_adt_def().unwrap();
|
||||
let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
|
||||
.zip(&def.variants)
|
||||
.map(|((_, discr), v)| {
|
||||
let name = SmallCStr::new(&v.ident.as_str());
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
discr.val as u64))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let enumerators_metadata: Vec<_> = match enum_type.sty {
|
||||
ty::Adt(def, _) => def
|
||||
.discriminants(cx.tcx)
|
||||
.zip(&def.variants)
|
||||
.map(|((_, discr), v)| {
|
||||
let name = SmallCStr::new(&v.ident.as_str());
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
discr.val as u64))
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
ty::Generator(_, substs, _) => substs
|
||||
.variants(enum_def_id, cx.tcx)
|
||||
.map(|v| substs.map_variant_name(v, |name| {
|
||||
let name = SmallCStr::new(name);
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
v.as_usize() as u64))
|
||||
}
|
||||
}))
|
||||
.collect(),
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
let disr_type_key = (enum_def_id, discr);
|
||||
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
||||
@ -1648,14 +1730,18 @@ fn prepare_enum_metadata(
|
||||
(discr.size(cx), discr.align(cx));
|
||||
let discriminant_base_type_metadata =
|
||||
type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
|
||||
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
|
||||
|
||||
let name = SmallCStr::new(&discriminant_name);
|
||||
let discriminant_name = match enum_type.sty {
|
||||
ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()),
|
||||
ty::Generator(..) => SmallCStr::new(&enum_name),
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
let discriminant_type_metadata = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_ptr(),
|
||||
discriminant_name.as_ptr(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
discriminant_size.bits(),
|
||||
@ -1736,6 +1822,11 @@ fn prepare_enum_metadata(
|
||||
);
|
||||
}
|
||||
|
||||
let discriminator_name = match &enum_type.sty {
|
||||
ty::Generator(..) => Some(SmallCStr::new(&"__state")),
|
||||
_ => None,
|
||||
};
|
||||
let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut());
|
||||
let discriminator_metadata = match layout.variants {
|
||||
// A single-variant enum has no discriminant.
|
||||
layout::Variants::Single { .. } => None,
|
||||
@ -1762,7 +1853,7 @@ fn prepare_enum_metadata(
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
ptr::null_mut(),
|
||||
discriminator_name,
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
@ -1787,7 +1878,7 @@ fn prepare_enum_metadata(
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
ptr::null_mut(),
|
||||
discriminator_name,
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
@ -1799,6 +1890,22 @@ fn prepare_enum_metadata(
|
||||
},
|
||||
};
|
||||
|
||||
let mut outer_fields = match layout.variants {
|
||||
layout::Variants::Single { .. } => vec![],
|
||||
layout::Variants::Multiple { .. } => {
|
||||
let tuple_mdf = TupleMemberDescriptionFactory {
|
||||
ty: enum_type,
|
||||
component_types: outer_field_tys,
|
||||
span
|
||||
};
|
||||
tuple_mdf
|
||||
.create_member_descriptions(cx)
|
||||
.into_iter()
|
||||
.map(|desc| Some(desc.into_metadata(cx, containing_scope)))
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
let variant_part_unique_type_id_str = SmallCStr::new(
|
||||
debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
@ -1819,10 +1926,10 @@ fn prepare_enum_metadata(
|
||||
empty_array,
|
||||
variant_part_unique_type_id_str.as_ptr())
|
||||
};
|
||||
outer_fields.push(Some(variant_part));
|
||||
|
||||
// The variant part must be wrapped in a struct according to DWARF.
|
||||
// TODO create remaining fields here, if any.
|
||||
let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]);
|
||||
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
||||
let struct_wrapper = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
@ -1854,12 +1961,6 @@ fn prepare_enum_metadata(
|
||||
span,
|
||||
}),
|
||||
);
|
||||
|
||||
fn get_enum_discriminant_name(cx: &CodegenCx<'_, '_>,
|
||||
def_id: DefId)
|
||||
-> InternedString {
|
||||
cx.tcx.item_name(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates debug information for a composite type, that is, anything that
|
||||
@ -1917,26 +2018,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>,
|
||||
|
||||
let member_metadata: Vec<_> = member_descriptions
|
||||
.into_iter()
|
||||
.map(|member_description| {
|
||||
let member_name = CString::new(member_description.name).unwrap();
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
||||
DIB(cx),
|
||||
composite_type_metadata,
|
||||
member_name.as_ptr(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
member_description.size.bits(),
|
||||
member_description.align.bits() as u32,
|
||||
member_description.offset.bits(),
|
||||
match member_description.discriminant {
|
||||
None => None,
|
||||
Some(value) => Some(cx.const_u64(value)),
|
||||
},
|
||||
member_description.flags,
|
||||
member_description.type_metadata))
|
||||
}
|
||||
})
|
||||
.map(|desc| Some(desc.into_metadata(cx, composite_type_metadata)))
|
||||
.collect();
|
||||
|
||||
let type_params = compute_type_parameters(cx, composite_type);
|
||||
|
@ -54,6 +54,7 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
|
||||
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
|
||||
use rustc::ty::GeneratorSubsts;
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -145,11 +146,11 @@ fn self_arg() -> Local {
|
||||
}
|
||||
|
||||
/// Generator have not been resumed yet
|
||||
const UNRESUMED: usize = 0;
|
||||
const UNRESUMED: usize = GeneratorSubsts::UNRESUMED;
|
||||
/// Generator has returned / is completed
|
||||
const RETURNED: usize = 1;
|
||||
const RETURNED: usize = GeneratorSubsts::RETURNED;
|
||||
/// Generator has been poisoned
|
||||
const POISONED: usize = 2;
|
||||
const POISONED: usize = GeneratorSubsts::POISONED;
|
||||
|
||||
struct SuspensionPoint {
|
||||
state: usize,
|
||||
|
68
src/test/debuginfo/generator-objects.rs
Normal file
68
src/test/debuginfo/generator-objects.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
|
||||
// min-system-llvm-version: 8.0
|
||||
// min-gdb-version: 8.2
|
||||
|
||||
// compile-flags:-g
|
||||
|
||||
// === GDB TESTS ===================================================================================
|
||||
|
||||
// gdb-command:run
|
||||
// gdb-command:print b
|
||||
// gdb-check:$1 = generator_objects::main::generator {__0: 0x[...], <<variant>>: {__state: 0, Unresumed: generator_objects::main::generator::Unresumed, Returned: generator_objects::main::generator::Returned, Panicked: generator_objects::main::generator::Panicked, variant#3: generator_objects::main::generator::variant#3 ([...]), variant#4: generator_objects::main::generator::variant#4 ([...])}}
|
||||
// gdb-command:continue
|
||||
// gdb-command:print b
|
||||
// gdb-check:$2 = generator_objects::main::generator {__0: 0x[...], <<variant>>: {__state: 3, Unresumed: generator_objects::main::generator::Unresumed, Returned: generator_objects::main::generator::Returned, Panicked: generator_objects::main::generator::Panicked, variant#3: generator_objects::main::generator::variant#3 (6, 7), variant#4: generator_objects::main::generator::variant#4 ([...])}}
|
||||
// gdb-command:continue
|
||||
// gdb-command:print b
|
||||
// gdb-check:$3 = generator_objects::main::generator {__0: 0x[...], <<variant>>: {__state: 4, Unresumed: generator_objects::main::generator::Unresumed, Returned: generator_objects::main::generator::Returned, Panicked: generator_objects::main::generator::Panicked, variant#3: generator_objects::main::generator::variant#3 ([...]), variant#4: generator_objects::main::generator::variant#4 (7, 8)}}
|
||||
// gdb-command:continue
|
||||
// gdb-command:print b
|
||||
// gdb-check:$4 = generator_objects::main::generator {__0: 0x[...], <<variant>>: {__state: 1, Unresumed: generator_objects::main::generator::Unresumed, Returned: generator_objects::main::generator::Returned, Panicked: generator_objects::main::generator::Panicked, variant#3: generator_objects::main::generator::variant#3 ([...]), variant#4: generator_objects::main::generator::variant#4 ([...])}}
|
||||
|
||||
// === LLDB TESTS ==================================================================================
|
||||
|
||||
// lldb-command:run
|
||||
// lldb-command:print b
|
||||
// lldbg-check:(generator_objects::main::generator) $0 = generator(&0x[...])
|
||||
// lldb-command:continue
|
||||
// lldb-command:print b
|
||||
// lldbg-check:(generator_objects::main::generator) $1 = generator(&0x[...])
|
||||
// lldb-command:continue
|
||||
// lldb-command:print b
|
||||
// lldbg-check:(generator_objects::main::generator) $2 = generator(&0x[...])
|
||||
// lldb-command:continue
|
||||
// lldb-command:print b
|
||||
// lldbg-check:(generator_objects::main::generator) $3 = generator(&0x[...])
|
||||
|
||||
#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut a = 5;
|
||||
let mut b = || {
|
||||
let mut c = 6;
|
||||
let mut d = 7;
|
||||
|
||||
yield;
|
||||
a += 1;
|
||||
c += 1;
|
||||
d += 1;
|
||||
|
||||
yield;
|
||||
println!("{} {} {}", a, c, d);
|
||||
};
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
_zzz(); // #break
|
||||
}
|
||||
|
||||
fn _zzz() {()}
|
Loading…
Reference in New Issue
Block a user