Skip to content

Commit e87a205

Browse files
committed
Auto merge of #56231 - eddyb:mir-debuginfo, r=oli-obk
rustc: move debug info from LocalDecl and UpvarDecl into a dedicated VarDebugInfo. This PR introduces a MIR "user variable" debuginfo system, which amounts to mapping a variable name, in some `SourceScope`, to a `Place`, so that: * each name can appear multiple times (e.g. due to macro hygiene), even in the same scope * each `Place` can appear multiple times (e.g. in the future from optimizations like NRVO, which collapse multiple MIR locals into one) * the `Place`s aren't limited to just locals, so they can describe the (right now quite ad-hoc) closure upvars and generator saved state fields, and can be properly transformed by optimizations (e.g. inlining - see `src/test/mir-opt/inline-closure-captures.rs`) The main motivation for this was that #48300 and further optimizations were blocked on being able to describe complex debuginfo transformations (see #48300 (comment)). <hr/> In the textual representation, the "user variable" debuginfo can be found in each scope, and consists of `debug NAME => PLACE;` "declarations", e.g. the MIR for `let x = ...; let y = ...; ...` is now: ```rust let _1: T; // in scope 0 at ... scope 1 { debug x => _1; // in scope 1 at ... let _2: T; // in scope 1 at ... scope 2 { debug y => _2; // in scope 2 at ... } } ``` For reference, this is how the information was represented before this PR: (notably, the scopes in which the variables are visible for debuginfo weren't even shown anywhere, making `scope 2` look pointless, and user variable names were part of MIR locals) ```rust let _1: T; // "x" in scope 0 at ... scope 1 { let _2: T; // "y" in scope 1 at ... scope 2 { } } ``` cc @nikomatsakis @michaelwoerister
2 parents 04e69e4 + 563ed27 commit e87a205

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+780
-480
lines changed

src/librustc/mir/mod.rs

+24-49
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,8 @@ pub struct Body<'tcx> {
141141
/// This is used for the "rust-call" ABI.
142142
pub spread_arg: Option<Local>,
143143

144-
/// Names and capture modes of all the closure upvars, assuming
145-
/// the first argument is either the closure or a reference to it.
146-
//
147-
// NOTE(eddyb) This is *strictly* a temporary hack for codegen
148-
// debuginfo generation, and will be removed at some point.
149-
// Do **NOT** use it for anything else; upvar information should not be
150-
// in the MIR, so please rely on local crate HIR or other side-channels.
151-
pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
144+
/// Debug information pertaining to user variables, including captures.
145+
pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
152146

