Skip to content

Commit 2553053

Browse files
authored
Rollup merge of #84752 - lrh2000:generator-debuginfo, r=tmandry
Fix debuginfo for generators First, all fields except the discriminant (including `outer_fields`) should be put into structures inside the variant part, which gives an equivalent layout but offers us much better integration with debuggers. Second, artificial flags in generator variants should be removed. - Literally, variants are not artificial. We have `yield` statements, upvars and inner variables in the source code. - Functionally, we don't want debuggers to suppress the variants. It contains the state of the generator, which is useful when debugging. So they shouldn't be marked artificial. - Debuggers may use artificial flags to find the active variant. In this case, marking variants artificial will make debuggers not work properly. Fixes #62572. Fixes #79009. And refer https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Debuginfo.20for.20generators.
2 parents 4198d0a + 5bf989e commit 2553053

File tree

7 files changed

+114
-80
lines changed

7 files changed

+114
-80
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+34-30
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> {
309309
unfinished_type,
310310
member_holding_stub,
311311
member_descriptions,
312+
None,
312313
);
313314
MetadataCreationResult::new(metadata_stub, true)
314315
}
@@ -1459,6 +1460,7 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> {
14591460
layout: TyAndLayout<'tcx>,
14601461
tag_type_metadata: Option<&'ll DIType>,
14611462
containing_scope: &'ll DIScope,
1463+
common_members: Vec<Option<&'ll DIType>>,
14621464
span: Span,
14631465
}
14641466

@@ -1493,10 +1495,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
14931495
} else {
14941496
type_metadata(cx, self.enum_type, self.span)
14951497
};
1496-
let flags = match self.enum_type.kind() {
1497-
ty::Generator(..) => DIFlags::FlagArtificial,
1498-
_ => DIFlags::FlagZero,
1499-
};
15001498

15011499
match self.layout.variants {
15021500
Variants::Single { index } => {
@@ -1523,14 +1521,15 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15231521
self.enum_type,
15241522
variant_type_metadata,
15251523
member_descriptions,
1524+
Some(&self.common_members),
15261525
);
15271526
vec![MemberDescription {
15281527
name: if fallback { String::new() } else { variant_info.variant_name() },
15291528
type_metadata: variant_type_metadata,
15301529
offset: Size::ZERO,
15311530
size: self.layout.size,
15321531
align: self.layout.align.abi,
1533-
flags,
1532+
flags: DIFlags::FlagZero,
15341533
discriminant: None,
15351534
source_info: variant_info.source_info(cx),
15361535
}]
@@ -1572,6 +1571,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15721571
self.enum_type,
15731572
variant_type_metadata,
15741573
member_descriptions,
1574+
Some(&self.common_members),
15751575
);
15761576

15771577
MemberDescription {
@@ -1584,7 +1584,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15841584
offset: Size::ZERO,
15851585
size: self.layout.size,
15861586
align: self.layout.align.abi,
1587-
flags,
1587+
flags: DIFlags::FlagZero,
15881588
discriminant: Some(
15891589
self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val
15901590
as u64,
@@ -1621,6 +1621,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
16211621
self.enum_type,
16221622
variant_type_metadata,
16231623
variant_member_descriptions,
1624+
Some(&self.common_members),
16241625
);
16251626

16261627
// Encode the information about the null variant in the union
@@ -1667,7 +1668,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
16671668
offset: Size::ZERO,
16681669
size: variant.size,
16691670
align: variant.align.abi,
1670-
flags,
1671+
flags: DIFlags::FlagZero,
16711672
discriminant: None,
16721673
source_info: variant_info.source_info(cx),
16731674
}]
@@ -1695,6 +1696,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
16951696
self.enum_type,
16961697
variant_type_metadata,
16971698
member_descriptions,
1699+
Some(&self.common_members),
16981700
);
16991701

