Skip to content

Commit a5b2ac6

Browse files
committed
Auto merge of rust-lang#115252 - cjgillot:mir-composite, r=davidtwco
Represent MIR composite debuginfo as projections instead of aggregates Composite debuginfo for MIR is currently represented as ``` debug name => Type { projection1 => place1, projection2 => place2 }; ``` ie. a single `VarDebugInfo` object with that name, and its value a `VarDebugInfoContents::Composite`. This PR proposes to reverse the representation to be ``` debug name.projection1 => place1; debug name.projection2 => place2; ``` ie. multiple `VarDebugInfo` objects with each their projection. This simplifies the handling of composite debuginfo by the compiler by avoiding weird nesting. Based on rust-lang#115139
2 parents a0c28cd + 26c48e6 commit a5b2ac6

17 files changed

+292
-299
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+77-78
Original file line numberDiff line numberDiff line change
@@ -484,54 +484,89 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
484484
None
485485
};
486486

487-
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
488-
let (var_ty, var_kind) = match var.value {
487+
let var_ty = if let Some(ref fragment) = var.composite {
488+
self.monomorphize(fragment.ty)
489+
} else {
490+
match var.value {
489491
mir::VarDebugInfoContents::Place(place) => {
490-
let var_ty = self.monomorphized_place_ty(place.as_ref());
491-
let var_kind = if let Some(arg_index) = var.argument_index
492-
&& place.projection.is_empty()
493-
{
494-
let arg_index = arg_index as usize;
495-
if target_is_msvc {
496-
// ScalarPair parameters are spilled to the stack so they need to
497-
// be marked as a `LocalVariable` for MSVC debuggers to visualize
498-
// their data correctly. (See #81894 & #88625)
499-
let var_ty_layout = self.cx.layout_of(var_ty);
500-
if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
501-
VariableKind::LocalVariable
502-
} else {
503-
VariableKind::ArgumentVariable(arg_index)
504-
}
505-
} else {
506-
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
507-
// offset in closures to account for the hidden environment?
508-
VariableKind::ArgumentVariable(arg_index)
509-
}
510-
} else {
511-
VariableKind::LocalVariable
512-
};
513-
(var_ty, var_kind)
492+
self.monomorphized_place_ty(place.as_ref())
514493
}
515-
mir::VarDebugInfoContents::Const(c) => {
516-
let ty = self.monomorphize(c.ty());
517-
(ty, VariableKind::LocalVariable)
518-
}
519-
mir::VarDebugInfoContents::Composite { ty, fragments: _ } => {
520-
let ty = self.monomorphize(ty);
521-
(ty, VariableKind::LocalVariable)
494+
mir::VarDebugInfoContents::Const(c) => self.monomorphize(c.ty()),
495+
}
496+
};
497+
498+
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
499+
let var_kind = if let Some(arg_index) = var.argument_index
500+
&& var.composite.is_none()
501+
&& let mir::VarDebugInfoContents::Place(place) = var.value
502+
&& place.projection.is_empty()
503+
{
504+
let arg_index = arg_index as usize;
505+
if target_is_msvc {
506+
// ScalarPair parameters are spilled to the stack so they need to
507+
// be marked as a `LocalVariable` for MSVC debuggers to visualize
508+
// their data correctly. (See #81894 & #88625)
509+
let var_ty_layout = self.cx.layout_of(var_ty);
510+
if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
511+
VariableKind::LocalVariable
512+
} else {
513+
VariableKind::ArgumentVariable(arg_index)
514+
}
515+
} else {
516+
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
517+
// offset in closures to account for the hidden environment?
518+
VariableKind::ArgumentVariable(arg_index)
522519
}
520+
} else {
521+
VariableKind::LocalVariable
523522
};
524523

525524
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
526525
});
527526

527+
let fragment = if let Some(ref fragment) = var.composite {
528+
let var_layout = self.cx.layout_of(var_ty);
529+
530+
let mut fragment_start = Size::ZERO;
531+
let mut fragment_layout = var_layout;
532+
533+
for elem in &fragment.projection {
534+
match *elem {
535+
mir::ProjectionElem::Field(field, _) => {
536+
let i = field.index();
537+
fragment_start += fragment_layout.fields.offset(i);
538+
fragment_layout = fragment_layout.field(self.cx, i);
539+
}
540+
_ => span_bug!(
541+
var.source_info.span,
542+
"unsupported fragment projection `{:?}`",
543+
elem,
544+
),
545+
}
546+
}
547+
548+
if fragment_layout.size == Size::ZERO {
549+
// Fragment is a ZST, so does not represent anything. Avoid generating anything
550+
// as this may conflict with a fragment that covers the entire variable.
551+
continue;
552+
} else if fragment_layout.size == var_layout.size {
553+
// Fragment covers entire variable, so as far as
554+
// DWARF is concerned, it's not really a fragment.
555+
None
556+
} else {
557+
Some(fragment_start..fragment_start + fragment_layout.size)
558+
}
559+
} else {
560+
None
561+
};
562+
528563
match var.value {
529564
mir::VarDebugInfoContents::Place(place) => {
530565
per_local[place.local].push(PerLocalVarDebugInfo {
531566
name: var.name,
532567
source_info: var.source_info,
533568
dbg_var,
534-
fragment: None,
569+
fragment,
535570
projection: place.projection,
536571
});
537572
}
@@ -547,51 +582,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
547582
bx,
548583
);
549584

