From a5a831f51169767c27ddd7edb30269d01f00bf29 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 17 Jun 2020 16:04:25 -0700 Subject: [PATCH 1/9] Emit line info for generator variants --- .../debuginfo/metadata.rs | 66 ++++++++++++++++--- src/librustc_middle/mir/query.rs | 4 ++ src/librustc_mir/transform/generator.rs | 22 ++++++- ...ustc.main-{{closure}}.generator_drop.0.mir | 2 +- ...tc.main-{{closure}}.generator_resume.0.mir | 2 +- 5 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 8a957a729fb68..ee8ab7c0e4df3 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -392,6 +392,7 @@ fn vec_slice_metadata( align: pointer_align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, }, MemberDescription { name: "length".to_owned(), @@ -401,6 +402,7 @@ fn vec_slice_metadata( align: usize_align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, }, ]; @@ -508,6 +510,7 @@ fn trait_pointer_metadata( align: data_ptr_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, + source_info: None, }, MemberDescription { name: "vtable".to_owned(), @@ -517,6 +520,7 @@ fn trait_pointer_metadata( align: vtable_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, + source_info: None, }, ]; @@ -1026,6 +1030,12 @@ impl MetadataCreationResult<'ll> { } } +#[derive(Debug)] +struct SourceInfo<'ll> { + file: &'ll DIFile, + line: u32, +} + /// Description of a type member, which can either be a regular field (as in /// structs or tuples) or an enum variant. #[derive(Debug)] @@ -1037,6 +1047,7 @@ struct MemberDescription<'ll> { align: Align, flags: DIFlags, discriminant: Option, + source_info: Option>, } impl<'ll> MemberDescription<'ll> { @@ -1045,14 +1056,18 @@ impl<'ll> MemberDescription<'ll> { cx: &CodegenCx<'ll, '_>, composite_type_metadata: &'ll DIScope, ) -> &'ll DIType { + let (file, line) = self + .source_info + .map(|info| (info.file, info.line)) + .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); unsafe { llvm::LLVMRustDIBuilderCreateVariantMemberType( DIB(cx), composite_type_metadata, self.name.as_ptr().cast(), self.name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file, + line, self.size.bits(), self.align.bits() as u32, self.offset.bits(), @@ -1124,6 +1139,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1185,6 +1201,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1244,6 +1261,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1351,10 +1369,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let variant_info_for = |index: VariantIdx| match self.enum_type.kind { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), - ty::Generator(_, substs, _) => { + ty::Generator(def_id, substs, _) => { let (generator_layout, generator_saved_local_names) = generator_variant_info_data.as_ref().unwrap(); VariantInfo::Generator { + def_id, substs, generator_layout: *generator_layout, generator_saved_local_names, @@ -1406,6 +1425,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { align: self.layout.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: variant_info.source_info(cx), }] } Variants::Multiple { @@ -1462,6 +1482,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val as u64, ), + source_info: variant_info.source_info(cx), } }) .collect() @@ -1527,7 +1548,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.layout.fields.offset(tag_field), self.layout.field(cx, tag_field).size, ); - variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| { + let variant_info = variant_info_for(*niche_variants.start()); + variant_info.map_struct_name(|variant_name| { name.push_str(variant_name); }); @@ -1540,6 +1562,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { align: variant.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: variant_info.source_info(cx), }] } else { variants @@ -1589,6 +1612,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { align: self.layout.align.abi, flags: DIFlags::FlagZero, discriminant: niche_value, + source_info: variant_info.source_info(cx), } }) .collect() @@ -1631,6 +1655,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1651,6 +1676,7 @@ enum EnumTagInfo<'ll> { enum VariantInfo<'a, 'tcx> { Adt(&'tcx ty::VariantDef), Generator { + def_id: DefId, substs: SubstsRef<'tcx>, generator_layout: &'tcx GeneratorLayout<'tcx>, generator_saved_local_names: &'a IndexVec>, @@ -1699,6 +1725,24 @@ impl<'tcx> VariantInfo<'_, 'tcx> { }; field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) } + + fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { + match self { + VariantInfo::Generator { def_id, variant_index, .. } => { + let span = + cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span; + if !span.is_dummy() { + let loc = cx.lookup_debug_loc(span.lo()); + return Some(SourceInfo { + file: file_metadata(cx, &loc.file, def_id.krate), + line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), + }); + } + } + _ => {} + } + None + } } /// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a @@ -1778,7 +1822,8 @@ fn prepare_enum_metadata( span: Span, outer_field_tys: Vec>, ) -> RecursiveTypeDescription<'ll, 'tcx> { - let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false); + let tcx = cx.tcx; + let enum_name = compute_debuginfo_type_name(tcx, enum_type, false); let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we @@ -1792,7 +1837,7 @@ fn prepare_enum_metadata( let discriminant_type_metadata = |discr: Primitive| { let enumerators_metadata: Vec<_> = match enum_type.kind { ty::Adt(def, _) => def - .discriminants(cx.tcx) + .discriminants(tcx) .zip(&def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); @@ -1815,15 +1860,16 @@ fn prepare_enum_metadata( .collect(), ty::Generator(_, substs, _) => substs .as_generator() - .variant_range(enum_def_id, cx.tcx) + .variant_range(enum_def_id, tcx) .map(|variant_index| { + debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx)); let name = substs.as_generator().variant_name(variant_index); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), name.as_ptr().cast(), name.len(), - // Generators use u32 as discriminant type. + // Generators use u32 as discriminant type, verified above. variant_index.as_u32().into(), true, // IsUnsigned )) @@ -1841,12 +1887,12 @@ fn prepare_enum_metadata( None => { let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); let discriminant_base_type_metadata = - type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP); + type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP); let item_name; let discriminant_name = match enum_type.kind { ty::Adt(..) => { - item_name = cx.tcx.item_name(enum_def_id).as_str(); + item_name = tcx.item_name(enum_def_id).as_str(); &*item_name } ty::Generator(..) => enum_name.as_str(), diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 1aae97cc2a894..b77b069befd00 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -67,6 +67,10 @@ pub struct GeneratorLayout<'tcx> { /// be stored in multiple variants. pub variant_fields: IndexVec>, + /// The source that led to each variant being created (usually, a yield or + /// await). + pub variant_source_info: IndexVec, + /// Which saved locals are storage-live at the same time. Locals that do not /// have conflicts with each other are allowed to overlap in the computed /// layout. diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 59be8dc224dee..523d3c9af3f68 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -422,6 +422,9 @@ struct LivenessInfo { /// The set of saved locals live at each suspension point. live_locals_at_suspension_points: Vec>, + /// Parallel vec to the above with SourceInfo for each yield terminator. + source_info_at_suspension_points: Vec, + /// For every saved local, the set of other saved locals that are /// storage-live at the same time as this local. We cannot overlap locals in /// the layout which have conflicting storage. @@ -473,6 +476,7 @@ fn locals_live_across_suspend_points( let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks()); let mut live_locals_at_suspension_points = Vec::new(); + let mut source_info_at_suspension_points = Vec::new(); let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len()); for (block, data) in body.basic_blocks().iter_enumerated() { @@ -518,6 +522,7 @@ fn locals_live_across_suspend_points( live_locals_at_any_suspension_point.union(&live_locals); live_locals_at_suspension_points.push(live_locals); + source_info_at_suspension_points.push(data.terminator().source_info); } } @@ -541,6 +546,7 @@ fn locals_live_across_suspend_points( LivenessInfo { saved_locals, live_locals_at_suspension_points, + source_info_at_suspension_points, storage_conflicts, storage_liveness: storage_liveness_map, } @@ -754,6 +760,7 @@ fn compute_layout<'tcx>( let LivenessInfo { saved_locals, live_locals_at_suspension_points, + source_info_at_suspension_points, storage_conflicts, storage_liveness, } = liveness; @@ -768,7 +775,18 @@ fn compute_layout<'tcx>( } // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. + // In debuginfo, these will correspond to the beginning (UNRESUMED) or end + // (RETURNED, POISONED) of the function. const RESERVED_VARIANTS: usize = 3; + let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; + let mut variant_source_info: IndexVec = [ + SourceInfo::outermost(body_span.shrink_to_lo()), + SourceInfo::outermost(body_span.shrink_to_hi()), + SourceInfo::outermost(body_span.shrink_to_hi()), + ] + .iter() + .copied() + .collect(); // Build the generator variant field list. // Create a map from local indices to generator struct indices. @@ -787,11 +805,13 @@ fn compute_layout<'tcx>( remap.entry(locals[saved_local]).or_insert((tys[saved_local], variant_index, idx)); } variant_fields.push(fields); + variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]); } debug!("generator variant_fields = {:?}", variant_fields); debug!("generator storage_conflicts = {:#?}", storage_conflicts); - let layout = GeneratorLayout { field_tys: tys, variant_fields, storage_conflicts }; + let layout = + GeneratorLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts }; (remap, layout, storage_liveness) } diff --git a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir index 3e7083ff62ecd..b34d42155cc6c 100644 --- a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir +++ b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir @@ -1,5 +1,5 @@ // MIR for `main::{{closure}}#0` 0 generator_drop -// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-drop-cleanup.rs:10:15: 10:15 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:12:9: 12:14 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } fn main::{{closure}}#0(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {std::string::String, ()}]) -> () { let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 diff --git a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir index c73dea5f8fde6..2398e9501452e 100644 --- a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir +++ b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir @@ -1,5 +1,5 @@ // MIR for `main::{{closure}}#0` 0 generator_resume -// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-tiny.rs:19:16: 19:16 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:22:13: 22:18 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> std::ops::GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 From eb726c0fcec3f9d12a6a9990c5c041478e1e7187 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 17 Jun 2020 19:39:23 -0700 Subject: [PATCH 2/9] Add Artificial flag to generator variants --- .../debuginfo/metadata.rs | 67 +++++++++++++++---- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index ee8ab7c0e4df3..f26c45e90110a 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -863,7 +863,7 @@ fn foreign_type_metadata( debug!("foreign_type_metadata: {:?}", t); let name = compute_debuginfo_type_name(cx.tcx, t, false); - create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA) + create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) } fn pointer_type_metadata( @@ -1161,8 +1161,14 @@ fn prepare_struct_metadata( let containing_scope = get_namespace_for_item(cx, struct_def_id); - let struct_metadata_stub = - create_struct_stub(cx, struct_type, &struct_name, unique_type_id, Some(containing_scope)); + let struct_metadata_stub = create_struct_stub( + cx, + struct_type, + &struct_name, + unique_type_id, + Some(containing_scope), + DIFlags::FlagZero, + ); create_and_register_recursive_type_forward_declaration( cx, @@ -1218,8 +1224,14 @@ fn prepare_tuple_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); - let struct_stub = - create_struct_stub(cx, tuple_type, &tuple_name[..], unique_type_id, containing_scope); + let struct_stub = create_struct_stub( + cx, + tuple_type, + &tuple_name[..], + unique_type_id, + containing_scope, + DIFlags::FlagZero, + ); create_and_register_recursive_type_forward_declaration( cx, @@ -1390,6 +1402,10 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } else { type_metadata(cx, self.enum_type, self.span) }; + let flags = match self.enum_type.kind { + ty::Generator(..) => DIFlags::FlagArtificial, + _ => DIFlags::FlagZero, + }; match self.layout.variants { Variants::Single { index } => { @@ -1423,7 +1439,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: None, source_info: variant_info.source_info(cx), }] @@ -1477,7 +1493,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: Some( self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val as u64, @@ -1560,7 +1576,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: variant.size, align: variant.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: None, source_info: variant_info.source_info(cx), }] @@ -1610,7 +1626,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: niche_value, source_info: variant_info.source_info(cx), } @@ -1743,6 +1759,14 @@ impl<'tcx> VariantInfo<'_, 'tcx> { } None } + + #[allow(dead_code)] + fn is_artificial(&self) -> bool { + match self { + VariantInfo::Generator { .. } => true, + VariantInfo::Adt(..) => false, + } + } } /// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a @@ -1762,7 +1786,15 @@ fn describe_enum_variant( .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)) + create_struct_stub( + cx, + layout.ty, + &variant_name, + unique_type_id, + Some(containing_scope), + // FIXME(tmandry): This doesn't seem to have any effect. + if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero }, + ) }); // Build an array of (field name, field type) pairs to be captured in the factory closure. @@ -1824,6 +1856,11 @@ fn prepare_enum_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let tcx = cx.tcx; let enum_name = compute_debuginfo_type_name(tcx, enum_type, false); + // FIXME(tmandry): This doesn't seem to have any effect. + let enum_flags = match enum_type.kind { + ty::Generator(..) => DIFlags::FlagArtificial, + _ => DIFlags::FlagZero, + }; let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we @@ -1958,7 +1995,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, None, 0, // RuntimeLang unique_type_id_str.as_ptr().cast(), @@ -2079,7 +2116,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, discriminator_metadata, empty_array, variant_part_unique_type_id_str.as_ptr().cast(), @@ -2105,7 +2142,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, None, type_array, 0, @@ -2156,6 +2193,7 @@ fn composite_type_metadata( composite_type_name, composite_type_unique_id, containing_scope, + DIFlags::FlagZero, ); // ... and immediately create and add the member descriptions. set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions); @@ -2257,6 +2295,7 @@ fn create_struct_stub( struct_type_name: &str, unique_type_id: UniqueTypeId, containing_scope: Option<&'ll DIScope>, + flags: DIFlags, ) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); @@ -2278,7 +2317,7 @@ fn create_struct_stub( UNKNOWN_LINE_NUMBER, struct_size.bits(), struct_align.bits() as u32, - DIFlags::FlagZero, + flags, None, empty_array, 0, From 367858aedc1e1dbee5560676c00618a386ed8e37 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 18 Jun 2020 16:17:25 -0700 Subject: [PATCH 3/9] Add test for generator debuginfo --- src/test/codegen/generator-debug.rs | 94 +++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/test/codegen/generator-debug.rs diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs new file mode 100644 index 0000000000000..3007099393ffe --- /dev/null +++ b/src/test/codegen/generator-debug.rs @@ -0,0 +1,94 @@ +// Verify debuginfo for generators: +// - Each variant points to the file and line of its yield point +// - The generator types and variants are marked artificial +// - Captured vars from the source are not marked artificial +// +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 + +#![feature(generators, generator_trait)] +use std::ops::Generator; + +fn generator_test() -> impl Generator { + || { + yield 0; + let s = String::from("foo"); + yield 1; + } +} + +async fn foo() {} +async fn async_fn_test() { + foo().await; + let s = String::from("foo"); + foo().await; +} + +// FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file +// metadata, even when -C codegen-units=1. +// CHECK: [[FILE:!.*]] = !DIFile(filename: "{{.*}}/generator-debug.rs", {{.*}}, checksum: + +// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[FN]] = !DINamespace(name: "generator_test" +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK-SAME: discriminator: [[DISC:![0-9]*]] +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 13, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 16, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial + +// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[FN]] = !DINamespace(name: "async_fn_test" +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK-SAME: discriminator: [[DISC:![0-9]*]] +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 21, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 22, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 24, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial + +fn main() { + let _dummy = generator_test(); + let _dummy = async_fn_test(); +} From 242a5cd4c673c02d817fb5cbadd5bd3ff08f10eb Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 19 Jun 2020 18:37:52 -0700 Subject: [PATCH 4/9] Allow calling GeneratorSubsts::variant_name() without substs --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 14 ++++++-------- src/librustc_codegen_llvm/type_of.rs | 4 ++-- src/librustc_middle/ty/sty.rs | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f26c45e90110a..0338aff509658 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -33,9 +33,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::truncate; use rustc_middle::mir::{self, Field, GeneratorLayout}; use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout}; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; @@ -1381,12 +1381,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let variant_info_for = |index: VariantIdx| match self.enum_type.kind { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), - ty::Generator(def_id, substs, _) => { + ty::Generator(def_id, _, _) => { let (generator_layout, generator_saved_local_names) = generator_variant_info_data.as_ref().unwrap(); VariantInfo::Generator { def_id, - substs, generator_layout: *generator_layout, generator_saved_local_names, variant_index: index, @@ -1693,7 +1692,6 @@ enum VariantInfo<'a, 'tcx> { Adt(&'tcx ty::VariantDef), Generator { def_id: DefId, - substs: SubstsRef<'tcx>, generator_layout: &'tcx GeneratorLayout<'tcx>, generator_saved_local_names: &'a IndexVec>, variant_index: VariantIdx, @@ -1704,8 +1702,8 @@ impl<'tcx> VariantInfo<'_, 'tcx> { fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), - VariantInfo::Generator { substs, variant_index, .. } => { - f(&substs.as_generator().variant_name(*variant_index)) + VariantInfo::Generator { variant_index, .. } => { + f(&GeneratorSubsts::variant_name(*variant_index)) } } } @@ -1900,7 +1898,7 @@ fn prepare_enum_metadata( .variant_range(enum_def_id, tcx) .map(|variant_index| { debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx)); - let name = substs.as_generator().variant_name(variant_index); + let name = GeneratorSubsts::variant_name(variant_index); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 77009aca6d32e..5a0da6be5980e 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -70,10 +70,10 @@ fn uncached_llvm_type<'a, 'tcx>( write!(&mut name, "::{}", def.variants[index].ident).unwrap(); } } - if let (&ty::Generator(_, substs, _), &Variants::Single { index }) + if let (&ty::Generator(_, _, _), &Variants::Single { index }) = (&layout.ty.kind, &layout.variants) { - write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap(); + write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap(); } Some(name) } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 1d680c3563675..79fa06790bd4a 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -523,7 +523,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. #[inline] - pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> { + pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), From 547d86307c6acd10520af96f8e2974522c50ac1e Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 19 Jun 2020 20:19:19 -0700 Subject: [PATCH 5/9] Improve GeneratorLayout debug output --- src/librustc_index/bit_set.rs | 18 +++++- src/librustc_middle/mir/query.rs | 60 ++++++++++++++++++- src/librustc_middle/ty/sty.rs | 1 - src/librustc_mir/util/pretty.rs | 2 +- ...ustc.main-{{closure}}.generator_drop.0.mir | 15 ++++- ...tc.main-{{closure}}.generator_resume.0.mir | 15 ++++- 6 files changed, 105 insertions(+), 6 deletions(-) diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index 46c38840516e2..cb8b30830c5de 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -700,7 +700,7 @@ impl GrowableBitSet { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)] +#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitMatrix { num_rows: usize, num_columns: usize, @@ -876,6 +876,22 @@ impl BitMatrix { } } +impl fmt::Debug for BitMatrix { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl fmt::Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + write!(fmt, "BitMatrix({}x{}) ", self.num_rows, self.num_columns)?; + let items = self.rows().flat_map(|r| self.iter(r).map(move |c| (r, c))); + fmt.debug_set().entries(items.map(OneLinePrinter)).finish() + } +} + /// A fixed-column-size, variable-row-size 2D bit matrix with a moderately /// sparse representation. /// diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index b77b069befd00..9ad79230a4f6d 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -10,6 +10,8 @@ use rustc_index::vec::IndexVec; use rustc_span::{Span, Symbol}; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; +use std::cell::Cell; +use std::fmt::{self, Debug}; use super::{Field, SourceInfo}; @@ -58,7 +60,7 @@ rustc_index::newtype_index! { } /// The layout of generator state. -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec>, @@ -77,6 +79,62 @@ pub struct GeneratorLayout<'tcx> { pub storage_conflicts: BitMatrix, } +impl Debug for GeneratorLayout<'_> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Prints an iterator of (key, value) tuples as a map. + struct MapPrinter<'a, K, V>(Cell + 'a>>>); + impl<'a, K, V> MapPrinter<'a, K, V> { + fn new(iter: impl Iterator + 'a) -> Self { + Self(Cell::new(Some(Box::new(iter)))) + } + } + impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().entries(self.0.take().unwrap()).finish() + } + } + + /// Prints the generator variant name. + struct GenVariantPrinter(VariantIdx); + impl From for GenVariantPrinter { + fn from(idx: VariantIdx) -> Self { + GenVariantPrinter(idx) + } + } + impl Debug for GenVariantPrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let variant_name = ty::GeneratorSubsts::variant_name(self.0); + if fmt.alternate() { + write!(fmt, "{:9}({:?})", variant_name, self.0) + } else { + write!(fmt, "{}", variant_name) + } + } + } + + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + fmt.debug_struct("GeneratorLayout") + .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) + .field( + "variant_fields", + &MapPrinter::new( + self.variant_fields + .iter_enumerated() + .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), + ), + ) + .field("storage_conflicts", &self.storage_conflicts) + .finish() + } +} + #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 79fa06790bd4a..8f86d2ef522d3 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -522,7 +522,6 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. - #[inline] pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 02614044063fc..db45481e4fd25 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -131,7 +131,7 @@ fn dump_matched_mir_node<'tcx, F>( } writeln!(file, " {} {}", disambiguator, pass_name)?; if let Some(ref layout) = body.generator_layout { - writeln!(file, "// generator_layout = {:?}", layout)?; + writeln!(file, "/* generator_layout = {:#?} */", layout)?; } writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; diff --git a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir index b34d42155cc6c..3c77995eea893 100644 --- a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir +++ b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_drop -// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-drop-cleanup.rs:10:15: 10:15 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:12:9: 12:14 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: std::string::String, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {std::string::String, ()}]) -> () { let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 diff --git a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir index 2398e9501452e..bd6db11a7e73e 100644 --- a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir +++ b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_resume -// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-tiny.rs:19:16: 19:16 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:22:13: 22:18 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: HasDrop, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> std::ops::GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 From 477ecc51caea03c22eb6c7dedcf5656593b71fb0 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 23 Jun 2020 16:21:53 -0700 Subject: [PATCH 6/9] Generalize generator-debug test a bit Don't be so reliant on particular line ordering (though FileCheck makes this hard in general, IMO). Also disable for MSVC. --- src/test/codegen/generator-debug.rs | 40 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 3007099393ffe..fa16a460dde4d 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -5,6 +5,7 @@ // // ignore-tidy-linelength // compile-flags: -C debuginfo=2 --edition=2018 +// ignore-msvc #![feature(generators, generator_trait)] use std::ops::Generator; @@ -26,66 +27,63 @@ async fn async_fn_test() { // FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file // metadata, even when -C codegen-units=1. -// CHECK: [[FILE:!.*]] = !DIFile(filename: "{{.*}}/generator-debug.rs", {{.*}}, checksum: +// CHECK-DAG: [[FILE:!.*]] = !DIFile(filename: "{{.*}}generator-debug.rs", {{.*}}, checksum: -// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: [[FN]] = !DINamespace(name: "generator_test" -// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]], // CHECK-SAME: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 13, +// CHECK-SAME: file: [[FILE]], line: 14, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: file: [[FILE]], line: 18, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: file: [[FILE]], line: 18, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE]], line: 15, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 16, +// CHECK-SAME: file: [[FILE]], line: 17, // CHECK-SAME: flags: DIFlagArtificial // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[GEN_FN]], // CHECK-SAME: flags: DIFlagArtificial -// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: [[FN]] = !DINamespace(name: "async_fn_test" -// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN:![0-9]*]], {{.*}}flags: DIFlagArtificial +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], // CHECK-SAME: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 21, +// CHECK-SAME: file: [[FILE]], line: 22, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: file: [[FILE]], line: 26, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: file: [[FILE]], line: 26, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 22, +// CHECK-SAME: file: [[FILE]], line: 23, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 24, +// CHECK-SAME: file: [[FILE]], line: 25, // CHECK-SAME: flags: DIFlagArtificial // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[ASYNC_FN]], // CHECK-SAME: flags: DIFlagArtificial fn main() { From 2d652d9d735f10402803318351f7a8ee91fc4c47 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 23 Jun 2020 16:23:01 -0700 Subject: [PATCH 7/9] Add generator-debug test for MSVC ..which doesn't use variant types. --- .../debuginfo/metadata.rs | 18 ++-- src/test/codegen/generator-debug-msvc.rs | 88 +++++++++++++++++++ 2 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/test/codegen/generator-debug-msvc.rs diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0338aff509658..33351c06d27ee 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1652,23 +1652,25 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { .iter() .enumerate() .map(|(i, &(ref name, ty))| { + // Discriminant is always the first field of our variant + // when using the enum fallback. + let is_artificial_discr = use_enum_fallback(cx) && i == 0; let (size, align) = cx.size_and_align_of(ty); MemberDescription { name: name.to_string(), - type_metadata: if use_enum_fallback(cx) { - match self.tag_type_metadata { - // Discriminant is always the first field of our variant - // when using the enum fallback. - Some(metadata) if i == 0 => metadata, - _ => type_metadata(cx, ty, self.span), - } + type_metadata: if is_artificial_discr { + self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span)) } else { type_metadata(cx, ty, self.span) }, offset: self.offsets[i], size, align, - flags: DIFlags::FlagZero, + flags: if is_artificial_discr { + DIFlags::FlagArtificial + } else { + DIFlags::FlagZero + }, discriminant: None, source_info: None, } diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs new file mode 100644 index 0000000000000..ebd0c7ba544b0 --- /dev/null +++ b/src/test/codegen/generator-debug-msvc.rs @@ -0,0 +1,88 @@ +// Verify debuginfo for generators: +// - Each variant points to the file and line of its yield point +// - The generator types and variants are marked artificial +// - Captured vars from the source are not marked artificial +// +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 +// only-msvc + +#![feature(generators, generator_trait)] +use std::ops::Generator; + +fn generator_test() -> impl Generator { + || { + yield 0; + let s = String::from("foo"); + yield 1; + } +} + +async fn foo() {} +async fn async_fn_test() { + foo().await; + let s = String::from("foo"); + foo().await; +} + +// FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file +// metadata, even when -C codegen-units=1. +// CHECK-DAG: [[FILE:!.*]] = !DIFile(filename: "{{.*}}generator-debug-msvc.rs", {{.*}}, checksum: + +// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// For brevity, we just check the struct name and members of the last variant. +// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) + +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN:![0-9]*]], {{.*}}flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// For brevity, we just check the struct name and members of the last variant. +// CHECK-SAME: file: [[FILE]], line: 22, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 26, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 26, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 23, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) + +fn main() { + let _dummy = generator_test(); + let _dummy = async_fn_test(); +} From fe3df646fe415123d0a6bd09df698dc69074263a Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 23 Jun 2020 20:19:26 -0700 Subject: [PATCH 8/9] Give up on checking filename --- src/test/codegen/generator-debug-msvc.rs | 6 ++---- src/test/codegen/generator-debug.rs | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index ebd0c7ba544b0..705fa5187292c 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -25,15 +25,13 @@ async fn async_fn_test() { foo().await; } -// FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file -// metadata, even when -C codegen-units=1. -// CHECK-DAG: [[FILE:!.*]] = !DIFile(filename: "{{.*}}generator-debug-msvc.rs", {{.*}}, checksum: +// FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" // CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // For brevity, we just check the struct name and members of the last variant. -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 18, diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index fa16a460dde4d..4de57c644e8ca 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -25,9 +25,7 @@ async fn async_fn_test() { foo().await; } -// FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file -// metadata, even when -C codegen-units=1. -// CHECK-DAG: [[FILE:!.*]] = !DIFile(filename: "{{.*}}generator-debug.rs", {{.*}}, checksum: +// FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" // CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial @@ -35,7 +33,7 @@ async fn async_fn_test() { // CHECK-SAME: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-SAME: flags: DIFlagArtificial From 887fbd9d3411ea7def2cc7a508d74bea6b7f19bb Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 24 Jun 2020 14:17:31 -0700 Subject: [PATCH 9/9] Split out async fn and generator test This keeps FileCheck from tripping over unimportant differences in codegen. --- src/test/codegen/async-fn-debug-msvc.rs | 48 ++++++++++++++++++++++ src/test/codegen/async-fn-debug.rs | 51 ++++++++++++++++++++++++ src/test/codegen/generator-debug-msvc.rs | 40 ++----------------- src/test/codegen/generator-debug.rs | 35 ---------------- 4 files changed, 102 insertions(+), 72 deletions(-) create mode 100644 src/test/codegen/async-fn-debug-msvc.rs create mode 100644 src/test/codegen/async-fn-debug.rs diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs new file mode 100644 index 0000000000000..4e145b81ecbf7 --- /dev/null +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -0,0 +1,48 @@ +// Verify debuginfo for generators: +// - Each variant points to the file and line of its yield point +// - The generator types and variants are marked artificial +// - Captured vars from the source are not marked artificial +// +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 +// only-msvc + +async fn foo() {} +async fn async_fn_test() { + foo().await; + let s = String::from("foo"); + foo().await; +} + +// FIXME: No way to reliably check the filename. + +// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// For brevity, we only check the struct name and members of the last variant. +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) + +fn main() { + let _dummy = async_fn_test(); +} diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs new file mode 100644 index 0000000000000..8fa4be1ae86d8 --- /dev/null +++ b/src/test/codegen/async-fn-debug.rs @@ -0,0 +1,51 @@ +// Verify debuginfo for async fn: +// - Each variant points to the file and line of its yield point +// - The generator types and variants are marked artificial +// - Captured vars from the source are not marked artificial +// +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 +// ignore-msvc + +async fn foo() {} +async fn async_fn_test() { + foo().await; + let s = String::from("foo"); + foo().await; +} + +// FIXME: No way to reliably check the filename. + +// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK-SAME: discriminator: [[DISC:![0-9]*]] +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[ASYNC_FN]], +// CHECK-SAME: flags: DIFlagArtificial + +fn main() { + let _dummy = async_fn_test(); +} diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 705fa5187292c..82a1568ea9584 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -4,7 +4,7 @@ // - Captured vars from the source are not marked artificial // // ignore-tidy-linelength -// compile-flags: -C debuginfo=2 --edition=2018 +// compile-flags: -C debuginfo=2 // only-msvc #![feature(generators, generator_trait)] @@ -18,19 +18,12 @@ fn generator_test() -> impl Generator { } } -async fn foo() {} -async fn async_fn_test() { - foo().await; - let s = String::from("foo"); - foo().await; -} - // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// For brevity, we just 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: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], @@ -54,33 +47,6 @@ async fn async_fn_test() { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN:![0-9]*]], {{.*}}flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// For brevity, we just check the struct name and members of the last variant. -// CHECK-SAME: file: [[FILE]], line: 22, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 26, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 26, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 23, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 25, -// CHECK-SAME: baseType: [[VARIANT:![0-9]*]] -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] -// CHECK-NOT: flags: DIFlagArtificial -// CHECK-SAME: ) - fn main() { let _dummy = generator_test(); - let _dummy = async_fn_test(); } diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 4de57c644e8ca..5c7c64148189a 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -18,13 +18,6 @@ fn generator_test() -> impl Generator { } } -async fn foo() {} -async fn async_fn_test() { - foo().await; - let s = String::from("foo"); - foo().await; -} - // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" @@ -57,34 +50,6 @@ async fn async_fn_test() { // CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[GEN_FN]], // CHECK-SAME: flags: DIFlagArtificial -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN:![0-9]*]], {{.*}}flags: DIFlagArtificial -// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK-SAME: discriminator: [[DISC:![0-9]*]] -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 22, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 26, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 26, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 23, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 25, -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], -// CHECK-SAME: flags: DIFlagArtificial -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] -// CHECK-NOT: flags: DIFlagArtificial -// CHECK-SAME: ) -// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[ASYNC_FN]], -// CHECK-SAME: flags: DIFlagArtificial - fn main() { let _dummy = generator_test(); - let _dummy = async_fn_test(); }