Skip to content

Commit 2ec0071

Browse files
committed
Implement references VarDebugInfo.
1 parent 1c36f50 commit 2ec0071

20 files changed

+439
-361
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
4141

4242
/// `.place.projection` from `mir::VarDebugInfo`.
4343
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
44+
45+
/// `references` from `mir::VarDebugInfo`.
46+
pub references: u8,
4447
}
4548

4649
#[derive(Clone, Copy, Debug)]
@@ -293,6 +296,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
293296
dbg_var,
294297
fragment: None,
295298
projection: ty::List::empty(),
299+
references: 0,
296300
})
297301
}
298302
} else {
@@ -366,14 +370,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
366370
&self,
367371
bx: &mut Bx,
368372
local: mir::Local,
369-
base: PlaceRef<'tcx, Bx::Value>,
373+
mut base: PlaceRef<'tcx, Bx::Value>,
370374
var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
371375
) {
372376
let Some(dbg_var) = var.dbg_var else { return };
373377
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
374378

375-
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
379+
let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
376380
calculate_debuginfo_offset(bx, local, &var, base.layout);
381+
let mut indirect_offsets = &indirect_offsets[..];
377382

378383
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
379384
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -387,28 +392,44 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
387392
// LLVM can handle simple things but anything more complex than just a direct
388393
// offset or one indirect offset of 0 is too complex for it to generate CV records
389394
// correctly.
390-
&& (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
391-
392-
if should_create_individual_allocas {
393-
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
394-
calculate_debuginfo_offset(bx, local, &var, base);
395+
&& (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
395396

397+
let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
396398
// Create a variable which will be a pointer to the actual value
397399
let ptr_ty = bx
398400
.tcx()
399401
.mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
400402
let ptr_layout = bx.layout_of(ptr_ty);
401403
let alloca = PlaceRef::alloca(bx, ptr_layout);
402-
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
404+
bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
403405

404406
// Write the pointer to the variable
405407
bx.store(place.llval, alloca.llval, alloca.align);
406408

407409
// Point the debug info to `*alloca` for the current variable
408-
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
409-
} else {
410-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
410+
alloca
411+
};
412+
413+
if var.references > 0 {
414+
base = calculate_debuginfo_offset(bx, local, &var, base).result;
415+
416+
// Point the debug info to `&...&base == alloca` for the current variable
417+
for refcount in 0..var.references {
418+
base = create_alloca(bx, base, refcount);
419+
}
420+
421+
direct_offset = Size::ZERO;
422+
indirect_offsets = &[];
423+
} else if should_create_individual_allocas {
424+
let place = calculate_debuginfo_offset(bx, local, &var, base).result;
425+
426+
// Point the debug info to `*alloca` for the current variable
427+
base = create_alloca(bx, place, 0);
428+
direct_offset = Size::ZERO;
429+
indirect_offsets = &[Size::ZERO];
411430
}
431+
432+
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
412433
}
413434

414435
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -441,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
441462
};
442463

443464
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
444-
let (var_ty, var_kind) = match var.value {
465+
let (mut var_ty, var_kind) = match var.value {
445466
mir::VarDebugInfoContents::Place(place) => {
446467
let var_ty = self.monomorphized_place_ty(place.as_ref());
447468
let var_kind = if let Some(arg_index) = var.argument_index
@@ -478,6 +499,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
478499
}
479500
};
480501

502+
for _ in 0..var.references {
503+
var_ty =
504+
bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty });
505+
}
506+
481507
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
482508
});
483509

