Skip to content

Commit

Permalink
Name the upvars for closures and generators in debuginfo
Browse files Browse the repository at this point in the history
Previously, debuggers print closures as something like
```
y::main::closure-0 (0x7fffffffdd34, 0x7fffffffdd30)
```
The two pointers are actually references to two upvars.
It is not very obvious, especially for beginners.

It's because upvars don't have names before, as they are
packed into a tuple. This commit names the upvars, so we
can expect to see something like
```
y::main::closure-0 {_upvar_ref_mut__b: 0x[...], _upvar_ref__a: 0x[...]}
```
  • Loading branch information
lrh2000 committed Apr 30, 2021
1 parent 1995cd9 commit e65c460
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
59 changes: 58 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use rustc_fs_util::path_to_c_string;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::hir;
use rustc_middle::ich::NodeIdHashingMode;
use rustc_middle::mir::{self, Field, GeneratorLayout};
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
Expand Down Expand Up @@ -1285,14 +1286,70 @@ struct TupleMemberDescriptionFactory<'tcx> {

impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
// For closures and generators, we mangle the upvars' names to something like:
// - `_upvar__name`
// - `_upvar_ref__name`
// - `_upvar_ref_mut__name`
// The purpose is to make those names human-understandable. Otherwise, the end users may
// get confused when the debuggers just print some pointers for closures or generators.
let closure_def_id = match *self.ty.kind() {
ty::Generator(def_id, ..) => def_id.as_local(),
ty::Closure(def_id, ..) => def_id.as_local(),
_ => None,
};
let captures = match closure_def_id {
Some(local_def_id) => {
let typeck_results = cx.tcx.typeck(local_def_id);
let captures = typeck_results
.closure_min_captures_flattened(local_def_id.to_def_id())
.collect::<Vec<_>>();
Some(captures)
}
_ => None,
};
let format_name = |i| {
match &captures {
Some(ref captures) => {
let capture: &ty::CapturedPlace<'tcx> = captures[i];

let prefix = if cx.tcx.features().capture_disjoint_fields {
// FIXME:
// Here we may need more name mangling to reflect disjoint fields.
format!("_upvar{}_", i)
} else {
"_upvar_".to_string()
};

let adjust = match capture.info.capture_kind {
ty::UpvarCapture::ByValue(_) => "_",
ty::UpvarCapture::ByRef(borrow)
if borrow.kind == ty::BorrowKind::MutBorrow =>
{
"ref_mut__"
}
ty::UpvarCapture::ByRef(_) => "ref__",
};

let hir_id = match capture.place.base {
hir::place::PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
base => bug!("Expected an upvar, found {:?}", base),
};
let name = cx.tcx.hir().name(hir_id).as_str();

prefix + adjust + &name
}
None => format!("__{}", i),
}
};

let layout = cx.layout_of(self.ty);
self.component_types
.iter()
.enumerate()
.map(|(i, &component_type)| {
let (size, align) = cx.size_and_align_of(component_type);
MemberDescription {
name: format!("__{}", i),
name: format_name(i),
type_metadata: type_metadata(cx, component_type, self.span),
offset: layout.fields.offset(i),
size,
Expand Down
8 changes: 4 additions & 4 deletions src/test/debuginfo/generator-objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@

// gdb-command:run
// gdb-command:print b
// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...])
// gdb-check:$1 = generator_objects::main::generator-0::Unresumed{_upvar_ref_mut__a: 0x[...]}
// gdb-command:continue
// gdb-command:print b
// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]}
// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, _upvar_ref_mut__a: 0x[...]}
// gdb-command:continue
// gdb-command:print b
// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]}
// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, _upvar_ref_mut__a: 0x[...]}
// gdb-command:continue
// gdb-command:print b
// gdb-check:$4 = generator_objects::main::generator-0::Returned([...])
// gdb-check:$4 = generator_objects::main::generator-0::Returned{_upvar_ref_mut__a: [...]}

// === LLDB TESTS ==================================================================================

Expand Down
6 changes: 3 additions & 3 deletions src/test/debuginfo/issue-57822.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@
// gdb-command:run

// gdb-command:print g
// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1))
// gdb-check:$1 = issue_57822::main::closure-1 {_upvar__f: issue_57822::main::closure-0 {_upvar__x: 1}}

// gdb-command:print b
// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2))
// gdb-check:$2 = issue_57822::main::generator-3::Unresumed{_upvar__a: issue_57822::main::generator-2::Unresumed{_upvar__y: 2}}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print g
// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } }
// lldbg-check:(issue_57822::main::closure-1) $0 = { _upvar__f = { _upvar__x = 1 } }

// lldb-command:print b
// lldbg-check:(issue_57822::main::generator-3) $1 =
Expand Down

0 comments on commit e65c460

Please sign in to comment.