Skip to content

Commit d32ca9b

Browse files
committed
properly use CompoundPlace in codegen debuginfo
1 parent 107d42e commit d32ca9b

File tree

1 file changed

+76
-37
lines changed

1 file changed

+76
-37
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
4444
/// if this is a fragment of a composite `VarDebugInfo`.
4545
pub fragment: Option<Range<Size>>,
4646

47-
/// `.place.projection` from `mir::VarDebugInfo`.
48-
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
47+
/// `.place.direct_projection` from `mir::VarDebugInfo`.
48+
pub direct_projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
49+
50+
/// `.place.projection_chain` from `mir::VarDebugInfo`.
51+
pub projection_chain: &'tcx ty::List<mir::ProjectionFragment<'tcx>>,
4952
}
5053

5154
/// Information needed to emit a constant.
@@ -168,46 +171,68 @@ fn calculate_debuginfo_offset<
168171
L: DebugInfoOffsetLocation<'tcx, Bx>,
169172
>(
170173
bx: &mut Bx,
171-
projection: &[mir::PlaceElem<'tcx>],
174+
direct_projection: &[mir::PlaceElem<'tcx>],
175+
projection_chain: &[mir::ProjectionFragment<'tcx>],
172176
base: L,
173177
) -> DebugInfoOffset<L> {
174-
let mut direct_offset = Size::ZERO;
175-
// FIXME(eddyb) use smallvec here.
176-
let mut indirect_offsets = vec![];
177-
let mut place = base;
178-
179-
for elem in projection {
180-
match *elem {
181-
mir::ProjectionElem::Deref => {
182-
indirect_offsets.push(Size::ZERO);
183-
place = place.deref(bx);
184-
}
178+
let project_direct = |bx: &mut Bx, place: L, offset, elem| {
179+
let (new_place, new_offset) = match elem {
185180
mir::ProjectionElem::Field(field, _) => {
186-
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
187-
*offset += place.layout().fields.offset(field.index());
188-
place = place.project_field(bx, field);
189-
}
190-
mir::ProjectionElem::Downcast(_, variant) => {
191-
place = place.downcast(bx, variant);
181+
let offset = place.layout().fields.offset(field.index());
182+
let place = place.project_field(bx, field);
183+
184+
(place, offset)
192185
}
186+
mir::ProjectionElem::Downcast(_, variant) => (place.downcast(bx, variant), Size::ZERO),
193187
mir::ProjectionElem::ConstantIndex {
194188
offset: index,
195189
min_length: _,
196190
from_end: false,
197191
} => {
198-
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
199192
let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
200193
bug!("ConstantIndex on non-array type {:?}", place.layout())
201194
};
202-
*offset += stride * index;
203-
place = place.project_constant_index(bx, index);
195+
let offset = stride * index;
196+
let place = place.project_constant_index(bx, index);
197+
198+
(place, offset)
199+
}
200+
201+
mir::ProjectionElem::Deref => {
202+
// derefs handled separately
203+
bug!(
204+
"unexpected deref in var debuginfo projection `{direct_projection:?} {projection_chain:?}`"
205+
)
204206
}
205207
_ => {
206208
// Sanity check for `can_use_in_debuginfo`.
207209
assert!(!elem.can_use_in_debuginfo());
208-
bug!("unsupported var debuginfo projection `{:?}`", projection)
210+
bug!(
211+
"unsupported var debuginfo projection `{direct_projection:?} {projection_chain:?}`"
212+
)
209213
}
210-
}
214+
};
215+
(new_place, offset + new_offset)
216+
};
217+
218+
let (mut place, direct_offset) = direct_projection
219+
.iter()
220+
.fold((base, Size::ZERO), |(place, offset), &elem| project_direct(bx, place, offset, elem));
221+
222+
// FIXME(eddyb) use smallvec here.
223+
let mut indirect_offsets = vec![];
224+
225+
for projection in projection_chain {
226+
debug_assert_eq!(projection[0], mir::ProjectionElem::Deref);
227+
let pointee = place.deref(bx);
228+
229+
let (projected, offset) =
230+
projection[1..].iter().fold((pointee, Size::ZERO), |(place, offset), &elem| {
231+
project_direct(bx, place, offset, elem)
232+
});
233+
234+
place = projected;
235+
indirect_offsets.push(offset);
211236
}
212237

213238
DebugInfoOffset { direct_offset, indirect_offsets, result: place }
@@ -262,8 +287,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
262287
Some(per_local) => &per_local[local],
263288
None => return,
264289
};
265-
let whole_local_var = vars.iter().find(|var| var.projection.is_empty()).cloned();
266-
let has_proj = || vars.iter().any(|var| !var.projection.is_empty());
290+
let whole_local_var = vars
291+
.iter()
292+
.find(|var| var.direct_projection.is_empty() && var.projection_chain.is_empty())
293+
.cloned();
294+
let has_proj = || {
295+
vars.iter()
296+
.any(|var| !var.direct_projection.is_empty() || !var.projection_chain.is_empty())
297+
};
267298

268299
let fallback_var = if self.mir.local_kind(local) == mir::LocalKind::Arg {
269300
let arg_index = local.index() - 1;
@@ -305,7 +336,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
305336
source_info: decl.source_info,
306337
dbg_var,
307338
fragment: None,
308-
projection: ty::List::empty(),
339+
direct_projection: ty::List::empty(),
340+
projection_chain: ty::List::empty(),
309341
})
310342
}
311343
} else {
@@ -388,7 +420,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
388420
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
389421

390422
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
391-
calculate_debuginfo_offset(bx, var.projection, base.layout);
423+
calculate_debuginfo_offset(
424+
bx,
425+
var.direct_projection,
426+
var.projection_chain,
427+
base.layout,
428+
);
392429

393430
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
394431
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -406,7 +443,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
406443

407444
if should_create_individual_allocas {
408445
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
409-
calculate_debuginfo_offset(bx, var.projection, base);
446+
calculate_debuginfo_offset(bx, var.direct_projection, var.projection_chain, base);
410447

411448
// Create a variable which will be a pointer to the actual value
412449
let ptr_ty = Ty::new_mut_ptr(bx.tcx(), place.layout.ty);
@@ -543,7 +580,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
543580
let var_layout = self.cx.layout_of(var_ty);
544581

545582
let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
546-
calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
583+
calculate_debuginfo_offset(bx, &fragment.projection, &[], var_layout);
547584
assert!(indirect_offsets.is_empty());
548585

549586
if fragment_layout.size == Size::ZERO {
@@ -562,16 +599,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
562599
};
563600

564601
match var.value {
565-
mir::VarDebugInfoContents::Place(place) => {
566-
per_local[place.local].push(PerLocalVarDebugInfo {
602+
mir::VarDebugInfoContents::Place(mir::CompoundPlace {
603+
local,
604+
direct_projection,
605+
projection_chain,
606+
}) => {
607+
per_local[local].push(PerLocalVarDebugInfo {
567608
name: var.name,
568609
source_info: var.source_info,
569610
dbg_var,
570611
fragment,
571-
// FIXME change field to be projection chain
572-
projection: bx
573-
.tcx()
574-
.mk_place_elems_from_iter(place.iter_projection_elems()),
612+
direct_projection,
613+
projection_chain,
575614
});
576615
}
577616
mir::VarDebugInfoContents::Const(c) => {

0 commit comments

Comments
 (0)