@@ -489,6 +515,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
489515
dbg_var,
490516
fragment: None,
491517
projection: place.projection,
518+
references: var.references,
492519
});
493520
}
494521
mir::VarDebugInfoContents::Const(c) => {
@@ -542,6 +569,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
542569
Some(fragment_start..fragment_start + fragment_layout.size)
543570
},
544571
projection: place.projection,
572+
references: var.references,
545573
});
546574
}
547575
}

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
448448
};
449449
match debuginfo.value {
450450
VarDebugInfoContents::Const(_) => {}
451-
VarDebugInfoContents::Place(place) => check_place(place),
451+
VarDebugInfoContents::Place(place) => {
452+
check_place(place);
453+
if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
454+
self.fail(
455+
START_BLOCK.start_location(),
456+
format!("debuginfo {:?}, has both ref and deref", debuginfo),
457+
);
458+
}
459+
}
452460
VarDebugInfoContents::Composite { ty, ref fragments } => {
453461
for f in fragments {
454462
check_place(f.contents);

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,10 @@ pub struct VarDebugInfo<'tcx> {
11111111
/// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
11121112
/// argument number in the original function before it was inlined.
11131113
pub argument_index: Option<u16>,
1114+
1115+
/// The data represents `name` dereferenced `references` times,
1116+
/// and not the direct value.
1117+
pub references: u8,
11141118
}
11151119

11161120
///////////////////////////////////////////////////////////////////////////
@@ -1639,18 +1643,7 @@ impl<'tcx> Place<'tcx> {
16391643
return self;
16401644
}
16411645

1642-
let mut v: Vec<PlaceElem<'tcx>>;
1643-
1644-
let new_projections = if self.projection.is_empty() {
1645-
more_projections
1646-
} else {
1647-
v = Vec::with_capacity(self.projection.len() + more_projections.len());
1648-
v.extend(self.projection);
1649-
v.extend(more_projections);
1650-
&v
1651-
};
1652-
1653-
Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
1646+
self.as_ref().project_deeper(more_projections, tcx)
16541647
}
16551648
}
16561649

@@ -1721,6 +1714,27 @@ impl<'tcx> PlaceRef<'tcx> {
17211714
(base, *proj)
17221715
})
17231716
}
1717+
1718+
/// Generates a new place by appending `more_projections` to the existing ones
1719+
/// and interning the result.
1720+
pub fn project_deeper(
1721+
self,
1722+
more_projections: &[PlaceElem<'tcx>],
1723+
tcx: TyCtxt<'tcx>,
1724+
) -> Place<'tcx> {
1725+
let mut v: Vec<PlaceElem<'tcx>>;
1726+
1727+
let new_projections = if self.projection.is_empty() {
1728+
more_projections
1729+
} else {
1730+
v = Vec::with_capacity(self.projection.len() + more_projections.len());
1731+
v.extend(self.projection);
1732+
v.extend(more_projections);
1733+
&v
1734+
};
1735+
1736+
Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
1737+
}
17241738
}
17251739

17261740
impl Debug for Place<'_> {

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,13 @@ fn write_scope_tree(
551551
}
552552

553553
let indented_debug_info = format!(
554-
"{0:1$}debug {2} => {3:?};",
555-
INDENT, indent, var_debug_info.name, var_debug_info.value,
554+
"{0:1$}debug {2} => {3:&<4$}{5:?};",
555+
INDENT,
556+
indent,
557+
var_debug_info.name,
558+
"",
559+
var_debug_info.references as usize,
560+
var_debug_info.value,
556561
);
557562

558563
writeln!(

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ macro_rules! make_mir_visitor {
842842
source_info,
843843
value,
844844
argument_index: _,
845+
references: _,
845846
} = var_debug_info;
846847

847848
self.visit_source_info(source_info);

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ CloneLiftImpls! {
204204
(),
205205
bool,
206206
usize,
207+
u8,
207208
u16,
208209
u32,
209210
u64,

compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22412241
self.var_debug_info.push(VarDebugInfo {
22422242
name,
22432243
source_info: debug_source_info,
2244+
references: 0,
22442245
value: VarDebugInfoContents::Place(for_arm_body.into()),
22452246
argument_index: None,
22462247
});
@@ -2260,6 +2261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22602261
self.var_debug_info.push(VarDebugInfo {
22612262
name,
22622263
source_info: debug_source_info,
2264+
references: 0,
22632265
value: VarDebugInfoContents::Place(ref_for_guard.into()),
22642266
argument_index: None,
22652267
});

compiler/rustc_mir_build/src/build/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
798798
};
799799
self.var_debug_info.push(VarDebugInfo {
800800
name,
801+
references: 0,
801802
source_info: SourceInfo::outermost(captured_place.var_ident.span),
802803
value: VarDebugInfoContents::Place(use_place),
803804
argument_index: None,
@@ -828,6 +829,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
828829
self.var_debug_info.push(VarDebugInfo {
829830
name,
830831
source_info,
832+
references: 0,
831833
value: VarDebugInfoContents::Place(arg_local.into()),
832834
argument_index: Some(argument_index as u16 + 1),
833835
});

compiler/rustc_mir_transform/src/ref_prop.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ fn compute_replacement<'tcx>(
263263
targets,
264264
storage_to_remove,
265265
allowed_replacements,
266+
fully_replacable_locals,
266267
any_replacement: false,
267268
};
268269

@@ -343,13 +344,31 @@ struct Replacer<'tcx> {
343344
storage_to_remove: BitSet<Local>,
344345
allowed_replacements: FxHashSet<(Local, Location)>,
345346
any_replacement: bool,
347+
fully_replacable_locals: BitSet<Local>,
346348
}
347349

348350
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
349351
fn tcx(&self) -> TyCtxt<'tcx> {
350352
self.tcx
351353
}
352354

