Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 36fae9e

Browse files
committed
Reimplement references debuginfo as projection.
1 parent fc1a4c5 commit 36fae9e

File tree

32 files changed

+2149
-1044
lines changed

32 files changed

+2149
-1044
lines changed

‎compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
33
use rustc_index::IndexVec;
44
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
55
use rustc_middle::mir;
6-
use rustc_middle::ty;
76
use rustc_middle::ty::layout::TyAndLayout;
87
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
98
use rustc_middle::ty::Instance;
@@ -17,8 +16,6 @@ use super::operand::{OperandRef, OperandValue};
1716
use super::place::PlaceRef;
1817
use super::{FunctionCx, LocalRef};
1918

20-
use std::ops::Range;
21-
2219
pub struct FunctionDebugContext<'tcx, S, L> {
2320
/// Maps from source code to the corresponding debug info scope.
2421
pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
@@ -36,17 +33,17 @@ pub enum VariableKind {
3633
#[derive(Clone)]
3734
pub struct PerLocalVarDebugInfo<'tcx, D> {
3835
pub name: Symbol,
36+
pub ty: Ty<'tcx>,
3937
pub source_info: mir::SourceInfo,
4038

4139
/// `DIVariable` returned by `create_dbg_var`.
4240
pub dbg_var: Option<D>,
4341

44-
/// Byte range in the `dbg_var` covered by this fragment,
45-
/// if this is a fragment of a composite `VarDebugInfo`.
46-
pub fragment: Option<Range<Size>>,
47-
4842
/// `.place.projection` from `mir::VarDebugInfo`.
49-
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
43+
pub projection: &'tcx [mir::PlaceElem<'tcx>],
44+
45+
/// Projection from fragment debuginfo.
46+
pub fragment: &'tcx [mir::PlaceElem<'tcx>],
5047
}
5148

5249
#[derive(Clone, Copy, Debug)]
@@ -149,6 +146,8 @@ struct DebugInfoOffset<T> {
149146
indirect_offsets: Vec<Size>,
150147
/// The final location debuginfo should point to.
151148
result: T,
149+
/// Whether the final location is a fragment of a larger contiguous projection.
150+
fragment: bool,
152151
}
153152

154153
fn calculate_debuginfo_offset<
@@ -165,17 +164,21 @@ fn calculate_debuginfo_offset<
165164
// FIXME(eddyb) use smallvec here.
166165
let mut indirect_offsets = vec![];
167166
let mut place = base;
167+
let mut fragment = false;
168168

169169
for elem in projection {
170+
let layout = place.layout();
170171
match *elem {
171172
mir::ProjectionElem::Deref => {
172173
indirect_offsets.push(Size::ZERO);
173174
place = place.deref(bx);
175+
fragment = false;
174176
}
175177
mir::ProjectionElem::Field(field, _) => {
176178
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
177179
*offset += place.layout().fields.offset(field.index());
178180
place = place.project_field(bx, field);
181+
fragment |= place.layout().size != layout.size;
179182
}
180183
mir::ProjectionElem::Downcast(_, variant) => {
181184
place = place.downcast(bx, variant);
@@ -191,16 +194,17 @@ fn calculate_debuginfo_offset<
191194
};
192195
*offset += stride * index;
193196
place = place.project_constant_index(bx, index);
197+
fragment |= place.layout().size != layout.size;
194198
}
195199
_ => {
196200
// Sanity check for `can_use_in_debuginfo`.
197201
debug_assert!(!elem.can_use_in_debuginfo());
198-
bug!("unsupported var debuginfo projection `{:?}`", projection)
202+
bug!("unsupported var debuginfo place `{:?}`", projection)
199203
}
200204
}
201205
}
202206

203-
DebugInfoOffset { direct_offset, indirect_offsets, result: place }
207+
DebugInfoOffset { direct_offset, indirect_offsets, result: place, fragment }
204208
}
205209

