Skip to content

Commit ccc3ac0

Browse files
committed
Auto merge of #114904 - cjgillot:no-ref-debuginfo, r=wesleywiser
Remove references in VarDebugInfo The codegen implementation is broken, and attempted to read uninitialized memory. Fixes #114488
2 parents 0768872 + 3798bca commit ccc3ac0

File tree

38 files changed

+787
-626
lines changed

38 files changed

+787
-626
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+12-42
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
4242

4343
/// `.place.projection` from `mir::VarDebugInfo`.
4444
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
45-
46-
/// `references` from `mir::VarDebugInfo`.
47-
pub references: u8,
4845
}
4946

5047
#[derive(Clone, Copy, Debug)]
@@ -323,7 +320,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
323320
dbg_var,
324321
fragment: None,
325322
projection: ty::List::empty(),
326-
references: 0,
327323
})
328324
}
329325
} else {
@@ -399,15 +395,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
399395
&self,
400396
bx: &mut Bx,
401397
local: mir::Local,
402-
mut base: PlaceRef<'tcx, Bx::Value>,
398+
base: PlaceRef<'tcx, Bx::Value>,
403399
var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
404400
) {
405401
let Some(dbg_var) = var.dbg_var else { return };
406402
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
407403

408-
let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
404+
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
409405
calculate_debuginfo_offset(bx, local, &var, base.layout);
410-
let mut indirect_offsets = &indirect_offsets[..];
411406

412407
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
413408
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -421,45 +416,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
421416
// LLVM can handle simple things but anything more complex than just a direct
422417
// offset or one indirect offset of 0 is too complex for it to generate CV records
423418
// correctly.
424-
&& (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
419+
&& (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
420+
421+
if should_create_individual_allocas {
422+
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
423+
calculate_debuginfo_offset(bx, local, &var, base);
425424

426-
let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
427425
// Create a variable which will be a pointer to the actual value
428426
let ptr_ty = Ty::new_ptr(
429427
bx.tcx(),
430428
ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty },
431429
);
432430
let ptr_layout = bx.layout_of(ptr_ty);
433431
let alloca = PlaceRef::alloca(bx, ptr_layout);
434-
bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
432+
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
435433

436434
// Write the pointer to the variable
437435
bx.store(place.llval, alloca.llval, alloca.align);
438436

439437
// Point the debug info to `*alloca` for the current variable
440-
alloca
441-
};
442-
443-
if var.references > 0 {
444-
base = calculate_debuginfo_offset(bx, local, &var, base).result;
445-
446-
// Point the debug info to `&...&base == alloca` for the current variable
447-
for refcount in 0..var.references {
448-
base = create_alloca(bx, base, refcount);
449-
}
450-
451-
direct_offset = Size::ZERO;
452-
indirect_offsets = &[];
453-
} else if should_create_individual_allocas {
454-
let place = calculate_debuginfo_offset(bx, local, &var, base).result;
455-
456-
// Point the debug info to `*alloca` for the current variable
457-
base = create_alloca(bx, place, 0);
458-
direct_offset = Size::ZERO;
459-
indirect_offsets = &[Size::ZERO];
438+
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
439+
} else {
440+
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
460441
}
461-
462-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
463442
}
464443

465444
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -492,7 +471,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
492471
};
493472

494473
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
495-
let (mut var_ty, var_kind) = match var.value {
474+
let (var_ty, var_kind) = match var.value {
496475
mir::VarDebugInfoContents::Place(place) => {
497476
let var_ty = self.monomorphized_place_ty(place.as_ref());
498477
let var_kind = if let Some(arg_index) = var.argument_index
@@ -529,13 +508,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
529508
}
530509
};
531510

532-
for _ in 0..var.references {
533-
var_ty = Ty::new_ptr(
534-
bx.tcx(),
535-
ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty },
536-
);
537-
}
538-
539511
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
540512
});
541513

@@ -547,7 +519,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
547519
dbg_var,
548520
fragment: None,
549521
projection: place.projection,
550-
references: var.references,
551522
});
552523
}
553524
mir::VarDebugInfoContents::Const(c) => {
@@ -601,7 +572,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
601572
Some(fragment_start..fragment_start + fragment_layout.size)
602573
},
603574
projection: place.projection,
604-
references: var.references,
605575
});
606576
}
607577
}

compiler/rustc_const_eval/src/transform/validate.rs

