about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authordianqk <dianqk@dianqk.net>2025-09-21 20:58:34 +0800
committerdianqk <dianqk@dianqk.net>2025-10-03 08:08:22 +0800
commitc2a03cefd8899941032940df0c6be3b364de0ed0 (patch)
treef157a032ba7e1901fc80486f0b967024858a0230 /compiler/rustc_codegen_ssa/src
parent8da04285cf6fe61587e16155a8b224dba64bf0be (diff)
downloadrust-c2a03cefd8899941032940df0c6be3b364de0ed0.tar.gz
rust-c2a03cefd8899941032940df0c6be3b364de0ed0.zip
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)`.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs61
2 files changed, 23 insertions, 47 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 38bb6f24b1c..0c9acf087f9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -259,8 +259,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         bx: &mut Bx,
         local: mir::Local,
-        base: PlaceValue<Bx::Value>,
-        layout: TyAndLayout<'tcx>,
+        base: PlaceRef<'tcx, Bx::Value>,
         projection: &[mir::PlaceElem<'tcx>],
     ) {
         let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
@@ -274,7 +273,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         };
 
         let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
-            calculate_debuginfo_offset(bx, projection, layout);
+            calculate_debuginfo_offset(bx, projection, base.layout);
         for var in vars.iter() {
             let Some(dbg_var) = var.dbg_var else {
                 continue;
@@ -285,7 +284,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             bx.dbg_var_value(
                 dbg_var,
                 dbg_loc,
-                base.llval,
+                base.val.llval,
                 direct_offset,
                 &indirect_offsets,
                 &var.fragment,
@@ -298,7 +297,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let layout = bx.cx().layout_of(ty);
         let to_backend_ty = bx.cx().immediate_backend_type(layout);
         let place_ref = PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout);
-        self.debug_new_val_to_local(bx, local, place_ref.val, layout, &[]);
+        self.debug_new_val_to_local(bx, local, place_ref, &[]);
     }
 
     /// Apply debuginfo and/or name, after creating the `alloca` for a local,
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 80f4f0fcda1..88590b6271b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -1,11 +1,8 @@
-use rustc_middle::mir::{self, NonDivergingIntrinsic, RETURN_PLACE, StmtDebugInfo};
-use rustc_middle::{bug, span_bug};
-use rustc_target::callconv::PassMode;
+use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo};
+use rustc_middle::span_bug;
 use tracing::instrument;
 
 use super::{FunctionCx, LocalRef};
-use crate::common::TypeKind;
-use crate::mir::place::PlaceRef;
 use crate::traits::*;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -110,48 +107,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         match debuginfo {
             StmtDebugInfo::AssignRef(dest, place) => {
                 let local_ref = match self.locals[place.local] {
-                    LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => {
-                        Some(place_ref)
+                    // For an rvalue like `&(_1.1)`, when `BackendRepr` is `BackendRepr::Memory`, we allocate a block of memory to this place.
+                    // The place is an indirect pointer, we can refer to it directly.
+                    LocalRef::Place(place_ref) => Some((place_ref, place.projection.as_slice())),
+                    // For an rvalue like `&((*_1).1)`, we are calculating the address of `_1.1`.
+                    // The deref projection is no-op here.
+                    LocalRef::Operand(operand_ref) if place.is_indirect_first_projection() => {
+                        Some((operand_ref.deref(bx.cx()), &place.projection[1..]))
                     }
-                    LocalRef::Operand(operand_ref) => operand_ref
-                        .val
-                        .try_pointer_parts()
-                        .map(|(pointer, _)| PlaceRef::new_sized(pointer, operand_ref.layout)),
-                    LocalRef::PendingOperand => None,
+                    // For an rvalue like `&1`, when `BackendRepr` is `BackendRepr::Scalar`,
+                    // we cannot get the address.
+                    // N.B. `non_ssa_locals` returns that this is an SSA local.
+                    LocalRef::Operand(_) => None,
+                    LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => None,
                 }
-                .filter(|place_ref| {
-                    // For the reference of an argument (e.x. `&_1`), it's only valid if the pass mode is indirect, and its reference is
-                    // llval.
-                    let local_ref_pass_mode = place.as_local().and_then(|local| {
-                        if local == RETURN_PLACE {
-                            None
-                        } else {
-                            self.fn_abi.args.get(local.as_usize() - 1).map(|arg| &arg.mode)
-                        }
-                    });
-                    matches!(local_ref_pass_mode, Some(&PassMode::Indirect {..}) | None) &&
+                .filter(|(_, projection)| {
                     // Drop unsupported projections.
-                    place.projection.iter().all(|p| p.can_use_in_debuginfo()) &&
-                    // Only pointers can be calculated addresses.
-                    bx.type_kind(bx.val_ty(place_ref.val.llval)) == TypeKind::Pointer
+                    projection.iter().all(|p| p.can_use_in_debuginfo())
                 });
-                if let Some(local_ref) = local_ref {
-                    let (base_layout, projection) = if place.is_indirect_first_projection() {
-                        // For `_n = &((*_1).0: i32);`, we are calculating the address of `_1.0`, so
-                        // we should drop the deref projection.
-                        let projected_ty = local_ref
-                            .layout
-                            .ty
-                            .builtin_deref(true)
-                            .unwrap_or_else(|| bug!("deref of non-pointer {:?}", local_ref));
-                        let layout = bx.cx().layout_of(projected_ty);
-                        (layout, &place.projection[1..])
-                    } else {
-                        (local_ref.layout, place.projection.as_slice())
-                    };
-                    self.debug_new_val_to_local(bx, *dest, local_ref.val, base_layout, projection);
+                if let Some((base, projection)) = local_ref {
+                    self.debug_new_val_to_local(bx, *dest, base, projection);
                 } else {
-                    // If the address cannot be computed, use poison to indicate that the value has been optimized out.
+                    // If the address cannot be calculated, use poison to indicate that the value has been optimized out.
                     self.debug_poison_to_local(bx, *dest);
                 }
             }