Skip to content

Commit a5a831f

Browse files
committed
Emit line info for generator variants
1 parent d8ed1b0 commit a5a831f

File tree

5 files changed

+83
-13
lines changed

5 files changed

+83
-13
lines changed

src/librustc_codegen_llvm/debuginfo/metadata.rs

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ fn vec_slice_metadata(
392392
align: pointer_align,
393393
flags: DIFlags::FlagZero,
394394
discriminant: None,
395+
source_info: None,
395396
},
396397
MemberDescription {
397398
name: "length".to_owned(),
@@ -401,6 +402,7 @@ fn vec_slice_metadata(
401402
align: usize_align,
402403
flags: DIFlags::FlagZero,
403404
discriminant: None,
405+
source_info: None,
404406
},
405407
];
406408

@@ -508,6 +510,7 @@ fn trait_pointer_metadata(
508510
align: data_ptr_field.align.abi,
509511
flags: DIFlags::FlagArtificial,
510512
discriminant: None,
513+
source_info: None,
511514
},
512515
MemberDescription {
513516
name: "vtable".to_owned(),
@@ -517,6 +520,7 @@ fn trait_pointer_metadata(
517520
align: vtable_field.align.abi,
518521
flags: DIFlags::FlagArtificial,
519522
discriminant: None,
523+
source_info: None,
520524
},
521525
];
522526

@@ -1026,6 +1030,12 @@ impl MetadataCreationResult<'ll> {
10261030
}
10271031
}
10281032

1033+
#[derive(Debug)]
1034+
struct SourceInfo<'ll> {
1035+
file: &'ll DIFile,
1036+
line: u32,
1037+
}
1038+
10291039
/// Description of a type member, which can either be a regular field (as in
10301040
/// structs or tuples) or an enum variant.
10311041
#[derive(Debug)]
@@ -1037,6 +1047,7 @@ struct MemberDescription<'ll> {
10371047
align: Align,
10381048
flags: DIFlags,
10391049
discriminant: Option<u64>,
1050+
source_info: Option<SourceInfo<'ll>>,
10401051
}
10411052

10421053
impl<'ll> MemberDescription<'ll> {
@@ -1045,14 +1056,18 @@ impl<'ll> MemberDescription<'ll> {
10451056
cx: &CodegenCx<'ll, '_>,
10461057
composite_type_metadata: &'ll DIScope,
10471058
) -> &'ll DIType {
1059+
let (file, line) = self
1060+
.source_info
1061+
.map(|info| (info.file, info.line))
1062+
.unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
10481063
unsafe {
10491064
llvm::LLVMRustDIBuilderCreateVariantMemberType(
10501065
DIB(cx),
10511066
composite_type_metadata,
10521067
self.name.as_ptr().cast(),
10531068
self.name.len(),
1054-
unknown_file_metadata(cx),
1055-
UNKNOWN_LINE_NUMBER,
1069+
file,
1070+
line,
10561071
self.size.bits(),
10571072
self.align.bits() as u32,
10581073
self.offset.bits(),
@@ -1124,6 +1139,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
11241139
align: field.align.abi,
11251140
flags: DIFlags::FlagZero,
11261141
discriminant: None,
1142+
source_info: None,
11271143
}
11281144
})
11291145
.collect()
@@ -1185,6 +1201,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
11851201
align,
11861202
flags: DIFlags::FlagZero,
11871203
discriminant: None,
1204+
source_info: None,
11881205
}
11891206
})
11901207
.collect()
@@ -1244,6 +1261,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
12441261
align: field.align.abi,
12451262
flags: DIFlags::FlagZero,
12461263
discriminant: None,
1264+
source_info: None,
12471265
}
12481266
})
12491267
.collect()
@@ -1351,10 +1369,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
13511369