-6
Original file line numberDiff line numberDiff line change
@@ -701,12 +701,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
701701
VarDebugInfoContents::Const(_) => {}
702702
VarDebugInfoContents::Place(place) => {
703703
check_place(self, place);
704-
if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
705-
self.fail(
706-
START_BLOCK.start_location(),
707-
format!("debuginfo {debuginfo:?}, has both ref and deref"),
708-
);
709-
}
710704
}
711705
VarDebugInfoContents::Composite { ty, ref fragments } => {
712706
for f in fragments {

compiler/rustc_middle/src/mir/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1109,10 +1109,6 @@ pub struct VarDebugInfo<'tcx> {
11091109
/// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
11101110
/// argument number in the original function before it was inlined.
11111111
pub argument_index: Option<u16>,
1112-
1113-
/// The data represents `name` dereferenced `references` times,
1114-
/// and not the direct value.
1115-
pub references: u8,
11161112
}
11171113

11181114
///////////////////////////////////////////////////////////////////////////

compiler/rustc_middle/src/mir/pretty.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -555,13 +555,8 @@ fn write_scope_tree(
555555
}
556556

557557
let indented_debug_info = format!(
558-
"{0:1$}debug {2} => {3:&<4$}{5:?};",
559-
INDENT,
560-
indent,
561-
var_debug_info.name,
562-
"",
563-
var_debug_info.references as usize,
564-
var_debug_info.value,
558+
"{0:1$}debug {2} => {3:?};",
559+
INDENT, indent, var_debug_info.name, var_debug_info.value,
565560
);
566561

567562
if tcx.sess.opts.unstable_opts.mir_include_spans {

compiler/rustc_middle/src/mir/visit.rs

-1
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,6 @@ macro_rules! make_mir_visitor {
840840
source_info,
841841
value,
842842
argument_index: _,
843-
references: _,
844843
} = var_debug_info;
845844

846845
self.visit_source_info(source_info);

compiler/rustc_middle/src/ty/structural_impls.rs

-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ CloneLiftImpls! {
438438
(),
439439
bool,
440440
usize,
441-
u8,
442441
u16,
443442
u32,
444443
u64,

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

-2
Original file line numberDiff line numberDiff line change
@@ -2242,7 +2242,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22422242
self.var_debug_info.push(VarDebugInfo {
22432243
name,
22442244
source_info: debug_source_info,
2245-
references: 0,
22462245
value: VarDebugInfoContents::Place(for_arm_body.into()),
22472246
argument_index: None,
22482247
});
@@ -2262,7 +2261,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22622261
self.var_debug_info.push(VarDebugInfo {
22632262
name,
22642263
source_info: debug_source_info,
2265-
references: 0,
22662264
value: VarDebugInfoContents::Place(ref_for_guard.into()),
22672265
argument_index: None,
22682266
});

compiler/rustc_mir_build/src/build/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
820820
};
821821
self.var_debug_info.push(VarDebugInfo {
822822
name,
823-
references: 0,
824823
source_info: SourceInfo::outermost(captured_place.var_ident.span),
825824
value: VarDebugInfoContents::Place(use_place),
826825
argument_index: None,
@@ -851,7 +850,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
851850
self.var_debug_info.push(VarDebugInfo {
852851
name,
853852
source_info,
854-
references: 0,
855853
value: VarDebugInfoContents::Place(arg_local.into()),
856854
argument_index: Some(argument_index as u16 + 1),
857855
});

compiler/rustc_mir_transform/src/ref_prop.rs

-8
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ fn compute_replacement<'tcx>(
265265
targets,
266266
storage_to_remove,
267267
allowed_replacements,
268-
fully_replacable_locals,
269268
any_replacement: false,
270269
};
271270

@@ -346,7 +345,6 @@ struct Replacer<'tcx> {
346345
storage_to_remove: BitSet<Local>,
347346
allowed_replacements: FxHashSet<(Local, Location)>,
348347
any_replacement: bool,
349-
fully_replacable_locals: BitSet<Local>,
350348
}
351349

352350
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
@@ -366,12 +364,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
366364
if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
367365
*place = Place::from(target.local).project_deeper(rest, self.tcx);
368366
self.any_replacement = true;
369-
} else if self.fully_replacable_locals.contains(place.local)
370-
&& let Some(references) = debuginfo.references.checked_add(1)
371-
{
372-
debuginfo.references = references;
373-
*place = target;
374-
self.any_replacement = true;
375367
} else {
376368
break
377369
}

compiler/rustc_type_ir/src/structural_impls.rs

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ TrivialTypeTraversalImpls! {
2323
(),
2424
bool,
2525
usize,
26-
u8,
2726
u16,
2827
u32,
2928
u64,

tests/codegen/slice-ref-equality.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
4444
// equality for non-byte types also just emit a `bcmp`, not a loop.
4545

4646
// CHECK-LABEL: @eq_slice_of_nested_u8(
47-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
48-
// CHECK-SAME: [[USIZE]] noundef %y.1
47+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
48+
// CHECK-SAME: [[USIZE]] noundef %3
4949
#[no_mangle]
5050
fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
51-
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
52-
// CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
51+
// CHECK: icmp eq [[USIZE]] %1, %3
52+
// CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
5353
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
5454
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
5555
x == y
5656
}
5757

5858
// CHECK-LABEL: @eq_slice_of_i32(
59-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
60-
// CHECK-SAME: [[USIZE]] noundef %y.1
59+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
60+
// CHECK-SAME: [[USIZE]] noundef %3
6161
#[no_mangle]
6262
fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
63-
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
64-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
63+
// CHECK: icmp eq [[USIZE]] %1, %3
64+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
6565
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
6666
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
6767
x == y
6868
}
6969

