Skip to content

Commit 1c34357

Browse files
committed
Emit line info for generator variants
1 parent a647c0c commit 1c34357

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(discr_index),
15281549
self.layout.field(cx, discr_index).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()
@@ -1648,6 +1673,7 @@ enum EnumDiscriminantInfo<'ll> {
16481673
enum VariantInfo<'a, 'tcx> {
16491674
Adt(&'tcx ty::VariantDef),
16501675
Generator {
1676+
def_id: DefId,
16511677
substs: SubstsRef<'tcx>,
16521678
generator_layout: &'tcx GeneratorLayout<'tcx>,
16531679
generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>,
@@ -1696,6 +1722,24 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
16961722
};
16971723
field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
16981724
}
1725+
1726+
fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
1727+
match self {
1728+
VariantInfo::Generator { def_id, variant_index, .. } => {
1729+
let span =
1730+
cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span;
1731+
if !span.is_dummy() {
1732+
let loc = cx.lookup_debug_loc(span.lo());
1733+
return Some(SourceInfo {
1734+
file: file_metadata(cx, &loc.file, def_id.krate),
1735+
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
1736+
});
1737+
}
1738+
}
1739+
_ => {}
1740+
}
1741+
None
1742+
}
16991743
}
17001744

17011745
/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
@@ -1775,7 +1819,8 @@ fn prepare_enum_metadata(
17751819
span: Span,
17761820
outer_field_tys: Vec<Ty<'tcx>>,
17771821
) -> RecursiveTypeDescription<'ll, 'tcx> {
1778-
let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
1822+
let tcx = cx.tcx;
1823+
let enum_name = compute_debuginfo_type_name(tcx, enum_type, false);
17791824

17801825
let containing_scope = get_namespace_for_item(cx, enum_def_id);
17811826
// FIXME: This should emit actual file metadata for the enum, but we
@@ -1789,7 +1834,7 @@ fn prepare_enum_metadata(
17891834
let discriminant_type_metadata = |discr: Primitive| {
17901835
let enumerators_metadata: Vec<_> = match enum_type.kind {
17911836
ty::Adt(def, _) => def
1792-
.discriminants(cx.tcx)
1837+
.discriminants(tcx)
17931838
.zip(&def.variants)
17941839
.map(|((_, discr), v)| {
17951840
let name = v.ident.as_str();
@@ -1812,15 +1857,16 @@ fn prepare_enum_metadata(
18121857
.collect(),
18131858
ty::Generator(_, substs, _) => substs
18141859
.as_generator()
1815-
.variant_range(enum_def_id, cx.tcx)
1860+
.variant_range(enum_def_id, tcx)
18161861
.map(|variant_index| {
1862+
debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx));
18171863
let name = substs.as_generator().variant_name(variant_index);
18181864
unsafe {
18191865
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
18201866
DIB(cx),
18211867
name.as_ptr().cast(),
18221868
name.len(),
1823-
// Generators use u32 as discriminant type.
1869+
// Generators use u32 as discriminant type, verified above.
18241870
variant_index.as_u32().into(),
18251871
true, // IsUnsigned
18261872
))
@@ -1838,12 +1884,12 @@ fn prepare_enum_metadata(
18381884
None => {
18391885
let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx));
18401886
let discriminant_base_type_metadata =
1841-
type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
1887+
type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP);
18421888

18431889
let item_name;
18441890
let discriminant_name = match enum_type.kind {
18451891
ty::Adt(..) => {
1846-
item_name = cx.tcx.item_name(enum_def_id).as_str();
1892+
item_name = tcx.item_name(enum_def_id).as_str();
18471893
&*item_name
18481894
}
18491895
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
@@ -426,6 +426,9 @@ struct LivenessInfo {
426426
/// The set of saved locals live at each suspension point.
427427
live_locals_at_suspension_points: Vec<BitSet<GeneratorSavedLocal>>,
428428

429+
/// Parallel vec to the above with SourceInfo for each yield terminator.
430+
source_info_at_suspension_points: Vec<SourceInfo>,
431+
429432
/// For every saved local, the set of other saved locals that are
430433
/// storage-live at the same time as this local. We cannot overlap locals in
431434
/// the layout which have conflicting storage.
@@ -477,6 +480,7 @@ fn locals_live_across_suspend_points(
477480

478481
let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks());
479482
let mut live_locals_at_suspension_points = Vec::new();
483+
let mut source_info_at_suspension_points = Vec::new();
480484
let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len());
481485

482486
for (block, data) in body.basic_blocks().iter_enumerated() {
@@ -522,6 +526,7 @@ fn locals_live_across_suspend_points(
522526
live_locals_at_any_suspension_point.union(&live_locals);
523527

524528
live_locals_at_suspension_points.push(live_locals);
529+
source_info_at_suspension_points.push(data.terminator().source_info);
525530
}
526531
}
527532
debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point);
@@ -543,6 +548,7 @@ fn locals_live_across_suspend_points(
543548
LivenessInfo {
544549
live_locals: live_locals_at_any_suspension_point,
545550
live_locals_at_suspension_points,
551+
source_info_at_suspension_points,
546552
storage_conflicts,
547553
storage_liveness: storage_liveness_map,
548554
}
@@ -740,6 +746,7 @@ fn compute_layout<'tcx>(
740746
let LivenessInfo {
741747
live_locals,
742748
live_locals_at_suspension_points,
749+
source_info_at_suspension_points,
743750
storage_conflicts,
744751
storage_liveness,
745752
} = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable);
@@ -756,7 +763,18 @@ fn compute_layout<'tcx>(
756763
}
757764

758765
// Leave empty variants for the UNRESUMED, RETURNED, and POISONED states.
766+
// In debuginfo, these will correspond to the beginning (UNRESUMED) or end
767+
// (RETURNED, POISONED) of the function.
759768
const RESERVED_VARIANTS: usize = 3;
769+
let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span;
770+
let mut variant_source_info: IndexVec<VariantIdx, SourceInfo> = [
771+
SourceInfo::outermost(body_span.shrink_to_lo()),
772+
SourceInfo::outermost(body_span.shrink_to_hi()),
773+
SourceInfo::outermost(body_span.shrink_to_hi()),
774+
]
775+
.iter()
776+
.copied()
777+
.collect();
760778

761779
// Build the generator variant field list.
762780
// Create a map from local indices to generator struct indices.
@@ -775,11 +793,13 @@ fn compute_layout<'tcx>(
775793
remap.entry(locals[saved_local]).or_insert((tys[saved_local], variant_index, idx));
776794
}
777795
variant_fields.push(fields);
796+
variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]);
778797
}
779798
debug!("generator variant_fields = {:?}", variant_fields);
780799
debug!("generator storage_conflicts = {:#?}", storage_conflicts);
781800

782-
let layout = GeneratorLayout { field_tys: tys, variant_fields, storage_conflicts };
801+
let layout =
802+
GeneratorLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts };
783803

784804
(remap, layout, storage_liveness)
785805
}

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)