13521370
let variant_info_for = |index: VariantIdx| match self.enum_type.kind {
13531371
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
1354-
ty::Generator(_, substs, _) => {
1372+
ty::Generator(def_id, substs, _) => {
13551373
let (generator_layout, generator_saved_local_names) =
13561374
generator_variant_info_data.as_ref().unwrap();
13571375
VariantInfo::Generator {
1376+
def_id,
13581377
substs,
13591378
generator_layout: *generator_layout,
13601379
generator_saved_local_names,
@@ -1406,6 +1425,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
14061425
align: self.layout.align.abi,
14071426
flags: DIFlags::FlagZero,
14081427
discriminant: None,
1428+
source_info: variant_info.source_info(cx),
14091429
}]
14101430
}
14111431
Variants::Multiple {
@@ -1462,6 +1482,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
14621482
self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val
14631483
as u64,
14641484
),
1485+
source_info: variant_info.source_info(cx),
14651486
}
14661487
})
14671488
.collect()
@@ -1527,7 +1548,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15271548
self.layout.fields.offset(tag_field),
15281549
self.layout.field(cx, tag_field).size,
15291550
);
1530-
variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| {
1551+
let variant_info = variant_info_for(*niche_variants.start());
1552+
variant_info.map_struct_name(|variant_name| {
15311553
name.push_str(variant_name);
15321554
});
15331555

@@ -1540,6 +1562,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15401562
align: variant.align.abi,
15411563
flags: DIFlags::FlagZero,
15421564
discriminant: None,
1565+
source_info: variant_info.source_info(cx),
15431566
}]
15441567
} else {
15451568
variants
@@ -1589,6 +1612,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
15891612
align: self.layout.align.abi,
15901613
flags: DIFlags::FlagZero,
15911614
discriminant: niche_value,
1615+
source_info: variant_info.source_info(cx),
15921616
}
15931617
})
15941618
.collect()
@@ -1631,6 +1655,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
16311655
align,
16321656
flags: DIFlags::FlagZero,
16331657
discriminant: None,
1658+
source_info: None,
16341659
}
16351660
})
16361661
.collect()
@@ -1651,6 +1676,7 @@ enum EnumTagInfo<'ll> {
16511676
enum VariantInfo<'a, 'tcx> {
16521677
Adt(&'tcx ty::VariantDef),
16531678
Generator {
1679+
def_id: DefId,
16541680
substs: SubstsRef<'tcx>,
16551681
generator_layout: &'tcx GeneratorLayout<'tcx>,
16561682
generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>,
@@ -1699,6 +1725,24 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
16991725
};
17001726
field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
17011727
}
1728+
1729+
fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
1730+
match self {
1731+
VariantInfo::Generator { def_id, variant_index, .. } => {
1732+
let span =
1733+
cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span;
1734+
if !span.is_dummy() {
1735+
let loc = cx.lookup_debug_loc(span.lo());
1736+
return Some(SourceInfo {
1737+
file: file_metadata(cx, &loc.file, def_id.krate),
1738+
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
1739+
});
1740+
}
1741+
}
1742+
_ => {}
1743+
}
1744+
None
1745+
}
17021746
}
17031747

