|  | 
| 1 |  | -use rustc_middle::mir::{self, NonDivergingIntrinsic, RETURN_PLACE, StmtDebugInfo}; | 
| 2 |  | -use rustc_middle::{bug, span_bug}; | 
| 3 |  | -use rustc_target::callconv::PassMode; | 
|  | 1 | +use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo}; | 
|  | 2 | +use rustc_middle::span_bug; | 
| 4 | 3 | use tracing::instrument; | 
| 5 | 4 | 
 | 
| 6 | 5 | use super::{FunctionCx, LocalRef}; | 
| 7 |  | -use crate::common::TypeKind; | 
| 8 |  | -use crate::mir::place::PlaceRef; | 
| 9 | 6 | use crate::traits::*; | 
| 10 | 7 | 
 | 
| 11 | 8 | 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> { | 
| 110 | 107 |         match debuginfo { | 
| 111 | 108 |             StmtDebugInfo::AssignRef(dest, place) => { | 
| 112 | 109 |                 let local_ref = match self.locals[place.local] { | 
| 113 |  | -                    LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => { | 
| 114 |  | -                        Some(place_ref) | 
|  | 110 | +                    // For an rvalue like `&(_1.1)`, when `BackendRepr` is `BackendRepr::Memory`, we allocate a block of memory to this place. | 
|  | 111 | +                    // The place is an indirect pointer, we can refer to it directly. | 
|  | 112 | +                    LocalRef::Place(place_ref) => Some((place_ref, place.projection.as_slice())), | 
|  | 113 | +                    // For an rvalue like `&((*_1).1)`, we are calculating the address of `_1.1`. | 
|  | 114 | +                    // The deref projection is no-op here. | 
|  | 115 | +                    LocalRef::Operand(operand_ref) if place.is_indirect_first_projection() => { | 
|  | 116 | +                        Some((operand_ref.deref(bx.cx()), &place.projection[1..])) | 
| 115 | 117 |                     } | 
| 116 |  | -                    LocalRef::Operand(operand_ref) => operand_ref | 
| 117 |  | -                        .val | 
| 118 |  | -                        .try_pointer_parts() | 
| 119 |  | -                        .map(|(pointer, _)| PlaceRef::new_sized(pointer, operand_ref.layout)), | 
| 120 |  | -                    LocalRef::PendingOperand => None, | 
|  | 118 | +                    // For an rvalue like `&1`, when `BackendRepr` is `BackendRepr::Scalar`, | 
|  | 119 | +                    // we cannot get the address. | 
|  | 120 | +                    // N.B. `non_ssa_locals` returns that this is an SSA local. | 
|  | 121 | +                    LocalRef::Operand(_) => None, | 
|  | 122 | +                    LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => None, | 
| 121 | 123 |                 } | 
| 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) && | 
|  | 124 | +                .filter(|(_, projection)| { | 
| 133 | 125 |                     // 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 | 
|  | 126 | +                    projection.iter().all(|p| p.can_use_in_debuginfo()) | 
| 137 | 127 |                 }); | 
| 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); | 
|  | 128 | +                if let Some((base, projection)) = local_ref { | 
|  | 129 | +                    self.debug_new_val_to_local(bx, *dest, base, projection); | 
| 153 | 130 |                 } else { | 
| 154 |  | -                    // If the address cannot be computed, use poison to indicate that the value has been optimized out. | 
|  | 131 | +                    // If the address cannot be calculated, use poison to indicate that the value has been optimized out. | 
| 155 | 132 |                     self.debug_poison_to_local(bx, *dest); | 
| 156 | 133 |                 } | 
| 157 | 134 |             } | 
|  | 
0 commit comments