550-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], None);
551-
}
552-
}
553-
}
554-
mir::VarDebugInfoContents::Composite { ty, ref fragments } => {
555-
let var_ty = self.monomorphize(ty);
556-
let var_layout = self.cx.layout_of(var_ty);
557-
for fragment in fragments {
558-
let mut fragment_start = Size::ZERO;
559-
let mut fragment_layout = var_layout;
560-
561-
for elem in &fragment.projection {
562-
match *elem {
563-
mir::ProjectionElem::Field(field, _) => {
564-
let i = field.index();
565-
fragment_start += fragment_layout.fields.offset(i);
566-
fragment_layout = fragment_layout.field(self.cx, i);
567-
}
568-
_ => span_bug!(
569-
var.source_info.span,
570-
"unsupported fragment projection `{:?}`",
571-
elem,
572-
),
573-
}
585+
bx.dbg_var_addr(
586+
dbg_var,
587+
dbg_loc,
588+
base.llval,
589+
Size::ZERO,
590+
&[],
591+
fragment,
592+
);
574593
}
575-
576-
let place = fragment.contents;
577-
let fragment = if fragment_layout.size == Size::ZERO {
578-
// Fragment is a ZST, so does not represent anything.
579-
continue;
580-
} else if fragment_layout.size == var_layout.size {
581-
// Fragment covers entire variable, so as far as
582-
// DWARF is concerned, it's not really a fragment.
583-
None
584-
} else {
585-
Some(fragment_start..fragment_start + fragment_layout.size)
586-
};
587-
588-
per_local[place.local].push(PerLocalVarDebugInfo {
589-
name: var.name,
590-
source_info: var.source_info,
591-
dbg_var,
592-
fragment,
593-
projection: place.projection,
594-
});
595594
}
596595
}
597596
}

compiler/rustc_const_eval/src/transform/validate.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@ use rustc_index::IndexVec;
66
use rustc_infer::traits::Reveal;
77
use rustc_middle::mir::interpret::Scalar;
88
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
9-
use rustc_middle::mir::{
10-
traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
11-
MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
12-
ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
13-
Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo,
14-
VarDebugInfoContents, START_BLOCK,
15-
};
9+
use rustc_middle::mir::*;
1610
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
1711
use rustc_mir_dataflow::impls::MaybeStorageLive;
1812
use rustc_mir_dataflow::storage::always_storage_live_locals;
@@ -757,37 +751,37 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
757751
}
758752

759753
fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) {
760-
let check_place = |this: &mut Self, place: Place<'_>| {
761-
if place.projection.iter().any(|p| !p.can_use_in_debuginfo()) {
762-
this.fail(
754+
if let Some(box VarDebugInfoFragment { ty, ref projection }) = debuginfo.composite {
755+
if ty.is_union() || ty.is_enum() {
756+
self.fail(
763757
START_BLOCK.start_location(),
764-
format!("illegal place {:?} in debuginfo for {:?}", place, debuginfo.name),
758+
format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name),
765759
);
766760
}
767-
};
761+
if projection.is_empty() {
762+
self.fail(
763+
START_BLOCK.start_location(),
764+
format!("invalid empty projection in debuginfo for {:?}", debuginfo.name),
765+
);
766+
}
767+
if projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) {
768+
self.fail(
769+
START_BLOCK.start_location(),
770+
format!(
771+
"illegal projection {:?} in debuginfo for {:?}",
772+
projection, debuginfo.name
773+
),
774+
);
775+
}
776+
}
768777
match debuginfo.value {
769778
VarDebugInfoContents::Const(_) => {}
770779
VarDebugInfoContents::Place(place) => {
771-
check_place(self, place);
772-
}
773-
VarDebugInfoContents::Composite { ty, ref fragments } => {
774-
for f in fragments {
775-
check_place(self, f.contents);
776-
if ty.is_union() || ty.is_enum() {
777-
self.fail(
778-
START_BLOCK.start_location(),
779-
format!("invalid type {ty:?} for composite debuginfo"),
780-
);
781-
}
782-
if f.projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) {
783-
self.fail(
784-
START_BLOCK.start_location(),
785-
format!(
786-
"illegal projection {:?} in debuginfo for {:?}",
787-
f.projection, debuginfo.name
788-
),
789-
);
790-
}
780+
if place.projection.iter().any(|p| !p.can_use_in_debuginfo()) {
781+
self.fail(
782+
START_BLOCK.start_location(),
783+
format!("illegal place {:?} in debuginfo for {:?}", place, debuginfo.name),
784+
);
791785
}
792786
}
793787
}

0 commit comments

Comments
 (0)