|
1 | | -use rustc_middle::mir::{self, NonDivergingIntrinsic, RETURN_PLACE, StmtDebugInfo}; |
| 1 | +use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo}; |
2 | 2 | use rustc_middle::{bug, span_bug}; |
3 | | -use rustc_target::callconv::PassMode; |
4 | 3 | use tracing::instrument; |
5 | 4 |
|
6 | 5 | use super::{FunctionCx, LocalRef}; |
7 | 6 | use crate::common::TypeKind; |
8 | | -use crate::mir::place::PlaceRef; |
9 | 7 | use crate::traits::*; |
10 | 8 |
|
11 | 9 | 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> { |
110 | 108 | match debuginfo { |
111 | 109 | StmtDebugInfo::AssignRef(dest, place) => { |
112 | 110 | 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. |
113 | 113 | 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)) |
115 | 115 | } |
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, |
120 | 138 | LocalRef::PendingOperand => None, |
121 | 139 | } |
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, _)| { |
133 | 141 | // 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()) |
137 | 143 | }); |
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); |
153 | 146 | } 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. |
155 | 148 | self.debug_poison_to_local(bx, *dest); |
156 | 149 | } |
157 | 150 | } |
|
0 commit comments