Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, StatementKind,
Terminator, TerminatorKind, VarBindingForm, VarDebugInfoContents,
Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
Expand Down Expand Up @@ -589,10 +589,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
move_span: Span,
err: &mut Diag<'infcx>,
) {
let var_info = self.body.var_debug_info.iter().find(|info| match info.value {
VarDebugInfoContents::Place(ref p) => p == place,
_ => false,
});
let var_info = self.body.var_debug_info.iter().find(|info| *place == info.place);
let Some(var_info) = var_info else { return };
let arg_name = var_info.name;
struct MatchArgFinder {
Expand Down
28 changes: 13 additions & 15 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_infer::traits::SelectionError;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement,
StatementKind, Terminator, TerminatorKind, VarDebugInfoContents, find_self_call,
StatementKind, Terminator, TerminatorKind, find_self_call,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Ty, TyCtxt};
Expand Down Expand Up @@ -200,21 +200,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.local_names.get_or_init(|| {
let mut local_names = IndexVec::from_elem(None, &self.body.local_decls);
for var_debug_info in &self.body.var_debug_info {
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
if let Some(local) = place.as_local() {
if let Some(prev_name) = local_names[local]
&& var_debug_info.name != prev_name
{
span_bug!(
var_debug_info.source_info.span,
"local {:?} has many names (`{}` vs `{}`)",
local,
prev_name,
var_debug_info.name
);
}
local_names[local] = Some(var_debug_info.name);
if let Some(local) = var_debug_info.place.as_local() {
if let Some(prev_name) = local_names[local]
&& var_debug_info.name != prev_name
{
span_bug!(
var_debug_info.source_info.span,
"local {:?} has many names (`{}` vs `{}`)",
local,
prev_name,
var_debug_info.name
);
}
local_names[local] = Some(var_debug_info.name);
}
}
local_names
Expand Down
174 changes: 96 additions & 78 deletions compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::ops::Range;

use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, Size, VariantIdx};
Expand Down Expand Up @@ -49,17 +48,6 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
}

/// Information needed to emit a constant.
pub struct ConstDebugInfo<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
pub name: String,
pub source_info: mir::SourceInfo,
pub operand: OperandRef<'tcx, Bx::Value>,
pub dbg_var: Bx::DIVariable,
pub dbg_loc: Bx::DILocation,
pub fragment: Option<Range<Size>>,
pub _phantom: PhantomData<&'a ()>,
}

#[derive(Clone, Copy, Debug)]
pub struct DebugScope<S, L> {
pub dbg_scope: S,
Expand Down Expand Up @@ -236,7 +224,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
}

fn spill_operand_to_stack(
pub(super) fn spill_operand_to_stack(
operand: OperandRef<'tcx, Bx::Value>,
name: Option<String>,
bx: &mut Bx,
Expand All @@ -254,14 +242,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
spill_slot
}

// Indicates that local is set to a new value. The `layout` and `projection` are used to
// calculate the offset.
pub(crate) fn debug_new_val_to_local(
/// Indicates that local is set to a new value.
fn debug_new_val_to_local(
&self,
bx: &mut Bx,
local: mir::Local,
base: PlaceRef<'tcx, Bx::Value>,
projection: &[mir::PlaceElem<'tcx>],
llval: Bx::Value,
direct_offset: Size,
indirect_offsets: &[Size],
) {
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
if !full_debug_info {
Expand All @@ -273,8 +261,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
None => return,
};

let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
calculate_debuginfo_offset(bx, projection, base.layout);
for var in vars.iter() {
let Some(dbg_var) = var.dbg_var else {
continue;
Expand All @@ -285,20 +271,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.dbg_var_value(
dbg_var,
dbg_loc,
base.val.llval,
llval,
direct_offset,
&indirect_offsets,
indirect_offsets,
&var.fragment,
);
}
}

pub(crate) fn debug_poison_to_local(&self, bx: &mut Bx, local: mir::Local) {
fn debug_poison_to_local(&self, bx: &mut Bx, local: mir::Local) {
let ty = self.monomorphize(self.mir.local_decls[local].ty);
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, &[]);
let llval = bx.cx().const_poison(to_backend_ty);
self.debug_new_val_to_local(bx, local, llval, Size::ZERO, &[]);
}

/// Apply debuginfo and/or name, after creating the `alloca` for a local,
Expand Down Expand Up @@ -524,36 +510,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}

pub(crate) fn debug_introduce_locals(
&self,
bx: &mut Bx,
consts: Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
) {
pub(crate) fn debug_introduce_locals(&self, bx: &mut Bx) {
if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
for local in self.locals.indices() {
self.debug_introduce_local(bx, local);
}

for ConstDebugInfo { name, source_info, operand, dbg_var, dbg_loc, fragment, .. } in
consts.into_iter()
{
self.set_debug_loc(bx, source_info);
let base = FunctionCx::spill_operand_to_stack(operand, Some(name), bx);
bx.clear_dbg_loc();

bx.dbg_var_addr(dbg_var, dbg_loc, base.val.llval, Size::ZERO, &[], &fragment);
}
}
}

/// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
pub(crate) fn compute_per_local_var_debug_info(
&self,
bx: &mut Bx,
) -> Option<(
PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>,
Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
)> {
) -> Option<PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>> {
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;

let target_is_msvc = self.cx.sess().target.is_like_msvc;
Expand All @@ -563,7 +532,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
let mut constants = vec![];
let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default();
for var in &self.mir.var_debug_info {
let dbg_scope_and_span = if full_debug_info {
Expand All @@ -575,19 +543,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let var_ty = if let Some(ref fragment) = var.composite {
self.monomorphize(fragment.ty)
} else {
match var.value {
mir::VarDebugInfoContents::Place(place) => {
self.monomorphized_place_ty(place.as_ref())
}
mir::VarDebugInfoContents::Const(c) => self.monomorphize(c.ty()),
}
self.monomorphized_place_ty(var.place.as_ref())
};

let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
let var_kind = if let Some(arg_index) = var.argument_index
&& var.composite.is_none()
&& let mir::VarDebugInfoContents::Place(place) = var.value
&& place.projection.is_empty()
&& var.place.projection.is_empty()
{
let arg_index = arg_index as usize;
if target_is_msvc {
Expand Down Expand Up @@ -645,35 +607,91 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
None
};

match var.value {
mir::VarDebugInfoContents::Place(place) => {
per_local[place.local].push(PerLocalVarDebugInfo {
name: var.name,
source_info: var.source_info,
dbg_var,
fragment,
projection: place.projection,
});
}
mir::VarDebugInfoContents::Const(c) => {
if let Some(dbg_var) = dbg_var {
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };

let operand = self.eval_mir_constant_to_operand(bx, &c);
constants.push(ConstDebugInfo {
name: var.name.to_string(),
source_info: var.source_info,
operand,
dbg_var,
dbg_loc,
fragment,
_phantom: PhantomData,
});
per_local[var.place.local].push(PerLocalVarDebugInfo {
name: var.name,
source_info: var.source_info,
dbg_var,
fragment,
projection: var.place.projection,
});
}
Some(per_local)
}

pub(crate) fn codegen_stmt_debuginfo(
&mut self,
bx: &mut Bx,
debuginfo: &mir::StmtDebugInfo<'tcx>,
) {
match debuginfo {
mir::StmtDebugInfo::AssignConst(dest, cnst) => {
let operand = self.eval_mir_constant_to_operand(bx, &cnst);
let (llval, indirect_offsets) = match operand.val {
OperandValue::Ref(place) => (place.llval, true),
OperandValue::Immediate(value) => (value, false),
OperandValue::Pair(..) => {
let place = FunctionCx::spill_operand_to_stack(operand, None, bx);
(place.val.llval, true)
}
OperandValue::ZeroSized => {
let to_backend_ty = bx.cx().immediate_backend_type(operand.layout);
let llval = bx.cx().const_poison(to_backend_ty);
(llval, false)
}
};
let indirect_offsets: &[Size] = if indirect_offsets { &[Size::ZERO] } else { &[] };
self.debug_new_val_to_local(bx, *dest, llval, Size::ZERO, indirect_offsets);
}
mir::StmtDebugInfo::AssignRef(dest, place) => {
let local_ref = match self.locals[place.local] {
// 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..]))
}
// 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(|(_, projection)| {
// Drop unsupported projections.
projection.iter().all(|p| p.can_use_in_debuginfo())
});
if let Some((base, projection)) = local_ref {
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
calculate_debuginfo_offset(bx, projection, base.layout);
self.debug_new_val_to_local(
bx,
*dest,
base.val.llval,
direct_offset,
&indirect_offsets,
);
} else {
// If the address cannot be calculated, use poison to indicate that the value has been optimized out.
self.debug_poison_to_local(bx, *dest);
}
}
mir::StmtDebugInfo::InvalidAssign(local) => {
self.debug_poison_to_local(bx, *local);
}
mir::StmtDebugInfo::Nop => {}
}
}

pub(crate) fn codegen_stmt_debuginfos(
&mut self,
bx: &mut Bx,
debuginfos: &[mir::StmtDebugInfo<'tcx>],
) {
for debuginfo in debuginfos {
self.codegen_stmt_debuginfo(bx, debuginfo);
}
Some((per_local, constants))
}

/// Creates the function-specific debug context.
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

fx.fill_function_debug_context();

let (per_local_var_debug_info, consts_debug_info) =
fx.compute_per_local_var_debug_info(&mut start_bx).unzip();
let per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
fx.per_local_var_debug_info = per_local_var_debug_info;

let traversal_order = traversal::mono_reachable_reverse_postorder(mir, tcx, instance);
Expand Down Expand Up @@ -325,7 +324,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx.initialize_locals(local_values);

// Apply debuginfo to the newly allocated locals.
fx.debug_introduce_locals(&mut start_bx, consts_debug_info.unwrap_or_default());
fx.debug_introduce_locals(&mut start_bx);

// The builders will be created separately for each basic block at `codegen_block`.
// So drop the builder of `start_llbb` to avoid having two at the same time.
Expand Down
Loading
Loading