17041748
/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
@@ -1778,7 +1822,8 @@ fn prepare_enum_metadata(
17781822
span: Span,
17791823
outer_field_tys: Vec<Ty<'tcx>>,
17801824
) -> RecursiveTypeDescription<'ll, 'tcx> {
1781-
let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
1825+
let tcx = cx.tcx;
1826+
let enum_name = compute_debuginfo_type_name(tcx, enum_type, false);
17821827

17831828
let containing_scope = get_namespace_for_item(cx, enum_def_id);
17841829
// FIXME: This should emit actual file metadata for the enum, but we
@@ -1792,7 +1837,7 @@ fn prepare_enum_metadata(
17921837
let discriminant_type_metadata = |discr: Primitive| {
17931838
let enumerators_metadata: Vec<_> = match enum_type.kind {
17941839
ty::Adt(def, _) => def
1795-
.discriminants(cx.tcx)
1840+
.discriminants(tcx)
17961841
.zip(&def.variants)
17971842
.map(|((_, discr), v)| {
17981843
let name = v.ident.as_str();
@@ -1815,15 +1860,16 @@ fn prepare_enum_metadata(
18151860
.collect(),
18161861
ty::Generator(_, substs, _) => substs
18171862
.as_generator()
1818-
.variant_range(enum_def_id, cx.tcx)
1863+
.variant_range(enum_def_id, tcx)
18191864
.map(|variant_index| {
1865+
debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx));
18201866
let name = substs.as_generator().variant_name(variant_index);
18211867
unsafe {
18221868
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
18231869
DIB(cx),
18241870
name.as_ptr().cast(),
18251871
name.len(),
1826-
// Generators use u32 as discriminant type.
1872+
// Generators use u32 as discriminant type, verified above.
18271873
variant_index.as_u32().into(),
18281874
true, // IsUnsigned
18291875
))
@@ -1841,12 +1887,12 @@ fn prepare_enum_metadata(
18411887
None => {
18421888
let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx));
18431889
let discriminant_base_type_metadata =
1844-
type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
1890+
type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP);
18451891

18461892
let item_name;
18471893
let discriminant_name = match enum_type.kind {
18481894
ty::Adt(..) => {
1849-
item_name = cx.tcx.item_name(enum_def_id).as_str();
1895+
item_name = tcx.item_name(enum_def_id).as_str();
18501896
&*item_name
18511897
}
18521898
ty::Generator(..) => enum_name.as_str(),

src/librustc_middle/mir/query.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ pub struct GeneratorLayout<'tcx> {
6767
/// be stored in multiple variants.
6868
pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
6969

70+
/// The source that led to each variant being created (usually, a yield or
71+
/// await).
72+
pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
73+
7074
/// Which saved locals are storage-live at the same time. Locals that do not
7175
/// have conflicts with each other are allowed to overlap in the computed
7276
/// layout.

src/librustc_mir/transform/generator.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ struct LivenessInfo {
422422
/// The set of saved locals live at each suspension point.
423423
live_locals_at_suspension_points: Vec<BitSet<GeneratorSavedLocal>>,
424424

425+
/// Parallel vec to the above with SourceInfo for each yield terminator.
426+
source_info_at_suspension_points: Vec<SourceInfo>,
427+
425428
/// For every saved local, the set of other saved locals that are
426429
/// storage-live at the same time as this local. We cannot overlap locals in
427430
/// the layout which have conflicting storage.
@@ -473,6 +476,7 @@ fn locals_live_across_suspend_points(
473476

474477
let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks());
475478
let mut live_locals_at_suspension_points = Vec::new();
479+
let mut source_info_at_suspension_points = Vec::new();
476480
let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len());
477481

478482
for (block, data) in body.basic_blocks().iter_enumerated() {
@@ -518,6 +522,7 @@ fn locals_live_across_suspend_points(
518522
live_locals_at_any_suspension_point.union(&live_locals);
519523

520524
live_locals_at_suspension_points.push(live_locals);
525+
source_info_at_suspension_points.push(data.terminator().source_info);
521526
}
522527
}
523528

@@ -541,6 +546,7 @@ fn locals_live_across_suspend_points(
541546
LivenessInfo {
542547
saved_locals,
543548
live_locals_at_suspension_points,
549+
source_info_at_suspension_points,
544550
storage_conflicts,
545551
storage_liveness: storage_liveness_map,
546552
}
@@ -754,6 +760,7 @@ fn compute_layout<'tcx>(
754760
let LivenessInfo {
755761
saved_locals,
756762
live_locals_at_suspension_points,
763+
source_info_at_suspension_points,
757764
storage_conflicts,
758765
storage_liveness,
759766
} = liveness;
@@ -768,7 +775,18 @@ fn compute_layout<'tcx>(
768775
}
769776

770777
// Leave empty variants for the UNRESUMED, RETURNED, and POISONED states.
778+
// In debuginfo, these will correspond to the beginning (UNRESUMED) or end
779+
// (RETURNED, POISONED) of the function.
771780
const RESERVED_VARIANTS: usize = 3;
781+
let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span;
782+
let mut variant_source_info: IndexVec<VariantIdx, SourceInfo> = [
783+
SourceInfo::outermost(body_span.shrink_to_lo()),
784+
SourceInfo::outermost(body_span.shrink_to_hi()),
785+
SourceInfo::outermost(body_span.shrink_to_hi()),
786+
]
787+
.iter()
788+
.copied()
789+
.collect();
772790

773791
// Build the generator variant field list.
774792
// Create a map from local indices to generator struct indices.
@@ -787,11 +805,13 @@ fn compute_layout<'tcx>(
787805
remap.entry(locals[saved_local]).or_insert((tys[saved_local], variant_index, idx));
788806
}
789807
variant_fields.push(fields);
808+
variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]);
790809
}
791810
debug!("generator variant_fields = {:?}", variant_fields);
792811
debug!("generator storage_conflicts = {:#?}", storage_conflicts);
793812

794-
let layout = GeneratorLayout { field_tys: tys, variant_fields, storage_conflicts };
813+
let layout =
814+
GeneratorLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts };
795815

796816
(remap, layout, storage_liveness)
797817
}

src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// MIR for `main::{{closure}}#0` 0 generator_drop
2-
// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } }
2+
// 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 } }
33

44
fn main::{{closure}}#0(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {std::string::String, ()}]) -> () {
55
let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6

src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// MIR for `main::{{closure}}#0` 0 generator_resume
2-
// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } }
2+
// 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 } }
33

44
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<(), ()> {
55
debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19

0 commit comments

Comments
 (0)