7070
// CHECK-LABEL: @eq_slice_of_nonzero(
71-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
72-
// CHECK-SAME: [[USIZE]] noundef %y.1
71+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
72+
// CHECK-SAME: [[USIZE]] noundef %3
7373
#[no_mangle]
7474
fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
75-
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
76-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
75+
// CHECK: icmp eq [[USIZE]] %1, %3
76+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
7777
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
7878
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
7979
x == y
8080
}
8181

8282
// CHECK-LABEL: @eq_slice_of_option_of_nonzero(
83-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
84-
// CHECK-SAME: [[USIZE]] noundef %y.1
83+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
84+
// CHECK-SAME: [[USIZE]] noundef %3
8585
#[no_mangle]
8686
fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
87-
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
88-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
87+
// CHECK: icmp eq [[USIZE]] %1, %3
88+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
8989
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
9090
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
9191
x == y

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
let mut _2: std::option::Option<T>;
88
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
99
+ debug self => _2;
10-
+ let mut _3: isize;
10+
+ let mut _3: &std::option::Option<T>;
11+
+ let mut _4: isize;
1112
+ scope 2 {
1213
+ debug val => _0;
1314
+ }
@@ -20,16 +21,17 @@
2021
+ }
2122
+ }
2223
+ scope 4 (inlined Option::<T>::is_some) {
23-
+ debug self => &_2;
24+
+ debug self => _3;
2425
+ }
2526
+ }
2627

2728
bb0: {
2829
StorageLive(_2);
2930
_2 = move _1;
3031
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
31-
+ _3 = discriminant(_2);
32-
+ switchInt(move _3) -> [1: bb2, otherwise: bb1];
32+
+ StorageLive(_3);
33+
+ _4 = discriminant(_2);
34+
+ switchInt(move _4) -> [1: bb2, otherwise: bb1];
3335
}
3436

3537
bb1: {
@@ -38,6 +40,7 @@
3840
+
3941
+ bb2: {
4042
+ _0 = move ((_2 as Some).0: T);
43+
+ StorageDead(_3);
4144
StorageDead(_2);
4245
return;
4346
}

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
let mut _2: std::option::Option<T>;
88
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
99
+ debug self => _2;
10-
+ let mut _3: isize;
10+
+ let mut _3: &std::option::Option<T>;
11+
+ let mut _4: isize;
1112
+ scope 2 {
1213
+ debug val => _0;
1314
+ }
@@ -20,16 +21,17 @@
2021
+ }
2122
+ }
2223
+ scope 4 (inlined Option::<T>::is_some) {
23-
+ debug self => &_2;
24+
+ debug self => _3;
2425
+ }
2526
+ }
2627

2728
bb0: {
2829
StorageLive(_2);
2930
_2 = move _1;
3031
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
31-
+ _3 = discriminant(_2);
32-
+ switchInt(move _3) -> [1: bb2, otherwise: bb1];
32+
+ StorageLive(_3);
33+
+ _4 = discriminant(_2);
34+
+ switchInt(move _4) -> [1: bb2, otherwise: bb1];
3335
}
3436

3537
bb1: {
@@ -42,6 +44,7 @@
4244
- resume;
4345
+ bb2: {
4446
+ _0 = move ((_2 as Some).0: T);
47+
+ StorageDead(_3);
4548
+ StorageDead(_2);
4649
+ return;
4750
}

0 commit comments

Comments
 (0)