355+
fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
356+
if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
357+
&& place.projection.is_empty()
358+
&& let Value::Pointer(target, _) = self.targets[place.local]
359+
&& target.projection.iter().all(|p| p.can_use_in_debuginfo())
360+
{
361+
if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
362+
*place = Place::from(target.local).project_deeper(rest, self.tcx);
363+
self.any_replacement = true;
364+
} else if self.fully_replacable_locals.contains(place.local) {
365+
debuginfo.references += 1;
366+
*place = target;
367+
self.any_replacement = true;
368+
}
369+
}
370+
}
371+
353372
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
354373
if place.projection.first() != Some(&PlaceElem::Deref) {
355374
return;

compiler/rustc_type_ir/src/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ TrivialTypeTraversalImpls! {
2121
(),
2222
bool,
2323
usize,
24+
u8,
2425
u16,
2526
u32,
2627
u64,

tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
debug x => _1; // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:14
1414
let _2: &mut i32; // in scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
1515
scope 2 {
16-
debug xref => _2; // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
16+
- debug xref => _2; // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
17+
+ debug xref => &_1; // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
1718
let _3: *mut i32; // in scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
1819
scope 3 {
19-
debug xraw => _3; // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
20+
- debug xraw => _3; // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
21+
+ debug xraw => _4; // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
2022
let _6: &i32; // in scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
2123
scope 4 {
22-
debug xshr => _6; // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
24+
- debug xshr => _6; // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
25+
+ debug xshr => _2; // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
2326
let _7: i32; // in scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
2427
scope 5 {
2528
debug a => _7; // in scope 5 at $DIR/reference_prop.rs:+6:9: +6:10
@@ -36,18 +39,17 @@
3639
_1 = const 2_i32; // scope 0 at $DIR/reference_prop.rs:+1:17: +1:18
3740
- StorageLive(_2); // scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
3841
_2 = &mut _1; // scope 1 at $DIR/reference_prop.rs:+2:16: +2:22
39-
StorageLive(_3); // scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
42+
- StorageLive(_3); // scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
4043
- StorageLive(_4); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
4144
- StorageLive(_5); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
4245
- _5 = &mut (*_2); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
4346
- _4 = &raw mut (*_5); // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
44-
+ _4 = &raw mut _1; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
45-
_3 = _4; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
47+
- _3 = _4; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
4648
- StorageDead(_5); // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
4749
- StorageDead(_4); // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
48-
StorageLive(_6); // scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
50+
- StorageLive(_6); // scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
4951
- _6 = &(*_2); // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
50-
+ _6 = &_1; // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
52+
+ _4 = &raw mut _1; // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
5153
StorageLive(_7); // scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
5254
- _7 = (*_6); // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
5355
- StorageLive(_8); // scope 5 at $DIR/reference_prop.rs:+7:5: +7:26
@@ -64,8 +66,8 @@
6466
StorageDead(_10); // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
6567
StorageDead(_9); // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
6668
StorageDead(_7); // scope 4 at $DIR/reference_prop.rs:+9:1: +9:2
67-
StorageDead(_6); // scope 3 at $DIR/reference_prop.rs:+9:1: +9:2
68-
StorageDead(_3); // scope 2 at $DIR/reference_prop.rs:+9:1: +9:2
69+
- StorageDead(_6); // scope 3 at $DIR/reference_prop.rs:+9:1: +9:2
70+
- StorageDead(_3); // scope 2 at $DIR/reference_prop.rs:+9:1: +9:2
6971
- StorageDead(_2); // scope 1 at $DIR/reference_prop.rs:+9:1: +9:2
7072
StorageDead(_1); // scope 0 at $DIR/reference_prop.rs:+9:1: +9:2
7173
return; // scope 0 at $DIR/reference_prop.rs:+9:2: +9:2

0 commit comments

Comments
 (0)