17001702
let niche_value = if i == dataful_variant {
@@ -1717,7 +1719,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
17171719
offset: Size::ZERO,
17181720
size: self.layout.size,
17191721
align: self.layout.align.abi,
1720-
flags,
1722+
flags: DIFlags::FlagZero,
17211723
discriminant: niche_value,
17221724
source_info: variant_info.source_info(cx),
17231725
}
@@ -1849,13 +1851,6 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
18491851
}
18501852
None
18511853
}
1852-
1853-
fn is_artificial(&self) -> bool {
1854-
match self {
1855-
VariantInfo::Generator { .. } => true,
1856-
VariantInfo::Adt(..) => false,
1857-
}
1858-
}
18591854
}
18601855

18611856
/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
@@ -1881,8 +1876,7 @@ fn describe_enum_variant(
18811876
&variant_name,
18821877
unique_type_id,
18831878
Some(containing_scope),
1884-
// FIXME(tmandry): This doesn't seem to have any effect.
1885-
if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero },
1879+
DIFlags::FlagZero,
18861880
)
18871881
});
18881882

@@ -1945,11 +1939,6 @@ fn prepare_enum_metadata(
19451939
) -> RecursiveTypeDescription<'ll, 'tcx> {
19461940
let tcx = cx.tcx;
19471941
let enum_name = compute_debuginfo_type_name(tcx, enum_type, false);
1948-
// FIXME(tmandry): This doesn't seem to have any effect.
1949-
let enum_flags = match enum_type.kind() {
1950-
ty::Generator(..) => DIFlags::FlagArtificial,
1951-
_ => DIFlags::FlagZero,
1952-
};
19531942

19541943
let containing_scope = get_namespace_for_item(cx, enum_def_id);
19551944
// FIXME: This should emit actual file metadata for the enum, but we
@@ -2082,7 +2071,7 @@ fn prepare_enum_metadata(
20822071
UNKNOWN_LINE_NUMBER,
20832072
layout.size.bits(),
20842073
layout.align.abi.bits() as u32,
2085-
enum_flags,
2074+
DIFlags::FlagZero,
20862075
None,
20872076
0, // RuntimeLang
20882077
unique_type_id_str.as_ptr().cast(),
@@ -2102,6 +2091,7 @@ fn prepare_enum_metadata(
21022091
layout,
21032092
tag_type_metadata: discriminant_type_metadata,
21042093
containing_scope,
2094+
common_members: vec![],
21052095
span,
21062096
}),
21072097
);
@@ -2171,7 +2161,7 @@ fn prepare_enum_metadata(
21712161
}
21722162
};
21732163

2174-
let mut outer_fields = match layout.variants {
2164+
let outer_fields = match layout.variants {
21752165
Variants::Single { .. } => vec![],
21762166
Variants::Multiple { .. } => {
21772167
let tuple_mdf = TupleMemberDescriptionFactory {
@@ -2203,18 +2193,21 @@ fn prepare_enum_metadata(
22032193
UNKNOWN_LINE_NUMBER,
22042194
layout.size.bits(),
22052195
layout.align.abi.bits() as u32,
2206-
enum_flags,
2196+
DIFlags::FlagZero,
22072197
discriminator_metadata,
22082198
empty_array,
22092199
variant_part_unique_type_id_str.as_ptr().cast(),
22102200
variant_part_unique_type_id_str.len(),
22112201
)
22122202
};
2213-
outer_fields.push(Some(variant_part));
22142203

22152204
let struct_wrapper = {
22162205
// The variant part must be wrapped in a struct according to DWARF.
2217-
let type_array = create_DIArray(DIB(cx), &outer_fields);
2206+
// All fields except the discriminant (including `outer_fields`)
2207+
// should be put into structures inside the variant part, which gives
2208+
// an equivalent layout but offers us much better integration with
2209+
// debuggers.
2210+
let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]);
22182211

22192212
let type_map = debug_context(cx).type_map.borrow();
22202213
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
@@ -2229,7 +2222,7 @@ fn prepare_enum_metadata(
22292222
UNKNOWN_LINE_NUMBER,
22302223
layout.size.bits(),
22312224
layout.align.abi.bits() as u32,
2232-
enum_flags,
2225+
DIFlags::FlagZero,
22332226
None,
22342227
type_array,
22352228
0,
@@ -2251,6 +2244,7 @@ fn prepare_enum_metadata(
22512244
layout,
22522245
tag_type_metadata: None,
22532246
containing_scope,
2247+
common_members: outer_fields,
22542248
span,
22552249
}),
22562250
)
@@ -2283,7 +2277,13 @@ fn composite_type_metadata(
22832277
DIFlags::FlagZero,
22842278
);
22852279
// ... and immediately create and add the member descriptions.
2286-
set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions);
2280+
set_members_of_composite_type(
2281+
cx,
2282+
composite_type,
2283+
composite_type_metadata,
2284+
member_descriptions,
2285+
None,
2286+
);
22872287

