|
1 |
| -use rustc_middle::mir::{self, NonDivergingIntrinsic}; |
2 |
| -use rustc_middle::span_bug; |
| 1 | +use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo}; |
| 2 | +use rustc_middle::{bug, span_bug}; |
3 | 3 | use tracing::instrument;
|
4 | 4 |
|
5 | 5 | use super::{FunctionCx, LocalRef};
|
| 6 | +use crate::common::TypeKind; |
| 7 | +use crate::mir::operand::OperandValue; |
| 8 | +use crate::mir::place::PlaceRef; |
6 | 9 | use crate::traits::*;
|
7 | 10 |
|
8 | 11 | impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
9 | 12 | #[instrument(level = "debug", skip(self, bx))]
|
10 | 13 | pub(crate) fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx>) {
|
| 14 | + self.codegen_stmt_debuginfos(bx, &statement.debuginfos); |
11 | 15 | self.set_debug_loc(bx, statement.source_info);
|
12 | 16 | match statement.kind {
|
13 | 17 | mir::StatementKind::Assign(box (ref place, ref rvalue)) => {
|
@@ -96,4 +100,68 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
96 | 100 | | mir::StatementKind::Nop => {}
|
97 | 101 | }
|
98 | 102 | }
|
| 103 | + |
| 104 | + pub(crate) fn codegen_stmt_debuginfo(&mut self, bx: &mut Bx, debuginfo: &StmtDebugInfo<'tcx>) { |
| 105 | + match debuginfo { |
| 106 | + StmtDebugInfo::AssignRef(dest, place) => { |
| 107 | + let place_ref = match self.locals[place.local] { |
| 108 | + LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => { |
| 109 | + Some(place_ref) |
| 110 | + } |
| 111 | + LocalRef::Operand(operand_ref) => match operand_ref.val { |
| 112 | + OperandValue::Ref(_place_value) => { |
| 113 | + todo!("supports OperandValue::Ref") |
| 114 | + } |
| 115 | + OperandValue::Immediate(v) => { |
| 116 | + // FIXME: add ref to layout? |
| 117 | + Some(PlaceRef::new_sized(v, operand_ref.layout)) |
| 118 | + } |
| 119 | + OperandValue::Pair(_, _) => None, |
| 120 | + OperandValue::ZeroSized => None, |
| 121 | + }, |
| 122 | + LocalRef::PendingOperand => None, |
| 123 | + } |
| 124 | + .filter(|place_ref| { |
| 125 | + // Drop unsupported projections. |
| 126 | + // FIXME: Add a test case. |
| 127 | + place.projection.iter().all(|p| p.can_use_in_debuginfo()) && |
| 128 | + // Only pointers can calculate addresses. |
| 129 | + bx.type_kind(bx.val_ty(place_ref.val.llval)) == TypeKind::Pointer |
| 130 | + }); |
| 131 | + let (val, layout, projection) = |
| 132 | + match (place_ref, place.is_indirect_first_projection()) { |
| 133 | + (Some(place_ref), false) => { |
| 134 | + (place_ref.val, place_ref.layout, place.projection.as_slice()) |
| 135 | + } |
| 136 | + (Some(place_ref), true) => { |
| 137 | + let projected_ty = |
| 138 | + place_ref.layout.ty.builtin_deref(true).unwrap_or_else(|| { |
| 139 | + bug!("deref of non-pointer {:?}", place_ref) |
| 140 | + }); |
| 141 | + let layout = bx.cx().layout_of(projected_ty); |
| 142 | + (place_ref.val, layout, &place.projection[1..]) |
| 143 | + } |
| 144 | + _ => { |
| 145 | + // If the address cannot be computed, use poison to indicate that the value has been optimized out. |
| 146 | + let ty = self.monomorphize(self.mir.local_decls[*dest].ty); |
| 147 | + let layout = bx.cx().layout_of(ty); |
| 148 | + let to_backend_ty = bx.cx().immediate_backend_type(layout); |
| 149 | + let place_ref = |
| 150 | + PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout); |
| 151 | + (place_ref.val, layout, [].as_slice()) |
| 152 | + } |
| 153 | + }; |
| 154 | + self.debug_new_value_to_local(bx, *dest, val, layout, projection); |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | + pub(crate) fn codegen_stmt_debuginfos( |
| 159 | + &mut self, |
| 160 | + bx: &mut Bx, |
| 161 | + debuginfos: &[StmtDebugInfo<'tcx>], |
| 162 | + ) { |
| 163 | + for debuginfo in debuginfos { |
| 164 | + self.codegen_stmt_debuginfo(bx, debuginfo); |
| 165 | + } |
| 166 | + } |
99 | 167 | }
|
0 commit comments