206210
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -290,14 +294,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
290294
} else {
291295
let name = kw::Empty;
292296
let decl = &self.mir.local_decls[local];
297+
let arg_ty = self.monomorphize(decl.ty);
298+
293299
let dbg_var = if full_debug_info {
294300
self.adjusted_span_and_dbg_scope(decl.source_info).map(
295301
|(dbg_scope, _, span)| {
296302
// FIXME(eddyb) is this `+ 1` needed at all?
297303
let kind = VariableKind::ArgumentVariable(arg_index + 1);
298304

299-
let arg_ty = self.monomorphize(decl.ty);
300-
301305
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
302306
},
303307
)
@@ -307,10 +311,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
307311

308312
Some(PerLocalVarDebugInfo {
309313
name,
314+
ty: arg_ty,
310315
source_info: decl.source_info,
311316
dbg_var,
312-
fragment: None,
313-
projection: ty::List::empty(),
317+
fragment: &[],
318+
projection: &[],
314319
})
315320
}
316321
} else {
@@ -392,8 +397,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
392397
let Some(dbg_var) = var.dbg_var else { return };
393398
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
394399

395-
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
400+
let DebugInfoOffset { mutdirect_offset, indirect_offsets, result: _,fragment: _ } =
396401
calculate_debuginfo_offset(bx, var.projection, base.layout);
402+
let mut indirect_offsets = &indirect_offsets[..];
397403

398404
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
399405
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -410,8 +416,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
410416
&& (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
411417

412418
if should_create_individual_allocas {
413-
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
414-
calculate_debuginfo_offset(bx, var.projection, base);
419+
let DebugInfoOffset {
420+
direct_offset: _,
421+
indirect_offsets: _,
422+
fragment: _,
423+
result: place,
424+
} = calculate_debuginfo_offset(bx, var.projection, base);
415425

416426
// Create a variable which will be a pointer to the actual value
417427
let ptr_ty = Ty::new_mut_ptr(bx.tcx(), place.layout.ty);
@@ -423,24 +433,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
423433
bx.store(place.llval, alloca.llval, alloca.align);
424434

425435
// Point the debug info to `*alloca` for the current variable
426-
bx.dbg_var_addr(
427-
dbg_var,
428-
dbg_loc,
429-
alloca.llval,
430-
Size::ZERO,
431-
&[Size::ZERO],
432-
var.fragment,
433-
);
436+
direct_offset = Size::ZERO;
437+
indirect_offsets = &[Size::ZERO];
438+
}
439+
440+
self.debug_introduce_place(
441+
bx,
442+
dbg_var,
443+
dbg_loc,
444+
base.llval,
445+
direct_offset,
446+
indirect_offsets,
447+
var.ty,
448+
var.fragment,
449+
);
450+
}
451+
452+
fn debug_introduce_place(
453+
&self,
454+
bx: &mut Bx,
455+
dbg_var: Bx::DIVariable,
456+
dbg_loc: Bx::DILocation,
457+
base: Bx::Value,
458+
direct_offset: Size,
459+
indirect_offsets: &[Size],
460+
ty: Ty<'tcx>,
461+
fragment: &[mir::PlaceElem<'tcx>],
462+
) {
463+
let DebugInfoOffset {
464+
direct_offset: fragment_offset,
465+
indirect_offsets: fragment_indirect,
466+
result: fragment_layout,
467+
fragment,
468+
} = calculate_debuginfo_offset(bx, fragment, bx.layout_of(ty));
469+
470+
let fragment = if fragment_layout.size == Size::ZERO {
471+
return;
472+
} else if fragment {
473+
Some(fragment_offset..fragment_offset + fragment_layout.size)
434474
} else {
435-
bx.dbg_var_addr(
436-
dbg_var,
437-
dbg_loc,
438-
base.llval,
439-
direct_offset,
440-
&indirect_offsets,
441-
var.fragment,
442-
);
475+
None
476+
};
477+
478+
if !fragment_indirect.is_empty() {
479+
return;
443480
}
481+
482+
bx.dbg_var_addr(dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment);
444483
}
445484

446485
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -512,32 +551,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
512551
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
513552
});
514553

515-
let fragment = if let Some(ref fragment) = var.composite {
516-
let var_layout = self.cx.layout_of(var_ty);
517-
518-
let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
519-
calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
520-
debug_assert!(indirect_offsets.is_empty());
521-
522-
if fragment_layout.size == Size::ZERO {
523-
// Fragment is a ZST, so does not represent anything. Avoid generating anything
524-
// as this may conflict with a fragment that covers the entire variable.
525-
continue;
526-
} else if fragment_layout.size == var_layout.size {
527-
// Fragment covers entire variable, so as far as
528-
// DWARF is concerned, it's not really a fragment.
529-
None
530-
} else {
531-
Some(direct_offset..direct_offset + fragment_layout.size)
532-
}
533-
} else {
534-
None
535-
};
554+
let fragment =
555+
if let Some(ref fragment) = var.composite { &fragment.projection[..] } else { &[] };
536556