22882288
composite_type_metadata
22892289
}
@@ -2293,6 +2293,7 @@ fn set_members_of_composite_type(
22932293
composite_type: Ty<'tcx>,
22942294
composite_type_metadata: &'ll DICompositeType,
22952295
member_descriptions: Vec<MemberDescription<'ll>>,
2296+
common_members: Option<&Vec<Option<&'ll DIType>>>,
22962297
) {
22972298
// In some rare cases LLVM metadata uniquing would lead to an existing type
22982299
// description being used instead of a new one created in
@@ -2311,10 +2312,13 @@ fn set_members_of_composite_type(
23112312
}
23122313
}
23132314

2314-
let member_metadata: Vec<_> = member_descriptions
2315+
let mut member_metadata: Vec<_> = member_descriptions
23152316
.into_iter()
23162317
.map(|desc| Some(desc.into_metadata(cx, composite_type_metadata)))
23172318
.collect();
2319+
if let Some(other_members) = common_members {
2320+
member_metadata.extend(other_members.iter());
2321+
}
23182322

23192323
let type_params = compute_type_parameters(cx, composite_type);
23202324
unsafe {

src/test/codegen/async-fn-debug-msvc.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Verify debuginfo for generators:
22
// - Each variant points to the file and line of its yield point
3-
// - The generator types and variants are marked artificial
4-
// - Captured vars from the source are not marked artificial
3+
// - The discriminants are marked artificial
4+
// - Other fields are not marked artificial
55
//
66
//
77
// compile-flags: -C debuginfo=2 --edition=2018
@@ -17,26 +17,32 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]]
2121
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
2222
// For brevity, we only check the struct name and members of the last variant.
2323
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
24-
// CHECK-SAME: flags: DIFlagArtificial
24+
// CHECK-NOT: flags: DIFlagArtificial
25+
// CHECK-SAME: )
2526
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
2627
// CHECK-SAME: file: [[FILE]], line: 15,
27-
// CHECK-SAME: flags: DIFlagArtificial
28+
// CHECK-NOT: flags: DIFlagArtificial
29+
// CHECK-SAME: )
2830
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
2931
// CHECK-SAME: file: [[FILE]], line: 15,
30-
// CHECK-SAME: flags: DIFlagArtificial
32+
// CHECK-NOT: flags: DIFlagArtificial
33+
// CHECK-SAME: )
3134
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3235
// CHECK-SAME: file: [[FILE]], line: 12,
33-
// CHECK-SAME: flags: DIFlagArtificial
36+
// CHECK-NOT: flags: DIFlagArtificial
37+
// CHECK-SAME: )
3438
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3539
// CHECK-SAME: file: [[FILE]], line: 14,
3640
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
37-
// CHECK-SAME: flags: DIFlagArtificial
41+
// CHECK-NOT: flags: DIFlagArtificial
42+
// CHECK-SAME: )
3843
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]],
39-
// CHECK-SAME: flags: DIFlagArtificial
44+
// CHECK-NOT: flags: DIFlagArtificial
45+
// CHECK-SAME: )
4046
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
4147
// CHECK-SAME: flags: DIFlagArtificial
4248
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]