153147
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
154148
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
@@ -170,11 +164,10 @@ impl<'tcx> Body<'tcx> {
170164
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
171165
source_scopes: IndexVec<SourceScope, SourceScopeData>,
172166
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
173-
yield_ty: Option<Ty<'tcx>>,
174167
local_decls: LocalDecls<'tcx>,
175168
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
176169
arg_count: usize,
177-
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
170+
var_debug_info: Vec<VarDebugInfo<'tcx>>,
178171
span: Span,
179172
control_flow_destroyed: Vec<(Span, String)>,
180173
) -> Self {
@@ -191,14 +184,14 @@ impl<'tcx> Body<'tcx> {
191184
basic_blocks,
192185
source_scopes,
193186
source_scope_local_data,
194-
yield_ty,
187+
yield_ty: None,
195188
generator_drop: None,
196189
generator_layout: None,
197190
local_decls,
198191
user_type_annotations,
199192
arg_count,
200-
__upvar_debuginfo_codegen_only_do_not_use,
201193
spread_arg: None,
194+
var_debug_info,
202195
span,
203196
cache: cache::Cache::new(),
204197
control_flow_destroyed,
@@ -280,7 +273,7 @@ impl<'tcx> Body<'tcx> {
280273
LocalKind::ReturnPointer
281274
} else if index < self.arg_count + 1 {
282275
LocalKind::Arg
283-
} else if self.local_decls[local].name.is_some() {
276+
} else if self.local_decls[local].is_user_variable() {
284277
LocalKind::Var
285278
} else {
286279
LocalKind::Temp
@@ -728,12 +721,6 @@ pub struct LocalDecl<'tcx> {
728721
// FIXME(matthewjasper) Don't store in this in `Body`
729722
pub user_ty: UserTypeProjections,
730723

731-
/// The name of the local, used in debuginfo and pretty-printing.
732-
///
733-
/// Note that function arguments can also have this set to `Some(_)`
734-
/// to generate better debuginfo.
735-
pub name: Option<Name>,
736-
737724
/// The *syntactic* (i.e., not visibility) source scope the local is defined
738725
/// in. If the local was defined in a let-statement, this
739726
/// is *within* the let-statement, rather than outside
@@ -785,9 +772,9 @@ pub struct LocalDecl<'tcx> {
785772
/// `drop(x)`, we want it to refer to `x: u32`.
786773
///
787774
/// To allow both uses to work, we need to have more than a single scope
788-
/// for a local. We have the `source_info.scope` represent the
789-
/// "syntactic" lint scope (with a variable being under its let
790-
/// block) while the `visibility_scope` represents the "local variable"
775+
/// for a local. We have the `source_info.scope` represent the "syntactic"
776+
/// lint scope (with a variable being under its let block) while the
777+
/// `var_debug_info.source_info.scope` represents the "local variable"
791778
/// scope (where the "rest" of a block is under all prior let-statements).
792779
///
793780
/// The end result looks like this:
@@ -806,18 +793,14 @@ pub struct LocalDecl<'tcx> {
806793
/// │ │
807794
/// │ │ │{ let y: u32 }
808795
/// │ │ │
809-
/// │ │ │← y.visibility_scope
796+
/// │ │ │← y.var_debug_info.source_info.scope
810797
/// │ │ │← `y + 2`
811798
/// │
812799
/// │ │{ let x: u32 }
813-
/// │ │← x.visibility_scope
800+
/// │ │← x.var_debug_info.source_info.scope
814801
/// │ │← `drop(x)` // This accesses `x: u32`.
815802
/// ```
816803
pub source_info: SourceInfo,
817-
818-
/// Source scope within which the local is visible (for debuginfo)
819-
/// (see `source_info` for more details).
820-
pub visibility_scope: SourceScope,
821804
}
822805

823806
/// Extra information about a local that's used for diagnostics.
@@ -955,9 +938,7 @@ impl<'tcx> LocalDecl<'tcx> {
955938
mutability,
956939
ty,
957940
user_ty: UserTypeProjections::none(),
958-
name: None,
959941
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
960-
visibility_scope: OUTERMOST_SOURCE_SCOPE,
961942
internal,
962943
local_info: LocalInfo::Other,
963944
is_block_tail: None,
@@ -974,22 +955,27 @@ impl<'tcx> LocalDecl<'tcx> {
974955
ty: return_ty,
975956
user_ty: UserTypeProjections::none(),
976957
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
977-
visibility_scope: OUTERMOST_SOURCE_SCOPE,
978958
internal: false,
979959
is_block_tail: None,
980-
name: None, // FIXME maybe we do want some name here?
981960
local_info: LocalInfo::Other,
982961
}
983962
}
984963
}
985964

986-
/// A closure capture, with its name and mode.
987-
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
988-
pub struct UpvarDebuginfo {
989-
pub debug_name: Name,
965+
/// Debug information pertaining to a user variable.
966+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
967+
pub struct VarDebugInfo<'tcx> {
968+
pub name: Name,
990969

991-
/// If true, the capture is behind a reference.
992-
pub by_ref: bool,
970+
/// Source info of the user variable, including the scope
971+
/// within which the variable is visible (to debuginfo)
972+
/// (see `LocalDecl`'s `source_info` field for more details).
973+
pub source_info: SourceInfo,
974+
975+
/// Where the data for this user variable is to be found.
976+
/// NOTE(eddyb) There's an unenforced invariant that this `Place` is
977+
/// based on a `Local`, not a `Static`, and contains no indexing.
978+
pub place: Place<'tcx>,
993979
}
994980

995981
///////////////////////////////////////////////////////////////////////////
@@ -2758,16 +2744,6 @@ pub struct GeneratorLayout<'tcx> {
27582744
/// have conflicts with each other are allowed to overlap in the computed
27592745
/// layout.
27602746
pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
2761-
2762-
/// The names and scopes of all the stored generator locals.
2763-
///
2764-
/// N.B., this is *strictly* a temporary hack for codegen
2765-
/// debuginfo generation, and will be removed at some point.
2766-
/// Do **NOT** use it for anything else, local information should not be
2767-
/// in the MIR, please rely on local crate HIR or other side-channels.
2768-
//
2769-
// FIXME(tmandry): see above.
2770-
pub __local_debuginfo_codegen_only_do_not_use: IndexVec<GeneratorSavedLocal, LocalDecl<'tcx>>,
27712747
}
27722748

27732749
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
@@ -2946,7 +2922,6 @@ CloneTypeFoldableAndLiftImpls! {
29462922
MirPhase,
29472923
Mutability,
29482924
SourceInfo,
2949-
UpvarDebuginfo,
29502925
FakeReadCause,
29512926
RetagKind,
29522927
SourceScope,

src/librustc/mir/visit.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ macro_rules! make_mir_visitor {
221221
self.super_local_decl(local, local_decl);
222222
}
223223

224+
fn visit_var_debug_info(&mut self,
225+
var_debug_info: & $($mutability)* VarDebugInfo<'tcx>) {
226+
self.super_var_debug_info(var_debug_info);
227+
}
228+
224229
fn visit_local(&mut self,
225230
_local: & $($mutability)? Local,
226231
_context: PlaceContext,
@@ -279,6 +284,10 @@ macro_rules! make_mir_visitor {
279284
);
280285
}
281286

287+
for var_debug_info in &$($mutability)? body.var_debug_info {
288+
self.visit_var_debug_info(var_debug_info);
289+
}
290+
282291
self.visit_span(&$($mutability)? body.span);
283292
}
284293

@@ -687,9 +696,7 @@ macro_rules! make_mir_visitor {
687696
mutability: _,
688697
ty,
689698
user_ty,
690-
name: _,
691699
source_info,
692-
visibility_scope,
693700
internal: _,
694701
local_info: _,
695702
is_block_tail: _,
@@ -703,7 +710,23 @@ macro_rules! make_mir_visitor {
703710
self.visit_user_type_projection(user_ty);
704711
}
705712
self.visit_source_info(source_info);
706-
self.visit_source_scope(visibility_scope);
713+
}
714+
715+
fn super_var_debug_info(&mut self,
716+
var_debug_info: & $($mutability)? VarDebugInfo<'tcx>) {
717+
let VarDebugInfo {
718+
name: _,
719+
source_info,
720+
place,
721+
} = var_debug_info;
722+
723+
self.visit_source_info(source_info);
724+
let location = START_BLOCK.start_location();
725+
self.visit_place(
726+
place,
727+
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
728+
location,
729+
);
707730
}
708731

709732
fn super_source_scope(&mut self,
@@ -1029,6 +1052,8 @@ pub enum NonUseContext {
10291052
StorageDead,
10301053
/// User type annotation assertions for NLL.
10311054
AscribeUserTy,
1055+
/// The data of an user variable, for debug info.
1056+
VarDebugInfo,
10321057
}
10331058

10341059
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

src/librustc_codegen_llvm/debuginfo/create_scope_map.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@ pub fn compute_mir_scopes(
2323
) {
2424
// Find all the scopes with variables defined in them.
2525
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
26-
// FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo.
2726
// FIXME(eddyb) take into account that arguments always have debuginfo,
2827
// irrespective of their name (assuming full debuginfo is enabled).
29-
for var in mir.vars_iter() {
30-
let decl = &mir.local_decls[var];
31-
has_variables.insert(decl.visibility_scope);
28+
for var_debug_info in &mir.var_debug_info {
29+
has_variables.insert(var_debug_info.source_info.scope);
3230
}
3331

3432
// Instantiate all scopes.

0 commit comments

Comments
 (0)