537557
match var.value {
538558
mir::VarDebugInfoContents::Place(place) => {
539559
per_local[place.local].push(PerLocalVarDebugInfo {
540560
name: var.name,
561+
ty: var_ty,
541562
source_info: var.source_info,
542563
dbg_var,
543564
fragment,
@@ -553,7 +574,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
553574
let base =
554575
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
555576

556-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], fragment);
577+
self.debug_introduce_place(
578+
bx,
579+
dbg_var,
580+
dbg_loc,
581+
base.llval,
582+
Size::ZERO,
583+
&[],
584+
var_ty,
585+
fragment,
586+
);
557587
}
558588
}
559589
}

‎compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
796796
format!("invalid empty projection in debuginfo for {:?}", debuginfo.name),
797797
);
798798
}
799-
if projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) {
799+
if !projection.iter().all(|p| matches!(p, PlaceElem::Field(..) | PlaceElem::Deref)) {
800800
self.fail(
801801
START_BLOCK.start_location(),
802802
format!(

‎compiler/rustc_middle/src/mir/visit.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -858,8 +858,13 @@ macro_rules! make_mir_visitor {
858858
if let Some(box VarDebugInfoFragment { ref $($mutability)? ty, ref $($mutability)? projection }) = composite {
859859
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
860860
for elem in projection {
861-
let ProjectionElem::Field(_, ty) = elem else { bug!() };
862-
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
861+
match elem {
862+
ProjectionElem::Deref => {}
863+
ProjectionElem::Field(_, ty) => {
864+
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location))
865+
}
866+
_ => bug!("unexpected projection in debuginfo: {elem:?}"),
867+
}
863868
}
864869
}
865870
match value {

‎compiler/rustc_mir_transform/src/ref_prop.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,20 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
8989
debug!(?replacer.allowed_replacements);
9090
debug!(?replacer.storage_to_remove);
9191

92-
replacer.visit_body_preserves_cfg(body);
92+
replacer.local_decls = Some(&body.local_decls);
93+
for debuginfo in body.var_debug_info.iter_mut() {
94+
replacer.visit_var_debug_info(debuginfo);
95+
}
96+
for (bb, bbdata) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
97+
replacer.visit_basic_block_data(bb, bbdata);
98+
}
9399

94100
if replacer.any_replacement {
95101
crate::simplify::remove_unused_definitions(body);
102+
true
103+
} else {
104+
false
96105
}
97-
98-
replacer.any_replacement
99106
}
100107

101108
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -113,7 +120,7 @@ fn compute_replacement<'tcx>(
113120
tcx: TyCtxt<'tcx>,
114121
body: &Body<'tcx>,
115122
ssa: &SsaLocals,
116-
) -> Replacer<'tcx> {
123+
) -> Replacer<'tcx,'tcx> {
117124
let always_live_locals = always_storage_live_locals(body);
118125

119126
// Compute which locals have a single `StorageLive` statement ever.
@@ -268,7 +275,9 @@ fn compute_replacement<'tcx>(
268275
targets,
269276
storage_to_remove,
270277
allowed_replacements,
278+
fully_replacable_locals,
271279
any_replacement: false,
280+
local_decls: None,
272281
};
273282

274283
struct ReplacementFinder<'a, 'tcx, F> {
@@ -342,15 +351,17 @@ fn fully_replacable_locals(ssa: &SsaLocals) -> BitSet<Local> {
342351
}
343352

344353
/// Utility to help performing subtitution of `*pattern` by `target`.
345-
struct Replacer<'tcx> {
354+
struct Replacer<'a,'tcx> {
346355
tcx: TyCtxt<'tcx>,
347356
targets: IndexVec<Local, Value<'tcx>>,
348357
storage_to_remove: BitSet<Local>,
349358
allowed_replacements: FxHashSet<(Local, Location)>,
350359
any_replacement: bool,
360+
fully_replacable_locals: BitSet<Local>,
361+
local_decls: Option<&'a LocalDecls<'tcx>>,
351362
}
352363

353-
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
364+
impl<'tcx> MutVisitor<'tcx> for Replacer<'_,'tcx> {
354365
fn tcx(&self) -> TyCtxt<'tcx> {
355366
self.tcx
356367
}
@@ -367,6 +378,19 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
367378
if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
368379
*place = Place::from(target.local).project_deeper(rest, self.tcx);
369380
self.any_replacement = true;
381+
} else if self.fully_replacable_locals.contains(place.local) {
382+
debuginfo
383+
.composite
384+
.get_or_insert_with(|| {
385+
Box::new(VarDebugInfoFragment {
386+
ty: self.local_decls.unwrap()[place.local].ty,
387+
projection: Vec::new(),
388+
})
389+
})
390+
.projection
391+
.push(PlaceElem::Deref);
392+
*place = target;
393+
self.any_replacement = true;
370394
} else {
371395
break;
372396
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /