Skip to content

Commit 8018751

Browse files
committed
debuginfo: Use LocalRef to simplify reference debuginfos
If the `LocalRef` is `LocalRef::Place`, we can refer to it directly, because the local of place is an indirect pointer. Such a statement is `_1 = &_2.1`. If the `LocalRef` is `LocalRef::Operand`, the `OperandRef` should provide the pointer of the reference. Such a statement is `_1 = &(*_2).1`. But there is a special case that hasn't been handled, scalar pairs like `(&[i32; 16], i32)`.
1 parent b5bdf02 commit 8018751

File tree

3 files changed

+321
-144
lines changed

3 files changed

+321
-144
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
259259
&self,
260260
bx: &mut Bx,
261261
local: mir::Local,
262-
base: PlaceValue<Bx::Value>,
262+
base: Bx::Value,
263263
layout: TyAndLayout<'tcx>,
264264
projection: &[mir::PlaceElem<'tcx>],
265265
) {
@@ -285,7 +285,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
285285
bx.dbg_var_value(
286286
dbg_var,
287287
dbg_loc,
288-
base.llval,
288+
base,
289289
direct_offset,
290290
&indirect_offsets,
291291
&var.fragment,
@@ -298,7 +298,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
298298
let layout = bx.cx().layout_of(ty);
299299
let to_backend_ty = bx.cx().immediate_backend_type(layout);
300300
let place_ref = PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout);
301-
self.debug_new_val_to_local(bx, local, place_ref.val, layout, &[]);
301+
self.debug_new_val_to_local(bx, local, place_ref.val.llval, layout, &[]);
302302
}
303303

304304
/// Apply debuginfo and/or name, after creating the `alloca` for a local,

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use rustc_middle::mir::{self, NonDivergingIntrinsic, RETURN_PLACE, StmtDebugInfo};
1+
use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo};
22
use rustc_middle::{bug, span_bug};
3-
use rustc_target::callconv::PassMode;
43
use tracing::instrument;
54

65
use super::{FunctionCx, LocalRef};
76
use crate::common::TypeKind;
8-
use crate::mir::place::PlaceRef;
97
use crate::traits::*;
108

119
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -110,48 +108,43 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
110108
match debuginfo {
111109
StmtDebugInfo::AssignRef(dest, place) => {
112110
let local_ref = match self.locals[place.local] {
111+
// For an rvalue like `&_1.1`, when `BackendRepr` is `BackendRepr::Memory`, we allocate a block of memory to this place.
112+
// The place is an indirect pointer, we can refer to it directly.
113113
LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => {
114-
Some(place_ref)
114+
Some((place_ref.val.llval, place.projection.as_slice(), place_ref.layout))
115115
}
116-
LocalRef::Operand(operand_ref) => operand_ref
117-
.val
118-
.try_pointer_parts()
119-
.map(|(pointer, _)| PlaceRef::new_sized(pointer, operand_ref.layout)),
116+
// For an rvalue like `&(*_1).1`, we are calculating the address of `_1.1`,
117+
// so we should drop the deref projection.
118+
LocalRef::Operand(operand_ref) if place.is_indirect_first_projection() => {
119+
operand_ref.val.try_pointer_parts().and_then(|(pointer, _)| {
120+
// The value may be a scalar, but only pointers can be calculated addresses.
121+
if bx.type_kind(bx.val_ty(pointer)) != TypeKind::Pointer {
122+
return None;
123+
}
124+
let deref_ty = operand_ref
125+
.layout
126+
.ty
127+
.builtin_deref(true)
128+
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", place));
129+
Some((pointer, &place.projection[1..], bx.cx().layout_of(deref_ty)))
130+
})
131+
}
132+
// For an rvalue like `&1`, when `BackendRepr` is `BackendRepr::Scalar`,
133+
// we cannot get the address.
134+
// FIXME: For scalar pairs like `(&[i32; 16], i32)` or `(i32, &[i32; 16])`,
135+
// we can also calculate the offset when accessing the offset of array elements,
136+
// but the `&pair.1[1]` is two MIR statements.
137+
LocalRef::Operand(_) => None,
120138
LocalRef::PendingOperand => None,
121139
}
122-
.filter(|place_ref| {
123-
// For the reference of an argument (e.x. `&_1`), it's only valid if the pass mode is indirect, and its reference is
124-
// llval.
125-
let local_ref_pass_mode = place.as_local().and_then(|local| {
126-
if local == RETURN_PLACE {
127-
None
128-
} else {
129-
self.fn_abi.args.get(local.as_usize() - 1).map(|arg| &arg.mode)
130-
}
131-
});
132-
matches!(local_ref_pass_mode, Some(&PassMode::Indirect {..}) | None) &&
140+
.filter(|(_, projection, _)| {
133141
// Drop unsupported projections.
134-
place.projection.iter().all(|p| p.can_use_in_debuginfo()) &&
135-
// Only pointers can be calculated addresses.
136-
bx.type_kind(bx.val_ty(place_ref.val.llval)) == TypeKind::Pointer
142+
projection.iter().all(|p| p.can_use_in_debuginfo())
137143
});
138-
if let Some(local_ref) = local_ref {
139-
let (base_layout, projection) = if place.is_indirect_first_projection() {
140-
// For `_n = &((*_1).0: i32);`, we are calculating the address of `_1.0`, so
141-
// we should drop the deref projection.
142-
let projected_ty = local_ref
143-
.layout
144-
.ty
145-
.builtin_deref(true)
146-
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", local_ref));
147-
let layout = bx.cx().layout_of(projected_ty);
148-
(layout, &place.projection[1..])
149-
} else {
150-
(local_ref.layout, place.projection.as_slice())
151-
};
152-
self.debug_new_val_to_local(bx, *dest, local_ref.val, base_layout, projection);
144+
if let Some((val, projection, layout)) = local_ref {
145+
self.debug_new_val_to_local(bx, *dest, val, layout, projection);
153146
} else {
154-
// If the address cannot be computed, use poison to indicate that the value has been optimized out.
147+
// If the address cannot be calculated, use poison to indicate that the value has been optimized out.
155148
self.debug_poison_to_local(bx, *dest);
156149
}
157150
}

0 commit comments

Comments
 (0)