src/test/codegen/async-fn-debug.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Verify debuginfo for async fn:
22
// - Each variant points to the file and line of its yield point
3-
// - The generator types and variants are marked artificial
4-
// - Captured vars from the source are not marked artificial
3+
// - The discriminants are marked artificial
4+
// - Other fields are not marked artificial
55
//
66
//
77
// compile-flags: -C debuginfo=2 --edition=2018
@@ -17,29 +17,36 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]]
2121
// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
22-
// CHECK-SAME: flags: DIFlagArtificial
22+
// CHECK-NOT: flags: DIFlagArtificial
2323
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
2424
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]],
2525
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
26-
// CHECK-SAME: flags: DIFlagArtificial
26+
// CHECK-NOT: flags: DIFlagArtificial
27+
// CHECK-SAME: )
2728
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]],
28-
// CHECK-SAME: flags: DIFlagArtificial
29+
// CHECK-NOT: flags: DIFlagArtificial
30+
// CHECK-SAME: )
2931
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]],
3032
// CHECK-SAME: file: [[FILE]], line: 15,
31-
// CHECK-SAME: flags: DIFlagArtificial
33+
// CHECK-NOT: flags: DIFlagArtificial
34+
// CHECK-SAME: )
3235
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]],
3336
// CHECK-SAME: file: [[FILE]], line: 15,
34-
// CHECK-SAME: flags: DIFlagArtificial
37+
// CHECK-NOT: flags: DIFlagArtificial
38+
// CHECK-SAME: )
3539
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
3640
// CHECK-SAME: file: [[FILE]], line: 12,
37-
// CHECK-SAME: flags: DIFlagArtificial
41+
// CHECK-NOT: flags: DIFlagArtificial
42+
// CHECK-SAME: )
3843
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
3944
// CHECK-SAME: file: [[FILE]], line: 14,
40-
// CHECK-SAME: flags: DIFlagArtificial
45+
// CHECK-NOT: flags: DIFlagArtificial
46+
// CHECK-SAME: )
4147
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
42-
// CHECK-SAME: flags: DIFlagArtificial
48+
// CHECK-NOT: flags: DIFlagArtificial
49+
// CHECK-SAME: )
4350
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
4451
// CHECK-NOT: flags: DIFlagArtificial
4552
// CHECK-SAME: )

src/test/codegen/generator-debug-msvc.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Verify debuginfo for generators:
22
// - Each variant points to the file and line of its yield point
3-
// - The generator types and variants are marked artificial
4-
// - Captured vars from the source are not marked artificial
3+
// - The discriminants are marked artificial
4+
// - Other fields are not marked artificial
55
//
66
//
77
// compile-flags: -C debuginfo=2
@@ -21,26 +21,32 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
2121
// FIXME: No way to reliably check the filename.
2222

2323
// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
24-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial
24+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]]
2525
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
2626
// For brevity, we only check the struct name and members of the last variant.
2727
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
28-
// CHECK-SAME: flags: DIFlagArtificial
28+
// CHECK-NOT: flags: DIFlagArtificial
29+
// CHECK-SAME: )
2930
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3031
// CHECK-SAME: file: [[FILE]], line: 18,
31-
// CHECK-SAME: flags: DIFlagArtificial
32+
// CHECK-NOT: flags: DIFlagArtificial
33+
// CHECK-SAME: )
3234
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3335
// CHECK-SAME: file: [[FILE]], line: 18,
34-
// CHECK-SAME: flags: DIFlagArtificial
36+
// CHECK-NOT: flags: DIFlagArtificial
37+
// CHECK-SAME: )
3538
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3639
// CHECK-SAME: file: [[FILE]], line: 15,
37-
// CHECK-SAME: flags: DIFlagArtificial
40+
// CHECK-NOT: flags: DIFlagArtificial
41+
// CHECK-SAME: )
3842
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
3943
// CHECK-SAME: file: [[FILE]], line: 17,
4044
// CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
41-
// CHECK-SAME: flags: DIFlagArtificial
45+
// CHECK-NOT: flags: DIFlagArtificial
46+
// CHECK-SAME: )
4247
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]],
43-
// CHECK-SAME: flags: DIFlagArtificial
48+
// CHECK-NOT: flags: DIFlagArtificial
49+
// CHECK-SAME: )
4450
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
4551
// CHECK-SAME: flags: DIFlagArtificial
4652
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]

0 commit comments

Comments
 (0)